commit 267ef714a7adf3fa7ffb95f3c47eaa6c8d76047b Author: Patrick Fic Date: Mon Dec 1 05:43:59 2025 -0800 Initial copy of shop partner app. diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000..25c23e9 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,65 @@ +version: 2.1 +orbs: + win: circleci/windows@5.1.0 +jobs: + partner-win-build: + executor: + name: win/default + parameters: + tenantID: + type: string + default: $AZURE_TENANT_ID + clientID: + type: string + default: $AZURE_CLIENT_ID + clientSecret: + type: string + default: $AZURE_CLIENT_SECRET + steps: + - checkout + - run: + name: Set up Node.js + command: | + nvm install 22 + nvm use 22 + - run: + name: Install Build Dependencies + command: | + choco install python visualstudio2022-workload-vctools -y + python -m pip install --upgrade pip setuptools wheel + + # look for existing cache and restore if found + - restore_cache: + key: bsp-win-deps-{{ checksum "package-lock.json" }} + # install dependencies + - run: + name: install dependencies + command: npm install + - run: + name: Install NPM Packages + command: npm install + - save_cache: + key: bsp-win-deps-{{ checksum "package-lock.json" }} + paths: + - node_modules + - run: + name: Build Electron App for Windows + environment: + AZURE_TENANT_ID: << parameters.tenantID >> + AZURE_CLIENT_ID: << parameters.clientID >> + AZURE_CLIENT_SECRET: << parameters.clientSecret >> + command: | + $env:AZURE_TENANT_ID = << parameters.tenantID >> + $env:AZURE_CLIENT_ID = << parameters.clientID >> + $env:AZURE_CLIENT_SECRET = << parameters.clientSecret >> + npm run build:win + # - store_artifacts: + # path: .\dist + +workflows: + deploy_and_build: + jobs: + - partner-win-build: + filters: + branches: + only: main diff --git a/.env.imex b/.env.imex new file mode 100644 index 0000000..3bd811e --- /dev/null +++ b/.env.imex @@ -0,0 +1,14 @@ +VITE_COMPANY=IMEX + +# Fire Base Config +VITE_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"} +VITE_FIREBASE_CONFIG_TEST={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"} +# GraphQL Config +VITE_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql +VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql +# Front End URL +VITE_FE_URL=https://imex.online +VITE_FE_URL_TEST=https://test.imex.online +# API Url +VITE_API_URL="https://api.imex.online" +VITE_API_TEST_URL="https://test.api.imex.online" \ No newline at end of file diff --git a/.env.local b/.env.local new file mode 100644 index 0000000..26fdcdd --- /dev/null +++ b/.env.local @@ -0,0 +1,9 @@ +VITE_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"} +VITE_GRAPHQL_ENDPOINT=https://db.dev.imex.online/v1/graphql +VITE_FIREBASE_CONFIG_TEST={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"} +VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.bodyshop.app/v1/graphql +VITE_COMPANY=IMEX +VITE_FE_URL=https://imex.online +VITE_FE_URL_TEST=https://test.imex.online +VITE_API_URL="http://localhost:4000" +VITE_API_TEST_URL="https://api.test.imex.online" \ No newline at end of file diff --git a/.env.rome b/.env.rome new file mode 100644 index 0000000..9695644 --- /dev/null +++ b/.env.rome @@ -0,0 +1,14 @@ +VITE_COMPANY=ROME + +# Fire Base Config +VITE_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"} +VITE_FIREBASE_CONFIG_TEST={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"} +# GraphQL Config +VITE_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql +VITE_GRAPHQL_ENDPOINT_TEST=https://db.test.romeonline.io/v1/graphql +# Front End URL +VITE_FE_URL=https://romeonline.io +VITE_FE_URL_TEST=https://test.romeonline.io +# API Url +VITE_API_URL="https://api.romeonline.io" +VITE_API_TEST_URL="https://test.api.romeonline.io" \ No newline at end of file diff --git a/.eslintcache b/.eslintcache new file mode 100644 index 0000000..906c156 --- /dev/null +++ b/.eslintcache @@ -0,0 +1 @@ +[{"/Users/pfic/Development/bodyshop-desktop/electron.vite.config.ts":"1","/Users/pfic/Development/bodyshop-desktop/eslint.config.mjs":"2","/Users/pfic/Development/bodyshop-desktop/playwright.config.ts":"3","/Users/pfic/Development/bodyshop-desktop/src/env.d.ts":"4","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad1.interface.ts":"5","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad1.ts":"6","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad2.interface.ts":"7","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad2.ts":"8","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-env.interface.ts":"9","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-env.ts":"10","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-lin.interface.ts":"11","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-lin.ts":"12","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfh.interface.ts":"13","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfh.ts":"14","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfl.interface.ts":"15","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfl.ts":"16","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfm.interface.ts":"17","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfm.ts":"18","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfo.interface.ts":"19","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfo.ts":"20","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfp.interface.ts":"21","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfp.ts":"22","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pft.interface.ts":"23","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pft.ts":"24","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-stl.interface.ts":"25","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-stl.ts":"26","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ttl.interface.ts":"27","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ttl.ts":"28","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-veh.interface.ts":"29","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-veh.ts":"30","/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decoder.ts":"31","/Users/pfic/Development/bodyshop-desktop/src/main/graphql/graphql-client.ts":"32","/Users/pfic/Development/bodyshop-desktop/src/main/graphql/queries.ts":"33","/Users/pfic/Development/bodyshop-desktop/src/main/http-server/http-server.ts":"34","/Users/pfic/Development/bodyshop-desktop/src/main/index.test.ts":"35","/Users/pfic/Development/bodyshop-desktop/src/main/index.ts":"36","/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainConfig.ts":"37","/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainHandler.settings.ts":"38","/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainHandler.user.ts":"39","/Users/pfic/Development/bodyshop-desktop/src/main/quickbooks-desktop/quickbooks-desktop.ts":"40","/Users/pfic/Development/bodyshop-desktop/src/main/store/store.ts":"41","/Users/pfic/Development/bodyshop-desktop/src/main/watcher/watcher.ts":"42","/Users/pfic/Development/bodyshop-desktop/src/preload/index.d.ts":"43","/Users/pfic/Development/bodyshop-desktop/src/preload/index.ts":"44","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/App.test.tsx":"45","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/App.tsx":"46","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx":"47","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Home/Home.tsx":"48","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/NavigationHeader/Navigationheader.tsx":"49","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx":"50","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.Watcher.tsx":"51","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.tsx":"52","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/SignInForm/SignInForm.tsx":"53","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx":"54","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Versions.tsx":"55","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/env.d.ts":"56","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/main.tsx":"57","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/app.slice.ts":"58","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/redux-store.ts":"59","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/reduxHooks.ts":"60","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/firebase.ts":"61","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/graphql.client.ts":"62","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/i18n.ts":"63","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/ipcRendererHandler.ts":"64","/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/notificationContext.tsx":"65","/Users/pfic/Development/bodyshop-desktop/src/util/deepLowercaseKeys.ts":"66","/Users/pfic/Development/bodyshop-desktop/src/util/errorTypeCheck.ts":"67","/Users/pfic/Development/bodyshop-desktop/src/util/typeCaster.ts":"68","/Users/pfic/Development/bodyshop-desktop/src/util/ynBoolConverter.ts":"69","/Users/pfic/Development/bodyshop-desktop/tests/example.spec.ts":"70","/Users/pfic/Development/bodyshop-desktop/tests-examples/demo-todo-app.spec.ts":"71"},{"size":430,"mtime":1742582232364,"results":"72","hashOfConfig":"73"},{"size":936,"mtime":1743202578379,"results":"74","hashOfConfig":"75"},{"size":2216,"mtime":1742581802577,"results":"76","hashOfConfig":"73"},{"size":221,"mtime":1742958175049,"results":"77","hashOfConfig":"73"},{"size":3006,"mtime":1742495803806,"results":"78","hashOfConfig":"73"},{"size":5556,"mtime":1743199570778,"results":"79","hashOfConfig":"73"},{"size":688,"mtime":1742338351014,"results":"80","hashOfConfig":"73"},{"size":3568,"mtime":1742851209900,"results":"81","hashOfConfig":"73"},{"size":98,"mtime":1742497834906,"results":"82","hashOfConfig":"73"},{"size":1329,"mtime":1742583313017,"results":"83","hashOfConfig":"73"},{"size":1140,"mtime":1742498039950,"results":"84","hashOfConfig":"73"},{"size":2705,"mtime":1742582232493,"results":"85","hashOfConfig":"73"},{"size":332,"mtime":1742336706602,"results":"86","hashOfConfig":"73"},{"size":2325,"mtime":1743199570779,"results":"87","hashOfConfig":"73"},{"size":1240,"mtime":1743199570779,"results":"88","hashOfConfig":"73"},{"size":2800,"mtime":1743199570779,"results":"89","hashOfConfig":"73"},{"size":1083,"mtime":1743199570780,"results":"90","hashOfConfig":"73"},{"size":4138,"mtime":1743199570780,"results":"91","hashOfConfig":"73"},{"size":695,"mtime":1742498131759,"results":"92","hashOfConfig":"73"},{"size":1938,"mtime":1742582232519,"results":"93","hashOfConfig":"73"},{"size":785,"mtime":1742498261855,"results":"94","hashOfConfig":"73"},{"size":2100,"mtime":1742582232524,"results":"95","hashOfConfig":"73"},{"size":3107,"mtime":1742498285145,"results":"96","hashOfConfig":"73"},{"size":3746,"mtime":1742582232531,"results":"97","hashOfConfig":"73"},{"size":480,"mtime":1742500616037,"results":"98","hashOfConfig":"73"},{"size":1741,"mtime":1742581802583,"results":"99","hashOfConfig":"73"},{"size":462,"mtime":1742416439977,"results":"100","hashOfConfig":"73"},{"size":1622,"mtime":1743199570781,"results":"101","hashOfConfig":"73"},{"size":1411,"mtime":1742578892546,"results":"102","hashOfConfig":"73"},{"size":3626,"mtime":1742595022375,"results":"103","hashOfConfig":"73"},{"size":9046,"mtime":1742597347205,"results":"104","hashOfConfig":"73"},{"size":1452,"mtime":1742582232554,"results":"105","hashOfConfig":"73"},{"size":3129,"mtime":1743199890064,"results":"106","hashOfConfig":"73"},{"size":3975,"mtime":1743200083808,"results":"107","hashOfConfig":"73"},{"size":671,"mtime":1742416546806,"results":"108","hashOfConfig":"73"},{"size":10320,"mtime":1743199570781,"results":"109","hashOfConfig":"73"},{"size":3373,"mtime":1743011140630,"results":"110","hashOfConfig":"73"},{"size":2288,"mtime":1743200361944,"results":"111","hashOfConfig":"73"},{"size":1237,"mtime":1742582232584,"results":"112","hashOfConfig":"73"},{"size":3585,"mtime":1743200370900,"results":"113","hashOfConfig":"73"},{"size":763,"mtime":1743102312968,"results":"114","hashOfConfig":"73"},{"size":4187,"mtime":1743016812427,"results":"115","hashOfConfig":"73"},{"size":147,"mtime":1742582232592,"results":"116","hashOfConfig":"73"},{"size":650,"mtime":1742582232594,"results":"117","hashOfConfig":"73"},{"size":2392,"mtime":1742582232611,"results":"118","hashOfConfig":"73"},{"size":2649,"mtime":1743199570782,"results":"119","hashOfConfig":"73"},{"size":640,"mtime":1743202618799,"results":"120","hashOfConfig":"73"},{"size":113,"mtime":1743114210441,"results":"121","hashOfConfig":"73"},{"size":1478,"mtime":1743112808532,"results":"122","hashOfConfig":"73"},{"size":1768,"mtime":1743114060198,"results":"123","hashOfConfig":"73"},{"size":3530,"mtime":1743112857952,"results":"124","hashOfConfig":"73"},{"size":393,"mtime":1743114291178,"results":"125","hashOfConfig":"73"},{"size":2148,"mtime":1743202185075,"results":"126","hashOfConfig":"73"},{"size":2136,"mtime":1742939043464,"results":"127","hashOfConfig":"73"},{"size":426,"mtime":1742582232638,"results":"128","hashOfConfig":"73"},{"size":38,"mtime":1741730195788,"results":"129","hashOfConfig":"73"},{"size":287,"mtime":1742582232641,"results":"130","hashOfConfig":"73"},{"size":3454,"mtime":1742962471553,"results":"131","hashOfConfig":"73"},{"size":592,"mtime":1742581802590,"results":"132","hashOfConfig":"73"},{"size":571,"mtime":1742572949268,"results":"133","hashOfConfig":"73"},{"size":335,"mtime":1742416846745,"results":"134","hashOfConfig":"73"},{"size":543,"mtime":1743199570782,"results":"135","hashOfConfig":"73"},{"size":366,"mtime":1742581802590,"results":"136","hashOfConfig":"73"},{"size":2067,"mtime":1743201539992,"results":"137","hashOfConfig":"73"},{"size":1450,"mtime":1743201366133,"results":"138","hashOfConfig":"73"},{"size":900,"mtime":1742582232655,"results":"139","hashOfConfig":"73"},{"size":534,"mtime":1742581802591,"results":"140","hashOfConfig":"73"},{"size":2000,"mtime":1743201056618,"results":"141","hashOfConfig":"73"},{"size":304,"mtime":1742420206955,"results":"142","hashOfConfig":"73"},{"size":592,"mtime":1742582232682,"results":"143","hashOfConfig":"73"},{"size":15991,"mtime":1742582232680,"results":"144","hashOfConfig":"73"},{"filePath":"145","messages":"146","suppressedMessages":"147","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"a0cq8m",{"filePath":"148","messages":"149","suppressedMessages":"150","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1mckiga",{"filePath":"151","messages":"152","suppressedMessages":"153","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"154","messages":"155","suppressedMessages":"156","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"157","messages":"158","suppressedMessages":"159","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"160","messages":"161","suppressedMessages":"162","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"163","messages":"164","suppressedMessages":"165","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"166","messages":"167","suppressedMessages":"168","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"169","messages":"170","suppressedMessages":"171","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"172","messages":"173","suppressedMessages":"174","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"175","messages":"176","suppressedMessages":"177","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"178","messages":"179","suppressedMessages":"180","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"181","messages":"182","suppressedMessages":"183","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"184","messages":"185","suppressedMessages":"186","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"187","messages":"188","suppressedMessages":"189","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"190","messages":"191","suppressedMessages":"192","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"193","messages":"194","suppressedMessages":"195","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"196","messages":"197","suppressedMessages":"198","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"199","messages":"200","suppressedMessages":"201","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"202","messages":"203","suppressedMessages":"204","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"205","messages":"206","suppressedMessages":"207","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"208","messages":"209","suppressedMessages":"210","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"211","messages":"212","suppressedMessages":"213","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"214","messages":"215","suppressedMessages":"216","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"217","messages":"218","suppressedMessages":"219","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"220","messages":"221","suppressedMessages":"222","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"223","messages":"224","suppressedMessages":"225","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"226","messages":"227","suppressedMessages":"228","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"229","messages":"230","suppressedMessages":"231","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"232","messages":"233","suppressedMessages":"234","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"235","messages":"236","suppressedMessages":"237","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"238","messages":"239","suppressedMessages":"240","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"241","messages":"242","suppressedMessages":"243","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"244","messages":"245","suppressedMessages":"246","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"247","messages":"248","suppressedMessages":"249","errorCount":1,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"250","messages":"251","suppressedMessages":"252","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"253","messages":"254","suppressedMessages":"255","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"256","messages":"257","suppressedMessages":"258","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"259","messages":"260","suppressedMessages":"261","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"262","messages":"263","suppressedMessages":"264","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"265","messages":"266","suppressedMessages":"267","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"268","messages":"269","suppressedMessages":"270","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"271","messages":"272","suppressedMessages":"273","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"274","messages":"275","suppressedMessages":"276","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"277","messages":"278","suppressedMessages":"279","errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"280","messages":"281","suppressedMessages":"282","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"283","messages":"284","suppressedMessages":"285","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"286","messages":"287","suppressedMessages":"288","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"289","messages":"290","suppressedMessages":"291","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"292","messages":"293","suppressedMessages":"294","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"295","messages":"296","suppressedMessages":"297","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"298","messages":"299","suppressedMessages":"300","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"301","messages":"302","suppressedMessages":"303","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"304","messages":"305","suppressedMessages":"306","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"307","messages":"308","suppressedMessages":"309","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"310","messages":"311","suppressedMessages":"312","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"313","messages":"314","suppressedMessages":"315","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"316","messages":"317","suppressedMessages":"318","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"319","messages":"320","suppressedMessages":"321","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"322","messages":"323","suppressedMessages":"324","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"325","messages":"326","suppressedMessages":"327","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"328","messages":"329","suppressedMessages":"330","errorCount":2,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},{"filePath":"331","messages":"332","suppressedMessages":"333","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"334","messages":"335","suppressedMessages":"336","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"337","messages":"338","suppressedMessages":"339","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"340","messages":"341","suppressedMessages":"342","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"343","messages":"344","suppressedMessages":"345","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"346","messages":"347","suppressedMessages":"348","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"349","messages":"350","suppressedMessages":"351","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"352","messages":"353","suppressedMessages":"354","errorCount":0,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"355","messages":"356","suppressedMessages":"357","errorCount":6,"fatalErrorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"/Users/pfic/Development/bodyshop-desktop/electron.vite.config.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/eslint.config.mjs",[],[],"/Users/pfic/Development/bodyshop-desktop/playwright.config.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/env.d.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad1.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad1.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad2.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ad2.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-env.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-env.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-lin.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-lin.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfh.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfh.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfl.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfl.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfm.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfm.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfo.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfo.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfp.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pfp.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pft.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-pft.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-stl.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-stl.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ttl.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-ttl.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-veh.interface.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decode-veh.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/decoder/decoder.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/graphql/graphql-client.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/graphql/queries.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/http-server/http-server.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/index.test.ts",["358"],[],"/Users/pfic/Development/bodyshop-desktop/src/main/index.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainConfig.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainHandler.settings.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/ipc/ipcMainHandler.user.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/quickbooks-desktop/quickbooks-desktop.ts",[],["359","360"],"/Users/pfic/Development/bodyshop-desktop/src/main/store/store.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/main/watcher/watcher.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/preload/index.d.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/preload/index.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/App.test.tsx",["361","362"],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/App.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx",[],["363","364","365"],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Home/Home.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/NavigationHeader/Navigationheader.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.WatchedPaths.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.Watcher.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Settings/Settings.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/SignInForm/SignInForm.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/components/Versions.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/env.d.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/main.tsx",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/app.slice.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/redux-store.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/redux/reduxHooks.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/firebase.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/graphql.client.ts",["366","367"],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/i18n.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/ipcRendererHandler.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/renderer/src/util/notificationContext.tsx",[],["368","369","370"],"/Users/pfic/Development/bodyshop-desktop/src/util/deepLowercaseKeys.ts",[],["371","372","373"],"/Users/pfic/Development/bodyshop-desktop/src/util/errorTypeCheck.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/src/util/typeCaster.ts",[],["374","375","376","377","378","379","380","381","382"],"/Users/pfic/Development/bodyshop-desktop/src/util/ynBoolConverter.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/tests/example.spec.ts",[],[],"/Users/pfic/Development/bodyshop-desktop/tests-examples/demo-todo-app.spec.ts",["383","384","385","386","387","388"],[],{"ruleId":"389","severity":2,"message":"390","line":16,"column":9,"nodeType":null,"messageId":"391","endLine":16,"endColumn":15},{"ruleId":"392","severity":2,"message":"393","line":9,"column":12,"nodeType":"394","messageId":"395","endLine":9,"endColumn":15,"suggestions":"396","suppressions":"397"},{"ruleId":"398","severity":2,"message":"399","line":13,"column":11,"nodeType":"400","messageId":"401","endLine":13,"endColumn":27,"suppressions":"402"},{"ruleId":"403","severity":2,"message":"404","line":11,"column":3,"nodeType":"405","messageId":"406","endLine":11,"endColumn":11},{"ruleId":"403","severity":2,"message":"404","line":34,"column":23,"nodeType":"405","messageId":"406","endLine":34,"endColumn":25},{"ruleId":"407","severity":2,"message":"408","line":8,"column":3,"nodeType":"409","messageId":"410","endLine":8,"endColumn":8,"suppressions":"411"},{"ruleId":"407","severity":2,"message":"412","line":9,"column":3,"nodeType":"409","messageId":"410","endLine":9,"endColumn":21,"suppressions":"413"},{"ruleId":"407","severity":2,"message":"414","line":16,"column":24,"nodeType":"415","messageId":"410","endLine":16,"endColumn":31,"suppressions":"416"},{"ruleId":"389","severity":2,"message":"417","line":8,"column":7,"nodeType":null,"messageId":"391","endLine":8,"endColumn":15},{"ruleId":"392","severity":2,"message":"393","line":13,"column":28,"nodeType":"394","messageId":"395","endLine":13,"endColumn":31,"suggestions":"418"},{"ruleId":"419","severity":2,"message":"420","line":15,"column":14,"nodeType":"415","messageId":"421","endLine":15,"endColumn":29,"suppressions":"422"},{"ruleId":"403","severity":2,"message":"404","line":15,"column":35,"nodeType":"405","messageId":"406","endLine":15,"endColumn":37,"suppressions":"423"},{"ruleId":"407","severity":2,"message":"424","line":31,"column":3,"nodeType":"409","messageId":"410","endLine":31,"endColumn":11,"suppressions":"425"},{"ruleId":"392","severity":2,"message":"393","line":8,"column":32,"nodeType":"394","messageId":"395","endLine":8,"endColumn":35,"suggestions":"426","suppressions":"427"},{"ruleId":"392","severity":2,"message":"393","line":8,"column":42,"nodeType":"394","messageId":"395","endLine":8,"endColumn":45,"suggestions":"428","suppressions":"429"},{"ruleId":"392","severity":2,"message":"393","line":33,"column":26,"nodeType":"394","messageId":"395","endLine":33,"endColumn":29,"suggestions":"430","suppressions":"431"},{"ruleId":"392","severity":2,"message":"393","line":25,"column":22,"nodeType":"394","messageId":"395","endLine":25,"endColumn":25,"suggestions":"432","suppressions":"433"},{"ruleId":"392","severity":2,"message":"393","line":28,"column":22,"nodeType":"394","messageId":"395","endLine":28,"endColumn":25,"suggestions":"434","suppressions":"435"},{"ruleId":"392","severity":2,"message":"393","line":31,"column":22,"nodeType":"394","messageId":"395","endLine":31,"endColumn":25,"suggestions":"436","suppressions":"437"},{"ruleId":"392","severity":2,"message":"393","line":36,"column":26,"nodeType":"394","messageId":"395","endLine":36,"endColumn":29,"suggestions":"438","suppressions":"439"},{"ruleId":"392","severity":2,"message":"393","line":38,"column":26,"nodeType":"394","messageId":"395","endLine":38,"endColumn":29,"suggestions":"440","suppressions":"441"},{"ruleId":"392","severity":2,"message":"393","line":44,"column":24,"nodeType":"394","messageId":"395","endLine":44,"endColumn":27,"suggestions":"442","suppressions":"443"},{"ruleId":"392","severity":2,"message":"393","line":48,"column":26,"nodeType":"394","messageId":"395","endLine":48,"endColumn":29,"suggestions":"444","suppressions":"445"},{"ruleId":"392","severity":2,"message":"393","line":50,"column":26,"nodeType":"394","messageId":"395","endLine":50,"endColumn":29,"suggestions":"446","suppressions":"447"},{"ruleId":"392","severity":2,"message":"393","line":53,"column":24,"nodeType":"394","messageId":"395","endLine":53,"endColumn":27,"suggestions":"448","suppressions":"449"},{"ruleId":"403","severity":2,"message":"404","line":454,"column":1,"nodeType":"450","messageId":"406","endLine":454,"endColumn":34},{"ruleId":"403","severity":2,"message":"404","line":464,"column":1,"nodeType":"450","messageId":"406","endLine":464,"endColumn":48},{"ruleId":"403","severity":2,"message":"404","line":470,"column":1,"nodeType":"450","messageId":"406","endLine":470,"endColumn":57},{"ruleId":"392","severity":2,"message":"393","line":477,"column":16,"nodeType":"394","messageId":"395","endLine":477,"endColumn":19,"suggestions":"451"},{"ruleId":"403","severity":2,"message":"404","line":483,"column":1,"nodeType":"450","messageId":"406","endLine":483,"endColumn":40},{"ruleId":"392","severity":2,"message":"393","line":486,"column":19,"nodeType":"394","messageId":"395","endLine":486,"endColumn":22,"suggestions":"452"},"@typescript-eslint/no-unused-vars","'window' is assigned a value but never used.","unusedVar","@typescript-eslint/no-explicit-any","Unexpected any. Specify a different type.","TSAnyKeyword","unexpectedAny",["453","454"],["455"],"@typescript-eslint/no-require-imports","A `require()` style import is forbidden.","CallExpression","noRequireImports",["456"],"@typescript-eslint/explicit-function-return-type","Missing return type on function.","ArrowFunctionExpression","missingReturnType","react/prop-types","'error' is missing in props validation","Property","missingPropType",["457"],"'resetErrorBoundary' is missing in props validation",["458"],"'error.message' is missing in props validation","Identifier",["459"],"'httpLink' is assigned a value but never used.",["460","461"],"react-refresh/only-export-components","Fast refresh only works when a file only exports components. Use a new file to share constants or functions between components.","namedExport",["462"],["463"],"'children' is missing in props validation",["464"],["465","466"],["467"],["468","469"],["470"],["471","472"],["473"],["474","475"],["476"],["477","478"],["479"],["480","481"],["482"],["483","484"],["485"],["486","487"],["488"],["489","490"],["491"],["492","493"],["494"],["495","496"],["497"],["498","499"],["500"],"FunctionDeclaration",["501","502"],["503","504"],{"messageId":"505","fix":"506","desc":"507"},{"messageId":"508","fix":"509","desc":"510"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"513","desc":"507"},{"messageId":"508","fix":"514","desc":"510"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"515","desc":"507"},{"messageId":"508","fix":"516","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"517","desc":"507"},{"messageId":"508","fix":"518","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"519","desc":"507"},{"messageId":"508","fix":"520","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"521","desc":"507"},{"messageId":"508","fix":"522","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"523","desc":"507"},{"messageId":"508","fix":"524","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"525","desc":"507"},{"messageId":"508","fix":"526","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"527","desc":"507"},{"messageId":"508","fix":"528","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"529","desc":"507"},{"messageId":"508","fix":"530","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"531","desc":"507"},{"messageId":"508","fix":"532","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"533","desc":"507"},{"messageId":"508","fix":"534","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"535","desc":"507"},{"messageId":"508","fix":"536","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"537","desc":"507"},{"messageId":"508","fix":"538","desc":"510"},{"kind":"511","justification":"512"},{"messageId":"505","fix":"539","desc":"507"},{"messageId":"508","fix":"540","desc":"510"},{"messageId":"505","fix":"541","desc":"507"},{"messageId":"508","fix":"542","desc":"510"},"suggestUnknown",{"range":"543","text":"544"},"Use `unknown` instead, this will force you to explicitly, and safely assert the type is correct.","suggestNever",{"range":"545","text":"546"},"Use `never` instead, this is useful when instantiating generic type parameters that you don't need to know the type of.","directive","",{"range":"547","text":"544"},{"range":"548","text":"546"},{"range":"549","text":"544"},{"range":"550","text":"546"},{"range":"551","text":"544"},{"range":"552","text":"546"},{"range":"553","text":"544"},{"range":"554","text":"546"},{"range":"555","text":"544"},{"range":"556","text":"546"},{"range":"557","text":"544"},{"range":"558","text":"546"},{"range":"559","text":"544"},{"range":"560","text":"546"},{"range":"561","text":"544"},{"range":"562","text":"546"},{"range":"563","text":"544"},{"range":"564","text":"546"},{"range":"565","text":"544"},{"range":"566","text":"546"},{"range":"567","text":"544"},{"range":"568","text":"546"},{"range":"569","text":"544"},{"range":"570","text":"546"},{"range":"571","text":"544"},{"range":"572","text":"546"},{"range":"573","text":"544"},{"range":"574","text":"546"},{"range":"575","text":"544"},{"range":"576","text":"546"},[269,272],"unknown",[269,272],"never",[233,236],[233,236],[249,252],[249,252],[259,262],[259,262],[848,851],[848,851],[955,958],[955,958],[1043,1046],[1043,1046],[1132,1135],[1132,1135],[1295,1298],[1295,1298],[1381,1384],[1381,1384],[1523,1526],[1523,1526],[1692,1695],[1692,1695],[1794,1797],[1794,1797],[1871,1874],[1871,1874],[15682,15685],[15682,15685],[15936,15939],[15936,15939]] \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d288d6b --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +node_modules +dist +out +.DS_Store +*.log* +/logs + +# Playwright +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ + + +# Build Files +macbuild.sh +deploy.ps1 +# Sentry Config File +.env.sentry-build-plugin diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/bodyshop-desktop.iml b/.idea/bodyshop-desktop.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/bodyshop-desktop.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..03d9549 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..d23208f --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/material_theme_project_new.xml b/.idea/material_theme_project_new.xml new file mode 100644 index 0000000..4647599 --- /dev/null +++ b/.idea/material_theme_project_new.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..82d3dd5 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/prettier.xml b/.idea/prettier.xml new file mode 100644 index 0000000..b0c1c68 --- /dev/null +++ b/.idea/prettier.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..8450bfb --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,65 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Main Process", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" + }, + "runtimeArgs": ["--sourcemap"], + "env": { + "REMOTE_DEBUGGING_PORT": "9222" + }, + "experimentalNetworking": "off" + }, + { + "name": "Debug Renderer Process", + "port": 9222, + "request": "attach", + "type": "chrome", + "webRoot": "${workspaceFolder}/src/renderer", + "timeout": 60000, + "presentation": { + "hidden": true + } + }, + { + "name": "Debug Main Process w/ Hot Reloading", + "type": "node", + "request": "launch", + "cwd": "${workspaceRoot}", + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite", + "windows": { + "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron-vite.cmd" + }, + "runtimeArgs": ["--sourcemap", "--watch"], + "env": { + "REMOTE_DEBUGGING_PORT": "9222" + } + } + ], + + "compounds": [ + { + "name": "Debug All", + "configurations": ["Debug Main Process", "Debug Renderer Process"], + "presentation": { + "order": 1 + } + }, + { + "name": "Debug All (Hot Reload)", + "configurations": [ + "Debug Main Process w/ Hot Reloading", + "Debug Renderer Process" + ], + "presentation": { + "order": 1 + } + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ff05bd0 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "prettier.trailingComma": "all", + "editor.formatOnSave": true +} diff --git a/PartnerCert.p12 b/PartnerCert.p12 new file mode 100644 index 0000000..c341d6f Binary files /dev/null and b/PartnerCert.p12 differ diff --git a/README.md b/README.md new file mode 100644 index 0000000..602d47b --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Shop Partner +An electron app that is replacing the existing Bodyshop Partner that was a C#/WPF Application. + +The purpose of this application is to: +* Parse EMS files, and upload them to the IO back end. +* Receive requests for EMS file parsing + +The following functionality will be coming: +* Interact with QuickBooks desktop (Windows Only) +* Paint scale integrations +* Parts Price Changes for CCC + +Toggling between the Production and Test servers can be done by pressing `CTRL/CMD + SHIFT + T`, and then going to the application menu, and enabling test. The application will restart automatically. + +## Dev and Build Notes +Unlike the main app, the dev mode will only connect to ImEX Online test data. + +Building the app will require specifying the company to build for. Those details are captured in their respective ENV and YAML files. diff --git a/_reference/ems/MPI_1/3698420.ENV b/_reference/ems/MPI_1/3698420.ENV new file mode 100644 index 0000000..392749f Binary files /dev/null and b/_reference/ems/MPI_1/3698420.ENV differ diff --git a/_reference/ems/MPI_1/3698420.LIN b/_reference/ems/MPI_1/3698420.LIN new file mode 100644 index 0000000..de703f2 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.LIN differ diff --git a/_reference/ems/MPI_1/3698420.PFH b/_reference/ems/MPI_1/3698420.PFH new file mode 100644 index 0000000..787eacc Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFH differ diff --git a/_reference/ems/MPI_1/3698420.PFL b/_reference/ems/MPI_1/3698420.PFL new file mode 100644 index 0000000..d97d93c Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFL differ diff --git a/_reference/ems/MPI_1/3698420.PFM b/_reference/ems/MPI_1/3698420.PFM new file mode 100644 index 0000000..5aaa152 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFM differ diff --git a/_reference/ems/MPI_1/3698420.PFO b/_reference/ems/MPI_1/3698420.PFO new file mode 100644 index 0000000..c8a3ace Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFO differ diff --git a/_reference/ems/MPI_1/3698420.PFP b/_reference/ems/MPI_1/3698420.PFP new file mode 100644 index 0000000..42bff61 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFP differ diff --git a/_reference/ems/MPI_1/3698420.PFT b/_reference/ems/MPI_1/3698420.PFT new file mode 100644 index 0000000..bcbb9c1 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.PFT differ diff --git a/_reference/ems/MPI_1/3698420.STL b/_reference/ems/MPI_1/3698420.STL new file mode 100644 index 0000000..27f2d55 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.STL differ diff --git a/_reference/ems/MPI_1/3698420.TTL b/_reference/ems/MPI_1/3698420.TTL new file mode 100644 index 0000000..b392bb1 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.TTL differ diff --git a/_reference/ems/MPI_1/3698420.VEN b/_reference/ems/MPI_1/3698420.VEN new file mode 100644 index 0000000..bd56765 Binary files /dev/null and b/_reference/ems/MPI_1/3698420.VEN differ diff --git a/_reference/ems/MPI_1/3698420A.AD1 b/_reference/ems/MPI_1/3698420A.AD1 new file mode 100644 index 0000000..2333b75 Binary files /dev/null and b/_reference/ems/MPI_1/3698420A.AD1 differ diff --git a/_reference/ems/MPI_1/3698420A.dbt b/_reference/ems/MPI_1/3698420A.dbt new file mode 100644 index 0000000..dd431fe Binary files /dev/null and b/_reference/ems/MPI_1/3698420A.dbt differ diff --git a/_reference/ems/MPI_1/3698420B.AD2 b/_reference/ems/MPI_1/3698420B.AD2 new file mode 100644 index 0000000..b606e0b Binary files /dev/null and b/_reference/ems/MPI_1/3698420B.AD2 differ diff --git a/_reference/ems/MPI_1/3698420B.dbt b/_reference/ems/MPI_1/3698420B.dbt new file mode 100644 index 0000000..b2b5bc2 Binary files /dev/null and b/_reference/ems/MPI_1/3698420B.dbt differ diff --git a/_reference/ems/MPI_1/3698420V.VEH b/_reference/ems/MPI_1/3698420V.VEH new file mode 100644 index 0000000..37bb1cc Binary files /dev/null and b/_reference/ems/MPI_1/3698420V.VEH differ diff --git a/_reference/ems/MPI_1/3698420V.dbt b/_reference/ems/MPI_1/3698420V.dbt new file mode 100644 index 0000000..e367c32 Binary files /dev/null and b/_reference/ems/MPI_1/3698420V.dbt differ diff --git a/build/com.convenient-brands.bodyshop-desktop.keepalive.plist b/build/com.convenient-brands.bodyshop-desktop.keepalive.plist new file mode 100644 index 0000000..e4e8635 --- /dev/null +++ b/build/com.convenient-brands.bodyshop-desktop.keepalive.plist @@ -0,0 +1,17 @@ + + + + + Label + com.convenientbrands.bodyshop-desktop.keepalive + ProgramArguments + + Shop Partner Keep Alive + imexmedia://keep-alive + + RunAtLoad + + StartInterval + ${KEEP_ALIVE_INTERVAL_SECONDS} + + \ No newline at end of file diff --git a/build/entitlements.mac.plist b/build/entitlements.mac.plist new file mode 100644 index 0000000..38c887b --- /dev/null +++ b/build/entitlements.mac.plist @@ -0,0 +1,12 @@ + + + + + com.apple.security.cs.allow-jit + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.cs.allow-dyld-environment-variables + + + diff --git a/build/icon.png b/build/icon.png new file mode 100644 index 0000000..dd32a22 Binary files /dev/null and b/build/icon.png differ diff --git a/deploy/set-artifact-name.js b/deploy/set-artifact-name.js new file mode 100644 index 0000000..d99d8f7 --- /dev/null +++ b/deploy/set-artifact-name.js @@ -0,0 +1,53 @@ +#!/usr/bin/env node +// Cross-platform script to set artifact naming based on version + +const fs = require('fs'); +const path = require('path'); +const { spawn } = require('child_process'); + +// Read the package.json to get the version +const packageJsonPath = path.join(__dirname, '..', 'package.json'); +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); +const version = packageJson.version; + +console.log(`Current version: ${version}`); + +// Determine the artifact suffix based on the version +let artifactSuffix = ''; + +if (version.includes('alpha')) { + artifactSuffix = `alpha-${version}-`; + console.log(`Detected alpha version, setting suffix to: ${artifactSuffix}`); +} else if (version.includes('beta')) { + artifactSuffix = `beta-${version}-`; + console.log(`Detected beta version, setting suffix to: ${artifactSuffix}`); +} else { + artifactSuffix = ''; + console.log('Detected release version, no suffix will be added'); +} + +// Set the environment variable for the current process +process.env.ARTIFACT_SUFFIX = artifactSuffix; + +console.log(`ARTIFACT_SUFFIX set to: '${artifactSuffix}'`); + +// If arguments are passed, execute the remaining command with the environment variable set +if (process.argv.length > 2) { + const command = process.argv[2]; + const args = process.argv.slice(3); + + console.log(`Executing: ${command} ${args.join(' ')}`); + + const child = spawn(command, args, { + stdio: 'inherit', + env: { ...process.env, ARTIFACT_SUFFIX: artifactSuffix }, + shell: true + }); + + child.on('close', (code) => { + process.exit(code); + }); +} else { + // Just setting the environment variable + console.log('Environment variable set. Use this script with additional arguments to run commands with the variable set.'); +} diff --git a/deploy/set-artifact-name.ps1 b/deploy/set-artifact-name.ps1 new file mode 100644 index 0000000..f140e64 --- /dev/null +++ b/deploy/set-artifact-name.ps1 @@ -0,0 +1,38 @@ +# PowerShell script to set artifact naming based on version +param( + [string]$ConfigType = "imex" +) + +# Read the package.json to get the version +$packageJsonPath = Join-Path $PSScriptRoot "..\package.json" +$packageJson = Get-Content $packageJsonPath | ConvertFrom-Json +$version = $packageJson.version + +Write-Host "Current version: $version" + +# Determine the artifact suffix based on the version +$artifactSuffix = "" + +if ($version -match "alpha") { + $artifactSuffix = "alpha-${version}-" + Write-Host "Detected alpha version, setting suffix to: $artifactSuffix" +} +elseif ($version -match "beta") { + $artifactSuffix = "beta-${version}-" + Write-Host "Detected beta version, setting suffix to: $artifactSuffix" +} +else { + $artifactSuffix = "" + Write-Host "Detected release version, no suffix will be added" +} + +# Set the environment variable +$env:ARTIFACT_SUFFIX = $artifactSuffix + +# Export for the current session +[Environment]::SetEnvironmentVariable("ARTIFACT_SUFFIX", $artifactSuffix, "Process") + +Write-Host "ARTIFACT_SUFFIX set to: '$env:ARTIFACT_SUFFIX'" + +# Return the suffix for use in other scripts +return $artifactSuffix diff --git a/deploy/set-artifact-name.sh b/deploy/set-artifact-name.sh new file mode 100644 index 0000000..1c7925c --- /dev/null +++ b/deploy/set-artifact-name.sh @@ -0,0 +1,33 @@ +#!/bin/bash +# Bash script to set artifact naming based on version + +# Get the directory where this script is located +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Read the package.json to get the version +PACKAGE_JSON_PATH="$SCRIPT_DIR/../package.json" +VERSION=$(node -p "require('$PACKAGE_JSON_PATH').version") + +echo "Current version: $VERSION" + +# Determine the artifact suffix based on the version +ARTIFACT_SUFFIX="" + +if [[ $VERSION == *"alpha"* ]]; then + ARTIFACT_SUFFIX="alpha-${VERSION}-" + echo "Detected alpha version, setting suffix to: $ARTIFACT_SUFFIX" +elif [[ $VERSION == *"beta"* ]]; then + ARTIFACT_SUFFIX="beta-${VERSION}-" + echo "Detected beta version, setting suffix to: $ARTIFACT_SUFFIX" +else + ARTIFACT_SUFFIX="" + echo "Detected release version, no suffix will be added" +fi + +# Export the environment variable +export ARTIFACT_SUFFIX="$ARTIFACT_SUFFIX" + +echo "ARTIFACT_SUFFIX set to: '$ARTIFACT_SUFFIX'" + +# Also write to a temporary file for sourcing in other scripts +echo "export ARTIFACT_SUFFIX='$ARTIFACT_SUFFIX'" > "$SCRIPT_DIR/.artifact-suffix.env" diff --git a/deploy/test-artifact-naming-cross-platform.js b/deploy/test-artifact-naming-cross-platform.js new file mode 100644 index 0000000..f8c0ef4 --- /dev/null +++ b/deploy/test-artifact-naming-cross-platform.js @@ -0,0 +1,64 @@ +#!/usr/bin/env node +// Cross-platform test script to demonstrate artifact naming for different versions + +const fs = require('fs'); +const path = require('path'); + +console.log('=== Artifact Naming Test (Cross-Platform) ==='); +console.log(''); + +// Get current version +const packageJsonPath = path.join(__dirname, '..', 'package.json'); +const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); +const currentVersion = packageJson.version; + +console.log(`Current version: ${currentVersion}`); + +// Function to get artifact suffix +function getArtifactSuffix(version) { + if (version.includes('alpha')) { + return `alpha-${version}-`; + } else if (version.includes('beta')) { + return `beta-${version}-`; + } else { + return ''; + } +} + +// Test scenarios +const testVersions = [ + '1.0.5', // Release version + '1.0.5-alpha.2', // Alpha version + '1.0.5-beta.1', // Beta version + '2.0.0-alpha.1', // Another alpha + '1.5.0-beta.3' // Another beta +]; + +console.log('Test scenarios:'); +console.log('=================='); + +testVersions.forEach(version => { + const suffix = getArtifactSuffix(version); + + // Different artifact names for different platforms + const windowsArtifact = `imex-partner-${suffix}x64.exe`; + const macArtifact = `imex-partner-${suffix}x64.dmg`; + const linuxArtifact = `imex-partner-${suffix}x64.AppImage`; + + console.log(`Version: ${version}`); + console.log(` Suffix: '${suffix}'`); + console.log(` Windows: ${windowsArtifact}`); + console.log(` Mac: ${macArtifact}`); + console.log(` Linux: ${linuxArtifact}`); + console.log(''); +}); + +console.log('Current configuration will produce:'); +const currentSuffix = getArtifactSuffix(currentVersion); +console.log(` Windows: imex-partner-${currentSuffix}x64.exe`); +console.log(` Mac: imex-partner-${currentSuffix}x64.dmg`); +console.log(` Linux: imex-partner-${currentSuffix}x64.AppImage`); + +console.log(''); +console.log(`Platform detected: ${process.platform}`); +console.log(`Architecture: ${process.arch}`); diff --git a/deploy/test-artifact-naming.ps1 b/deploy/test-artifact-naming.ps1 new file mode 100644 index 0000000..ee99659 --- /dev/null +++ b/deploy/test-artifact-naming.ps1 @@ -0,0 +1,48 @@ +# Test script to demonstrate artifact naming for different versions +Write-Host "=== Artifact Naming Test ===" +Write-Host "" + +# Test current version +$packageJsonPath = ".\package.json" +$packageJson = Get-Content $packageJsonPath | ConvertFrom-Json +$currentVersion = $packageJson.version + +Write-Host "Current version: $currentVersion" + +# Function to get artifact suffix +function Get-ArtifactSuffix($version) { + if ($version -match "alpha") { + return "alpha-${version}-" + } elseif ($version -match "beta") { + return "beta-${version}-" + } else { + return "" + } +} + +# Test scenarios +$testVersions = @( + "1.0.5", # Release version + "1.0.5-alpha.2", # Alpha version + "1.0.5-beta.1", # Beta version + "2.0.0-alpha.1", # Another alpha + "1.5.0-beta.3" # Another beta +) + +Write-Host "Test scenarios:" +Write-Host "==================" + +foreach ($version in $testVersions) { + $suffix = Get-ArtifactSuffix $version + $artifactName = "imex-partner-${suffix}x64.exe" + + Write-Host "Version: $version" + Write-Host " Suffix: '$suffix'" + Write-Host " Result: $artifactName" + Write-Host "" +} + +Write-Host "Current configuration will produce:" +$currentSuffix = Get-ArtifactSuffix $currentVersion +$currentArtifact = "imex-partner-${currentSuffix}x64.exe" +Write-Host " $currentArtifact" diff --git a/deploy/test-artifact-naming.sh b/deploy/test-artifact-naming.sh new file mode 100644 index 0000000..82a7785 --- /dev/null +++ b/deploy/test-artifact-naming.sh @@ -0,0 +1,50 @@ +#!/bin/bash +# Test script to demonstrate artifact naming for different versions on Mac + +echo "=== Artifact Naming Test (Mac) ===" +echo "" + +# Get current version +PACKAGE_JSON_PATH="./package.json" +CURRENT_VERSION=$(node -p "require('$PACKAGE_JSON_PATH').version") + +echo "Current version: $CURRENT_VERSION" + +# Function to get artifact suffix +get_artifact_suffix() { + local version=$1 + if [[ $version == *"alpha"* ]]; then + echo "alpha-${version}-" + elif [[ $version == *"beta"* ]]; then + echo "beta-${version}-" + else + echo "" + fi +} + +# Test scenarios +TEST_VERSIONS=( + "1.0.5" # Release version + "1.0.5-alpha.2" # Alpha version + "1.0.5-beta.1" # Beta version + "2.0.0-alpha.1" # Another alpha + "1.5.0-beta.3" # Another beta +) + +echo "Test scenarios:" +echo "==================" + +for version in "${TEST_VERSIONS[@]}"; do + suffix=$(get_artifact_suffix "$version") + artifact_name="imex-partner-${suffix}x64.dmg" + + echo "Version: $version" + echo " Suffix: '$suffix'" + echo " Result: $artifact_name" + echo "" +done + +echo "Current configuration will produce:" +current_suffix=$(get_artifact_suffix "$CURRENT_VERSION") +current_artifact="imex-partner-${current_suffix}x64.dmg" +echo " $current_artifact" diff --git a/dev-app-update.yml b/dev-app-update.yml new file mode 100644 index 0000000..8d30efd --- /dev/null +++ b/dev-app-update.yml @@ -0,0 +1,3 @@ +provider: s3 +bucket: imex-partner +region: ca-central-1 diff --git a/electron-builder.imex.yml b/electron-builder.imex.yml new file mode 100644 index 0000000..57bbe37 --- /dev/null +++ b/electron-builder.imex.yml @@ -0,0 +1,60 @@ +appId: com.convenientbrands.bodyshop-desktop-imex +copyright: Convenient Brands, LLC. +productName: ImEX Shop Partner +generateUpdatesFilesForAllChannels: true + +directories: + buildResources: build +files: + - "!**/.vscode/*" + - "!**/.idea/*" + - "!src/*" + - "!electron.vite.config.{js,ts,mjs,cjs}" + - "!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}" + - "!{.env,.env.*,.npmrc,pnpm-lock.yaml}" + - "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}" +asarUnpack: + - resources/** +win: + executableName: ShopPartner + icon: resources/icon.png + azureSignOptions: + endpoint: https://eus.codesigning.azure.net + certificateProfileName: ImEXRPS + codeSigningAccountName: ImEX + publisherName: ImEX Systems Inc. +nsis: + artifactName: imex-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always + include: "scripts/installer.nsh" # Reference NSIS script from scripts directory +mac: + entitlementsInherit: build/entitlements.mac.plist + category: public.app-category.business + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + - CFBundleURLTypes: + - CFBundleTypeRole: Viewer # More specific role for protocol handling + CFBundleURLName: com.convenientbrands.bodyshop-desktop-imex + CFBundleURLSchemes: + - imexmedia + target: + - target: default + arch: + - arm64 + - target: default + arch: + - x64 +dmg: + artifactName: imex-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} +appImage: + artifactName: imex-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} +npmRebuild: false +publish: + provider: s3 + bucket: imex-partner + region: ca-central-1 diff --git a/electron-builder.rome.yml b/electron-builder.rome.yml new file mode 100644 index 0000000..ff0cbbb --- /dev/null +++ b/electron-builder.rome.yml @@ -0,0 +1,61 @@ +appId: com.convenientbrands.bodyshop-desktop-rome +copyright: Convenient Brands, LLC. +productName: Rome Shop Partner +generateUpdatesFilesForAllChannels: true + +directories: + buildResources: build +files: + - "!**/.vscode/*" + - "!**/.idea/*" + - "!src/*" + - "!electron.vite.config.{js,ts,mjs,cjs}" + - "!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}" + - "!{.env,.env.*,.npmrc,pnpm-lock.yaml}" + - "!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}" +asarUnpack: + - resources/** +win: + executableName: ShopPartner + icon: resources/ro-icon.png + azureSignOptions: + endpoint: https://eus.codesigning.azure.net + certificateProfileName: ImEXRPS + codeSigningAccountName: ImEX + publisherName: ImEX Systems Inc. +nsis: + artifactName: rome-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} + shortcutName: ${productName} + uninstallDisplayName: ${productName} + createDesktopShortcut: always + include: "scripts/installer.nsh" # Reference NSIS script from scripts directory +mac: + entitlementsInherit: build/entitlements.mac.plist + category: public.app-category.business + icon: resources/ro-icon.png + extendInfo: + - NSCameraUsageDescription: Application requests access to the device's camera. + - NSMicrophoneUsageDescription: Application requests access to the device's microphone. + - NSDocumentsFolderUsageDescription: Application requests access to the user's Documents folder. + - NSDownloadsFolderUsageDescription: Application requests access to the user's Downloads folder. + - CFBundleURLTypes: + - CFBundleTypeRole: Viewer # More specific role for protocol handling + CFBundleURLName: com.convenientbrands.bodyshop-desktop-rome + CFBundleURLSchemes: + - imexmedia + target: + - target: default + arch: + - arm64 + - target: default + arch: + - x64 +dmg: + artifactName: rome-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} +appImage: + artifactName: rome-partner-${env.ARTIFACT_SUFFIX}${arch}.${ext} +npmRebuild: false +publish: + provider: s3 + bucket: rome-partner + region: us-east-2 diff --git a/electron.vite.config.ts b/electron.vite.config.ts new file mode 100644 index 0000000..1b90d23 --- /dev/null +++ b/electron.vite.config.ts @@ -0,0 +1,55 @@ +import { sentryVitePlugin } from "@sentry/vite-plugin"; +import { resolve } from "path"; +import { defineConfig, externalizeDepsPlugin } from "electron-vite"; +import react from "@vitejs/plugin-react"; + +export default defineConfig({ + main: { + plugins: [ + externalizeDepsPlugin({ + exclude: ["electron-store"], + }), + sentryVitePlugin({ + org: "imex", + project: "imex-partner", + sourcemaps: { + filesToDeleteAfterUpload: ["**.js.map"], + }, + release: { + name: `bodyshop-desktop@${process.env.npm_package_version}`, + }, + }), + ], + build: { + sourcemap: true, + }, + }, + + preload: { + plugins: [externalizeDepsPlugin()], + }, + + renderer: { + resolve: { + alias: { + "@renderer": resolve("src/renderer/src"), + }, + }, + plugins: [ + react(), + sentryVitePlugin({ + org: "imex", + project: "imex-partner", + sourcemaps: { + filesToDeleteAfterUpload: ["**.js.map"], + }, + release: { + name: `bodyshop-desktop@${process.env.npm_package_version}`, + }, + }), + ], + build: { + sourcemap: true, + }, + }, +}); diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..47f4e17 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,39 @@ +import eslintConfigPrettier from "@electron-toolkit/eslint-config-prettier"; +import tseslint from "@electron-toolkit/eslint-config-ts"; +import eslintPluginReact from "eslint-plugin-react"; +import eslintPluginReactHooks from "eslint-plugin-react-hooks"; +import eslintPluginReactRefresh from "eslint-plugin-react-refresh"; + +export default tseslint.config( + {ignores: ["**/node_modules", "**/dist", "**/out"]}, + tseslint.configs.recommended, + eslintPluginReact.configs.flat.recommended, + eslintPluginReact.configs.flat["jsx-runtime"], + { + settings: { + react: { + version: "detect", + }, + }, + }, + { + files: ["**/*.{ts,tsx}"], + plugins: { + "react-hooks": eslintPluginReactHooks, + "react-refresh": eslintPluginReactRefresh, + }, + rules: { + ...eslintPluginReactHooks.configs.recommended.rules, + ...eslintPluginReactRefresh.configs.vite.rules, + }, + + }, + { + files: ["**/*.{js,mjs,ts,tsx,jsx,tsx}"], + rules: { + "prettier/prettier": ["error", {"endOfLine": "off"}] + } + }, + eslintConfigPrettier, +) + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b906b23 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,15902 @@ +{ + "name": "bodyshop-desktop", + "version": "1.0.8-beta.4", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "bodyshop-desktop", + "version": "1.0.8-beta.4", + "hasInstallScript": true, + "dependencies": { + "@apollo/client": "^3.13.6", + "@electron-toolkit/preload": "^3.0.2", + "@electron-toolkit/utils": "^4.0.0", + "@sentry/electron": "^7.2.0", + "@sentry/vite-plugin": "^4.5.0", + "axios": "^1.12.2", + "dayjs": "^1.11.18", + "electron-log": "^5.4.3", + "electron-updater": "^6.6.2", + "winax": "^3.6.2" + }, + "devDependencies": { + "@ant-design/v5-patch-for-react-19": "^1.0.3", + "@electron-toolkit/eslint-config-prettier": "^3.0.0", + "@electron-toolkit/eslint-config-ts": "^3.1.0", + "@electron-toolkit/tsconfig": "^2.0.0", + "@playwright/test": "^1.56.1", + "@reduxjs/toolkit": "^2.9.1", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/lodash": "^4.17.20", + "@types/node": "^24.9.1", + "@types/node-cron": "^3.0.11", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@types/xml2js": "^0.4.14", + "@vitejs/plugin-react": "^5.0.4", + "antd": "^5.27.6", + "archiver": "^7.0.1", + "chokidar": "^4.0.3", + "cors": "^2.8.5", + "cross-env": "^10.1.0", + "dbffile": "^1.12.0", + "electron": "^38.3.0", + "electron-builder": "^26.0.12", + "electron-store": "^11.0.2", + "electron-vite": "^4.0.1", + "eslint": "^9.38.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-refresh": "^0.4.24", + "express": "^5.1.0", + "firebase": "^12.4.0", + "graphql": "^16.11.0", + "graphql-request": "^7.3.1", + "i18next": "^25.6.0", + "lodash": "^4.17.21", + "node-cron": "^4.2.1", + "playwright": "^1.56.1", + "prettier": "^3.6.2", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-error-boundary": "^6.0.0", + "react-i18next": "^16.1.4", + "react-redux": "^9.2.0", + "react-router": "^7.9.4", + "redux-logger": "^3.0.6", + "typescript": "^5.9.3", + "vite": "7.1.11", + "xml2js": "^0.6.2", + "xmlbuilder2": "^4.0.0" + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.23.0.tgz", + "integrity": "sha512-7GAg9bD/iC9ikWatU9ym+P9ugJhi/WbsTWzcKN6T4gU0aehsprtke1UAaaSxxkjjmkJb3llet/rbUSLPgwlY4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/cssinjs-utils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs-utils/-/cssinjs-utils-1.1.3.tgz", + "integrity": "sha512-nOoQMLW1l+xR1Co8NFVYiP8pZp3VjIIzqV6D6ShYF2ljtdwWJn5WSsH+7kvCktXL/yhEtWURKOfH5Xz/gzlwsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/cssinjs": "^1.21.0", + "@babel/runtime": "^7.23.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.1.2.tgz", + "integrity": "sha512-EzlvzE6xQUBrZuuhSAFTdsr4P2bBBHGZwKFemEfq8gIGyIQCxalYfZW/T2ORbtQx5rU69o+WycP3exY/7T1hGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@ant-design/v5-patch-for-react-19": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@ant-design/v5-patch-for-react-19/-/v5-patch-for-react-19-1.0.3.tgz", + "integrity": "sha512-iWfZuSUl5kuhqLUw7jJXUQFMMkM7XpW7apmKzQBQHU0cpifYW4A79xIBt9YVO5IBajKpPG5UKP87Ft7Yrw1p/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.x" + }, + "peerDependencies": { + "antd": ">=5.22.6", + "react": ">=19.0.0", + "react-dom": ">=19.0.0" + } + }, + "node_modules/@apollo/client": { + "version": "3.13.6", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.6.tgz", + "integrity": "sha512-G6A8uNb13V/Tv4TJQOs5PnxuE5Rf5D2dMnBQcg9mng1Eo4YBecwFEJ0L022mraq/dLB0jD5tiAESOD2bTyJ6gg==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "@wry/caches": "^1.0.0", + "@wry/equality": "^0.5.6", + "@wry/trie": "^0.5.0", + "graphql-tag": "^2.12.6", + "hoist-non-react-statics": "^3.3.2", + "optimism": "^0.18.0", + "prop-types": "^15.7.2", + "rehackt": "^0.1.0", + "symbol-observable": "^4.0.0", + "ts-invariant": "^0.10.3", + "tslib": "^2.3.0", + "zen-observable-ts": "^1.2.5" + }, + "peerDependencies": { + "graphql": "^15.0.0 || ^16.0.0", + "graphql-ws": "^5.5.5 || ^6.0.3", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc", + "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" + }, + "peerDependenciesMeta": { + "graphql-ws": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + }, + "subscriptions-transport-ws": { + "optional": true + } + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", + "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", + "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", + "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.3", + "@babel/types": "^7.28.2", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", + "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.3", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.4", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@electron-toolkit/eslint-config-prettier": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/eslint-config-prettier/-/eslint-config-prettier-3.0.0.tgz", + "integrity": "sha512-YapmIOVkbYdHLuTa+ad1SAVtcqYL9A/SJsc7cxQokmhcwAwonGevNom37jBf9slXegcZ/Slh01I/JARG1yhNFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-config-prettier": "^10.0.1", + "eslint-plugin-prettier": "^5.2.3" + }, + "peerDependencies": { + "eslint": ">= 9.0.0", + "prettier": ">= 3.0.0" + } + }, + "node_modules/@electron-toolkit/eslint-config-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/eslint-config-ts/-/eslint-config-ts-3.1.0.tgz", + "integrity": "sha512-MowZQKd3yxXSDLack5QvjQwYHhpOJFoWBGBwJ/k+DCd7NUSendplECbQGFp86tPQYPUrPBPceR/hdsSAnaY5ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint/js": "^9.24.0", + "globals": "^16.0.0", + "typescript-eslint": "^8.29.1" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@electron-toolkit/preload": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@electron-toolkit/preload/-/preload-3.0.2.tgz", + "integrity": "sha512-TWWPToXd8qPRfSXwzf5KVhpXMfONaUuRAZJHsKthKgZR/+LqX1dZVSSClQ8OTAEduvLGdecljCsoT2jSshfoUg==", + "license": "MIT", + "peerDependencies": { + "electron": ">=13.0.0" + } + }, + "node_modules/@electron-toolkit/tsconfig": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/tsconfig/-/tsconfig-2.0.0.tgz", + "integrity": "sha512-AdPsP770WhW7b260h13SHMdmjEEHJL6xFtgi3jwgdsSQbJOkJLeNnnpZW9qxTPCvmRI6vmdzWz5K3gibFS6SNg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/node": "*" + } + }, + "node_modules/@electron-toolkit/utils": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@electron-toolkit/utils/-/utils-4.0.0.tgz", + "integrity": "sha512-qXSntwEzluSzKl4z5yFNBknmPGjPa3zFhE4mp9+h0cgokY5ornAeP+CJQDBhKsL1S58aOQfcwkD3NwLZCl+64g==", + "license": "MIT", + "peerDependencies": { + "electron": ">=13.0.0" + } + }, + "node_modules/@electron/asar": { + "version": "3.2.18", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.18.tgz", + "integrity": "sha512-2XyvMe3N3Nrs8cV39IKELRHTYUWFKrmqqSY1U+GMlc0jvqjIVnoxhNd2H4JolWQncbJi1DCvb5TNxZuI2fEjWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/@electron/asar/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@electron/asar/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@electron/asar/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@electron/fuses": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@electron/fuses/-/fuses-1.8.0.tgz", + "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.1", + "fs-extra": "^9.0.1", + "minimist": "^1.2.5" + }, + "bin": { + "electron-fuses": "dist/bin.js" + } + }, + "node_modules/@electron/fuses/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/fuses/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/fuses/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/node-gyp": { + "version": "10.2.0-electron.1", + "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", + "integrity": "sha512-4MSBTT8y07YUDqf69/vSh80Hh791epYqGtWHO3zSKhYFwQg+gx9wi1PqbqP6YqC4WMsNxZ5l9oDmnWdK5pfCKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^8.1.0", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^10.2.1", + "nopt": "^6.0.0", + "proc-log": "^2.0.1", + "semver": "^7.3.5", + "tar": "^6.2.1", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/@electron/node-gyp/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@electron/node-gyp/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/node-gyp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.5.0.tgz", + "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/notarize/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/notarize/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/notarize/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/osx-sign": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.3.1.tgz", + "integrity": "sha512-BAfviURMHpmb1Yb50YbCxnOY0wfwaLXH5KJ4+80zS0gUkzDX3ec23naTlEqKsN+PwYn+a1cCzM7BJ4Wcd3sGzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/@electron/osx-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/osx-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/rebuild": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@electron/rebuild/-/rebuild-3.7.0.tgz", + "integrity": "sha512-VW++CNSlZwMYP7MyXEbrKjpzEwhB5kDNbzGtiPEjwYysqyTCF+YbNJ210Dj3AjWsGSV4iEEwNkmJN9yGZmVvmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", + "@malept/cross-spawn-promise": "^2.0.0", + "chalk": "^4.0.0", + "debug": "^4.1.1", + "detect-libc": "^2.0.1", + "fs-extra": "^10.0.0", + "got": "^11.7.0", + "node-abi": "^3.45.0", + "node-api-version": "^0.2.0", + "ora": "^5.1.0", + "read-binary-file-arch": "^1.0.6", + "semver": "^7.3.5", + "tar": "^6.0.5", + "yargs": "^17.0.1" + }, + "bin": { + "electron-rebuild": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/@electron/rebuild/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/rebuild/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/rebuild/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@electron/rebuild/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-2.0.1.tgz", + "integrity": "sha512-fKpv9kg4SPmt+hY7SVBnIYULE9QJl8L3sCfcBsnqbJwwBwAeTLokJ9TRt9y7bK0JAzIW2y78TVVjvnQEms/yyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.7", + "@malept/cross-spawn-promise": "^2.0.0", + "debug": "^4.3.1", + "dir-compare": "^4.2.0", + "fs-extra": "^11.1.1", + "minimatch": "^9.0.3", + "plist": "^3.1.0" + }, + "engines": { + "node": ">=16.4" + } + }, + "node_modules/@electron/universal/node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/universal/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/universal/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@electron/windows-sign": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@electron/windows-sign/-/windows-sign-1.2.2.tgz", + "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "cross-dirname": "^0.1.0", + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "minimist": "^1.2.8", + "postject": "^1.0.0-alpha.6" + }, + "bin": { + "electron-windows-sign": "bin/electron-windows-sign.js" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/windows-sign/node_modules/fs-extra": { + "version": "11.3.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.2.tgz", + "integrity": "sha512-Xr9F6z6up6Ws+NjzMCZc6WXg2YFRlrLP9NQDO3VQrWrfiojdhS56TzueT88ze0uBdCTwEIhQ3ptnmKeWGFAe0A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/@electron/windows-sign/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/windows-sign/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@epic-web/invariant": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@epic-web/invariant/-/invariant-1.0.0.tgz", + "integrity": "sha512-lrTPqgvfFQtR/eY/qkIzp98OGdNJu0m5ji3q/nJI8v3SXkRKEnWiOxMmbvcSoAIzv/cGiuvRy57k4suKQSAdwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.11.tgz", + "integrity": "sha512-Xt1dOL13m8u0WE8iplx9Ibbm+hFAO0GsU2P34UNoDGvZYkY8ifSiy6Zuc1lYxfG7svWE2fzqCUmFp5HCn51gJg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.11.tgz", + "integrity": "sha512-uoa7dU+Dt3HYsethkJ1k6Z9YdcHjTrSb5NUy66ZfZaSV8hEYGD5ZHbEMXnqLFlbBflLsl89Zke7CAdDJ4JI+Gg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.11.tgz", + "integrity": "sha512-9slpyFBc4FPPz48+f6jyiXOx/Y4v34TUeDDXJpZqAWQn/08lKGeD8aDp9TMn9jDz2CiEuHwfhRmGBvpnd/PWIQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.11.tgz", + "integrity": "sha512-Sgiab4xBjPU1QoPEIqS3Xx+R2lezu0LKIEcYe6pftr56PqPygbB7+szVnzoShbx64MUupqoE0KyRlN7gezbl8g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.11.tgz", + "integrity": "sha512-VekY0PBCukppoQrycFxUqkCojnTQhdec0vevUL/EDOCnXd9LKWqD/bHwMPzigIJXPhC59Vd1WFIL57SKs2mg4w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.11.tgz", + "integrity": "sha512-+hfp3yfBalNEpTGp9loYgbknjR695HkqtY3d3/JjSRUyPg/xd6q+mQqIb5qdywnDxRZykIHs3axEqU6l1+oWEQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.11.tgz", + "integrity": "sha512-CmKjrnayyTJF2eVuO//uSjl/K3KsMIeYeyN7FyDBjsR3lnSJHaXlVoAK8DZa7lXWChbuOk7NjAc7ygAwrnPBhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.11.tgz", + "integrity": "sha512-Dyq+5oscTJvMaYPvW3x3FLpi2+gSZTCE/1ffdwuM6G1ARang/mb3jvjxs0mw6n3Lsw84ocfo9CrNMqc5lTfGOw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.11.tgz", + "integrity": "sha512-TBMv6B4kCfrGJ8cUPo7vd6NECZH/8hPpBHHlYI3qzoYFvWu2AdTvZNuU/7hsbKWqu/COU7NIK12dHAAqBLLXgw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.11.tgz", + "integrity": "sha512-Qr8AzcplUhGvdyUF08A1kHU3Vr2O88xxP0Tm8GcdVOUm25XYcMPp2YqSVHbLuXzYQMf9Bh/iKx7YPqECs6ffLA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.11.tgz", + "integrity": "sha512-TmnJg8BMGPehs5JKrCLqyWTVAvielc615jbkOirATQvWWB1NMXY77oLMzsUjRLa0+ngecEmDGqt5jiDC6bfvOw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.11.tgz", + "integrity": "sha512-DIGXL2+gvDaXlaq8xruNXUJdT5tF+SBbJQKbWy/0J7OhU8gOHOzKmGIlfTTl6nHaCOoipxQbuJi7O++ldrxgMw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.11.tgz", + "integrity": "sha512-Osx1nALUJu4pU43o9OyjSCXokFkFbyzjXb6VhGIJZQ5JZi8ylCQ9/LFagolPsHtgw6himDSyb5ETSfmp4rpiKQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.11.tgz", + "integrity": "sha512-nbLFgsQQEsBa8XSgSTSlrnBSrpoWh7ioFDUmwo158gIm5NNP+17IYmNWzaIzWmgCxq56vfr34xGkOcZ7jX6CPw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.11.tgz", + "integrity": "sha512-HfyAmqZi9uBAbgKYP1yGuI7tSREXwIb438q0nqvlpxAOs3XnZ8RsisRfmVsgV486NdjD7Mw2UrFSw51lzUk1ww==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.11.tgz", + "integrity": "sha512-HjLqVgSSYnVXRisyfmzsH6mXqyvj0SA7pG5g+9W7ESgwA70AXYNpfKBqh1KbTxmQVaYxpzA/SvlB9oclGPbApw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.11.tgz", + "integrity": "sha512-HSFAT4+WYjIhrHxKBwGmOOSpphjYkcswF449j6EjsjbinTZbp8PJtjsVK1XFJStdzXdy/jaddAep2FGY+wyFAQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.11.tgz", + "integrity": "sha512-hr9Oxj1Fa4r04dNpWr3P8QKVVsjQhqrMSUzZzf+LZcYjZNqhA3IAfPQdEh1FLVUJSiu6sgAwp3OmwBfbFgG2Xg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.11.tgz", + "integrity": "sha512-u7tKA+qbzBydyj0vgpu+5h5AeudxOAGncb8N6C9Kh1N4n7wU1Xw1JDApsRjpShRpXRQlJLb9wY28ELpwdPcZ7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.11.tgz", + "integrity": "sha512-Qq6YHhayieor3DxFOoYM1q0q1uMFYb7cSpLD2qzDSvK1NAvqFi8Xgivv0cFC6J+hWVw2teCYltyy9/m/14ryHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.11.tgz", + "integrity": "sha512-CN+7c++kkbrckTOz5hrehxWN7uIhFFlmS/hqziSFVWpAzpWrQoAG4chH+nN3Be+Kzv/uuo7zhX716x3Sn2Jduw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.11.tgz", + "integrity": "sha512-rOREuNIQgaiR+9QuNkbkxubbp8MSO9rONmwP5nKncnWJ9v5jQ4JxFnLu4zDSRPf3x4u+2VN4pM4RdyIzDty/wQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.11.tgz", + "integrity": "sha512-nq2xdYaWxyg9DcIyXkZhcYulC6pQ2FuCgem3LI92IwMgIZ69KHeY8T4Y88pcwoLIjbed8n36CyKoYRDygNSGhA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.11.tgz", + "integrity": "sha512-3XxECOWJq1qMZ3MN8srCJ/QfoLpL+VaxD/WfNRm1O3B4+AZ/BnLVgFbUV3eiRYDMXetciH16dwPbbHqwe1uU0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.11.tgz", + "integrity": "sha512-3ukss6gb9XZ8TlRyJlgLn17ecsK4NSQTmdIXRASVsiS2sQ6zPPZklNJT5GR5tE/MUarymmy8kCEf5xPCNCqVOA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.11.tgz", + "integrity": "sha512-D7Hpz6A2L4hzsRpPaCYkQnGOotdUpDzSGRIv9I+1ITdHROSFUWW95ZPZWQmGka1Fg7W3zFJowyn9WGwMJ0+KPA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-array/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", + "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@firebase/ai": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@firebase/ai/-/ai-2.4.0.tgz", + "integrity": "sha512-YilG6AJ/nYpCKtxZyvEzBRAQv5bU+2tBOKX4Ps0rNNSdxN39aT37kGhjATbk1kq1z5Lq7mkWglw/ajAF3lOWUg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/analytics": { + "version": "0.10.19", + "resolved": "https://registry.npmjs.org/@firebase/analytics/-/analytics-0.10.19.tgz", + "integrity": "sha512-3wU676fh60gaiVYQEEXsbGS4HbF2XsiBphyvvqDbtC1U4/dO4coshbYktcCHq+HFaGIK07iHOh4pME0hEq1fcg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/analytics-compat": { + "version": "0.2.25", + "resolved": "https://registry.npmjs.org/@firebase/analytics-compat/-/analytics-compat-0.2.25.tgz", + "integrity": "sha512-fdzoaG0BEKbqksRDhmf4JoyZf16Wosrl0Y7tbZtJyVDOOwziE0vrFjmZuTdviL0yhak+Nco6rMsUUbkbD+qb6Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/analytics": "0.10.19", + "@firebase/analytics-types": "0.8.3", + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/analytics-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/analytics-types/-/analytics-types-0.8.3.tgz", + "integrity": "sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/app": { + "version": "0.14.4", + "resolved": "https://registry.npmjs.org/@firebase/app/-/app-0.14.4.tgz", + "integrity": "sha512-pUxEGmR+uu21OG/icAovjlu1fcYJzyVhhT0rsCrn+zi+nHtrS43Bp9KPn9KGa4NMspCUE++nkyiqziuIvJdwzw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-check": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check/-/app-check-0.11.0.tgz", + "integrity": "sha512-XAvALQayUMBJo58U/rxW02IhsesaxxfWVmVkauZvGEz3vOAjMEQnzFlyblqkc2iAaO82uJ2ZVyZv9XzPfxjJ6w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/app-check-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/app-check-compat/-/app-check-compat-0.4.0.tgz", + "integrity": "sha512-UfK2Q8RJNjYM/8MFORltZRG9lJj11k0nW84rrffiKvcJxLf1jf6IEjCIkCamykHE73C6BwqhVfhIBs69GXQV0g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check": "0.11.0", + "@firebase/app-check-types": "0.5.3", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/app-check-interop-types": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz", + "integrity": "sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/app-check-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/app-check-types/-/app-check-types-0.5.3.tgz", + "integrity": "sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/app-compat": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/@firebase/app-compat/-/app-compat-0.5.4.tgz", + "integrity": "sha512-T7ifGmb+awJEcp542Ek4HtNfBxcBrnuk1ggUdqyFEdsXHdq7+wVlhvE6YukTL7NS8hIkEfL7TMAPx/uCNqt30g==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@firebase/app": "0.14.4", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/app-types": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/@firebase/app-types/-/app-types-0.9.3.tgz", + "integrity": "sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/@firebase/auth": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@firebase/auth/-/auth-1.11.0.tgz", + "integrity": "sha512-5j7+ua93X+IRcJ1oMDTClTo85l7Xe40WSkoJ+shzPrX7OISlVWLdE1mKC57PSD+/LfAbdhJmvKixINBw2ESK6w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x", + "@react-native-async-storage/async-storage": "^1.18.1" + }, + "peerDependenciesMeta": { + "@react-native-async-storage/async-storage": { + "optional": true + } + } + }, + "node_modules/@firebase/auth-compat": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-compat/-/auth-compat-0.6.0.tgz", + "integrity": "sha512-J0lGSxXlG/lYVi45wbpPhcWiWUMXevY4fvLZsN1GHh+po7TZVng+figdHBVhFheaiipU8HZyc7ljw1jNojM2nw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/auth": "1.11.0", + "@firebase/auth-types": "0.13.0", + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/auth-interop-types": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz", + "integrity": "sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/auth-types": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@firebase/auth-types/-/auth-types-0.13.0.tgz", + "integrity": "sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/component": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/component/-/component-0.7.0.tgz", + "integrity": "sha512-wR9En2A+WESUHexjmRHkqtaVH94WLNKt6rmeqZhSLBybg4Wyf0Umk04SZsS6sBq4102ZsDBFwoqMqJYj2IoDSg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/data-connect": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@firebase/data-connect/-/data-connect-0.3.11.tgz", + "integrity": "sha512-G258eLzAD6im9Bsw+Qm1Z+P4x0PGNQ45yeUuuqe5M9B1rn0RJvvsQCRHXgE52Z+n9+WX1OJd/crcuunvOGc7Vw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/database": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database/-/database-1.1.0.tgz", + "integrity": "sha512-gM6MJFae3pTyNLoc9VcJNuaUDej0ctdjn3cVtILo3D5lpp0dmUHHLFN/pUKe7ImyeB1KAvRlEYxvIHNF04Filg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "faye-websocket": "0.11.4", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/database-compat": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@firebase/database-compat/-/database-compat-2.1.0.tgz", + "integrity": "sha512-8nYc43RqxScsePVd1qe1xxvWNf0OBnbwHxmXJ7MHSuuTVYFO3eLyLW3PiCKJ9fHnmIz4p4LbieXwz+qtr9PZDg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/database": "1.1.0", + "@firebase/database-types": "1.0.16", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/database-types": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/@firebase/database-types/-/database-types-1.0.16.tgz", + "integrity": "sha512-xkQLQfU5De7+SPhEGAXFBnDryUWhhlFXelEg2YeZOQMCdoe7dL64DDAd77SQsR+6uoXIZY5MB4y/inCs4GTfcw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-types": "0.9.3", + "@firebase/util": "1.13.0" + } + }, + "node_modules/@firebase/firestore": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore/-/firestore-4.9.2.tgz", + "integrity": "sha512-iuA5+nVr/IV/Thm0Luoqf2mERUvK9g791FZpUJV1ZGXO6RL2/i/WFJUj5ZTVXy5pRjpWYO+ZzPcReNrlilmztA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "@firebase/webchannel-wrapper": "1.0.5", + "@grpc/grpc-js": "~1.9.0", + "@grpc/proto-loader": "^0.7.8", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/firestore-compat": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@firebase/firestore-compat/-/firestore-compat-0.4.2.tgz", + "integrity": "sha512-cy7ov6SpFBx+PHwFdOOjbI7kH00uNKmIFurAn560WiPCZXy9EMnil1SOG7VF4hHZKdenC+AHtL4r3fNpirpm0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/firestore": "4.9.2", + "@firebase/firestore-types": "3.0.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/firestore-types": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@firebase/firestore-types/-/firestore-types-3.0.3.tgz", + "integrity": "sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/functions": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/@firebase/functions/-/functions-0.13.1.tgz", + "integrity": "sha512-sUeWSb0rw5T+6wuV2o9XNmh9yHxjFI9zVGFnjFi+n7drTEWpl7ZTz1nROgGrSu472r+LAaj+2YaSicD4R8wfbw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/app-check-interop-types": "0.3.3", + "@firebase/auth-interop-types": "0.2.4", + "@firebase/component": "0.7.0", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/functions-compat": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@firebase/functions-compat/-/functions-compat-0.4.1.tgz", + "integrity": "sha512-AxxUBXKuPrWaVNQ8o1cG1GaCAtXT8a0eaTDfqgS5VsRYLAR0ALcfqDLwo/QyijZj1w8Qf8n3Qrfy/+Im245hOQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/functions": "0.13.1", + "@firebase/functions-types": "0.6.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/functions-types": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/@firebase/functions-types/-/functions-types-0.6.3.tgz", + "integrity": "sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/installations": { + "version": "0.6.19", + "resolved": "https://registry.npmjs.org/@firebase/installations/-/installations-0.6.19.tgz", + "integrity": "sha512-nGDmiwKLI1lerhwfwSHvMR9RZuIH5/8E3kgUWnVRqqL7kGVSktjLTWEMva7oh5yxQ3zXfIlIwJwMcaM5bK5j8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/installations-compat": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/@firebase/installations-compat/-/installations-compat-0.2.19.tgz", + "integrity": "sha512-khfzIY3EI5LePePo7vT19/VEIH1E3iYsHknI/6ek9T8QCozAZshWT9CjlwOzZrKvTHMeNcbpo/VSOSIWDSjWdQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/installations-types": "0.5.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/installations-types": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@firebase/installations-types/-/installations-types-0.5.3.tgz", + "integrity": "sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x" + } + }, + "node_modules/@firebase/logger": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/logger/-/logger-0.5.0.tgz", + "integrity": "sha512-cGskaAvkrnh42b3BA3doDWeBmuHFO/Mx5A83rbRDYakPjO9bJtRL3dX7javzc2Rr/JHZf4HlterTW2lUkfeN4g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/messaging": { + "version": "0.12.23", + "resolved": "https://registry.npmjs.org/@firebase/messaging/-/messaging-0.12.23.tgz", + "integrity": "sha512-cfuzv47XxqW4HH/OcR5rM+AlQd1xL/VhuaeW/wzMW1LFrsFcTn0GND/hak1vkQc2th8UisBcrkVcQAnOnKwYxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/messaging-interop-types": "0.2.3", + "@firebase/util": "1.13.0", + "idb": "7.1.1", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/messaging-compat": { + "version": "0.2.23", + "resolved": "https://registry.npmjs.org/@firebase/messaging-compat/-/messaging-compat-0.2.23.tgz", + "integrity": "sha512-SN857v/kBUvlQ9X/UjAqBoQ2FEaL1ZozpnmL1ByTe57iXkmnVVFm9KqAsTfmf+OEwWI4kJJe9NObtN/w22lUgg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/messaging": "0.12.23", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/messaging-interop-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz", + "integrity": "sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/performance": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/@firebase/performance/-/performance-0.7.9.tgz", + "integrity": "sha512-UzybENl1EdM2I1sjYm74xGt/0JzRnU/0VmfMAKo2LSpHJzaj77FCLZXmYQ4oOuE+Pxtt8Wy2BVJEENiZkaZAzQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0", + "web-vitals": "^4.2.4" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/performance-compat": { + "version": "0.2.22", + "resolved": "https://registry.npmjs.org/@firebase/performance-compat/-/performance-compat-0.2.22.tgz", + "integrity": "sha512-xLKxaSAl/FVi10wDX/CHIYEUP13jXUjinL+UaNXT9ByIvxII5Ne5150mx6IgM8G6Q3V+sPiw9C8/kygkyHUVxg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/performance": "0.7.9", + "@firebase/performance-types": "0.2.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/performance-types": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@firebase/performance-types/-/performance-types-0.2.3.tgz", + "integrity": "sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/remote-config": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config/-/remote-config-0.7.0.tgz", + "integrity": "sha512-dX95X6WlW7QlgNd7aaGdjAIZUiQkgWgNS+aKNu4Wv92H1T8Ue/NDUjZHd9xb8fHxLXIHNZeco9/qbZzr500MjQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/installations": "0.6.19", + "@firebase/logger": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/remote-config-compat": { + "version": "0.2.20", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-compat/-/remote-config-compat-0.2.20.tgz", + "integrity": "sha512-P/ULS9vU35EL9maG7xp66uljkZgcPMQOxLj3Zx2F289baTKSInE6+YIkgHEi1TwHoddC/AFePXPpshPlEFkbgg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/logger": "0.5.0", + "@firebase/remote-config": "0.7.0", + "@firebase/remote-config-types": "0.5.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/remote-config-types": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@firebase/remote-config-types/-/remote-config-types-0.5.0.tgz", + "integrity": "sha512-vI3bqLoF14L/GchtgayMiFpZJF+Ao3uR8WCde0XpYNkSokDpAKca2DxvcfeZv7lZUqkUwQPL2wD83d3vQ4vvrg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@firebase/storage": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@firebase/storage/-/storage-0.14.0.tgz", + "integrity": "sha512-xWWbb15o6/pWEw8H01UQ1dC5U3rf8QTAzOChYyCpafV6Xki7KVp3Yaw2nSklUwHEziSWE9KoZJS7iYeyqWnYFA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app": "0.x" + } + }, + "node_modules/@firebase/storage-compat": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@firebase/storage-compat/-/storage-compat-0.4.0.tgz", + "integrity": "sha512-vDzhgGczr1OfcOy285YAPur5pWDEvD67w4thyeCUh6Ys0izN9fNYtA1MJERmNBfqjqu0lg0FM5GLbw0Il21M+g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/component": "0.7.0", + "@firebase/storage": "0.14.0", + "@firebase/storage-types": "0.8.3", + "@firebase/util": "1.13.0", + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "@firebase/app-compat": "0.x" + } + }, + "node_modules/@firebase/storage-types": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@firebase/storage-types/-/storage-types-0.8.3.tgz", + "integrity": "sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg==", + "dev": true, + "license": "Apache-2.0", + "peerDependencies": { + "@firebase/app-types": "0.x", + "@firebase/util": "1.x" + } + }, + "node_modules/@firebase/util": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/@firebase/util/-/util-1.13.0.tgz", + "integrity": "sha512-0AZUyYUfpMNcztR5l09izHwXkZpghLgCUaAGjtMwXnCg3bj4ml5VgiwqOMOxJ+Nw4qN/zJAaOQBcJ7KGkWStqQ==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@firebase/webchannel-wrapper": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.5.tgz", + "integrity": "sha512-+uGNN7rkfn41HLO0vekTFhTxk61eKa8mTpRGLO0QSqlQdKvIoGAvLp3ppdVIWbTGYJWM6Kp0iN+PjMIOcnVqTw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@graphql-typed-document-node/core": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", + "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, + "node_modules/@grpc/grpc-js": { + "version": "1.9.15", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.9.15.tgz", + "integrity": "sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@grpc/proto-loader": "^0.7.8", + "@types/node": ">=12.12.47" + }, + "engines": { + "node": "^8.13.0 || >=10.10.0" + } + }, + "node_modules/@grpc/proto-loader": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz", + "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" + }, + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.2.tgz", + "integrity": "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", + "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@malept/flatpak-bundler/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/fs/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@oozcitak/dom": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-2.0.1.tgz", + "integrity": "sha512-Un5k8MKqGak1LQM/behcHylmGdRopBXZax19weVedEAIrOCRZooY+MvX4Ehcz0ftOEPgYZ7vjIm/+MokVBFO3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.1", + "@oozcitak/url": "^2.0.1", + "@oozcitak/util": "^9.0.2" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/infra": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-2.0.1.tgz", + "integrity": "sha512-TtjI+kducm0ExL3OTKglPLkAIQ3alq0Otbokml62haZESfQaL3ojLJxl7+UTBhWCkBBuCshzGEEYmX5MXo8WOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/util": "~9.0.2" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-2.0.1.tgz", + "integrity": "sha512-lLHUQUyYy86q+qbALr0TMVh+VQAYwNGbsxBx4LhfjvkNYG0hgAwWtq7ePebGs2nEhZmmIFl24ikuCpH2r5d3+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/infra": "^2.0.1", + "@oozcitak/util": "^9.0.2" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@oozcitak/util": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-9.0.4.tgz", + "integrity": "sha512-kmx1hRJlsvxiTCpK97off59LqSEOtkWOPe4rdfFL8TjZtihYSTVNObIfc86jtLngfnuIuuTRt+TUCgRS220RSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20.0" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.204.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.204.0.tgz", + "integrity": "sha512-DqxY8yoAaiBPivoJD4UtgrMS8gEmzZ5lnaxzPojzLVHBGqPxgWm4zcuvcUHZiqQ6kRX2Klel2r9y8cA2HAtqpw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-2.2.0.tgz", + "integrity": "sha512-qRkLWiUEZNAmYapZ7KGS5C4OmBLcP/H2foXeOEaowYCR0wi89fHejrfYfbuLVCMLp/dWZXKvQusdbUEZjERfwQ==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.2.0.tgz", + "integrity": "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.204.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.204.0.tgz", + "integrity": "sha512-vV5+WSxktzoMP8JoYWKeopChy6G3HKk4UQ2hESCRDUUTZqQ3+nM3u8noVG0LmNfRWwcFBnbZ71GKC7vaYYdJ1g==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@opentelemetry/api-logs": "0.204.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-amqplib": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-amqplib/-/instrumentation-amqplib-0.51.0.tgz", + "integrity": "sha512-XGmjYwjVRktD4agFnWBWQXo9SiYHKBxR6Ag3MLXwtLE4R99N3a08kGKM5SC1qOFKIELcQDGFEFT9ydXMH00Luw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-connect": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-connect/-/instrumentation-connect-0.48.0.tgz", + "integrity": "sha512-OMjc3SFL4pC16PeK+tDhwP7MRvDPalYCGSvGqUhX5rASkI2H0RuxZHOWElYeXkV0WP+70Gw6JHWac/2Zqwmhdw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/connect": "3.4.38" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-dataloader": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-dataloader/-/instrumentation-dataloader-0.22.0.tgz", + "integrity": "sha512-bXnTcwtngQsI1CvodFkTemrrRSQjAjZxqHVc+CJZTDnidT0T6wt3jkKhnsjU/Kkkc0lacr6VdRpCu2CUWa0OKw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-express": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-express/-/instrumentation-express-0.53.0.tgz", + "integrity": "sha512-r/PBafQmFYRjuxLYEHJ3ze1iBnP2GDA1nXOSS6E02KnYNZAVjj6WcDA1MSthtdAUUK0XnotHvvWM8/qz7DMO5A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-fs": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-fs/-/instrumentation-fs-0.24.0.tgz", + "integrity": "sha512-HjIxJ6CBRD770KNVaTdMXIv29Sjz4C1kPCCK5x1Ujpc6SNnLGPqUVyJYZ3LUhhnHAqdbrl83ogVWjCgeT4Q0yw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-generic-pool": { + "version": "0.48.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-generic-pool/-/instrumentation-generic-pool-0.48.0.tgz", + "integrity": "sha512-TLv/On8pufynNR+pUbpkyvuESVASZZKMlqCm4bBImTpXKTpqXaJJ3o/MUDeMlM91rpen+PEv2SeyOKcHCSlgag==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-graphql": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-graphql/-/instrumentation-graphql-0.52.0.tgz", + "integrity": "sha512-3fEJ8jOOMwopvldY16KuzHbRhPk8wSsOTSF0v2psmOCGewh6ad+ZbkTx/xyUK9rUdUMWAxRVU0tFpj4Wx1vkPA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-hapi": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-hapi/-/instrumentation-hapi-0.51.0.tgz", + "integrity": "sha512-qyf27DaFNL1Qhbo/da+04MSCw982B02FhuOS5/UF+PMhM61CcOiu7fPuXj8TvbqyReQuJFljXE6UirlvoT/62g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http": { + "version": "0.204.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-http/-/instrumentation-http-0.204.0.tgz", + "integrity": "sha512-1afJYyGRA4OmHTv0FfNTrTAzoEjPQUYgd+8ih/lX0LlZBnGio/O80vxA0lN3knsJPS7FiDrsDrWq25K7oAzbkw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.1.0", + "@opentelemetry/instrumentation": "0.204.0", + "@opentelemetry/semantic-conventions": "^1.29.0", + "forwarded-parse": "2.1.2" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-http/node_modules/@opentelemetry/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.1.0.tgz", + "integrity": "sha512-RMEtHsxJs/GiHHxYT58IY57UXAQTuUnZVco6ymDEqTNlJKTimM4qPUPVe8InNFyBjhHBEAx4k3Q8LtNayBsbUQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation-ioredis": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-ioredis/-/instrumentation-ioredis-0.52.0.tgz", + "integrity": "sha512-rUvlyZwI90HRQPYicxpDGhT8setMrlHKokCtBtZgYxQWRF5RBbG4q0pGtbZvd7kyseuHbFpA3I/5z7M8b/5ywg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/redis-common": "^0.38.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-kafkajs": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-kafkajs/-/instrumentation-kafkajs-0.14.0.tgz", + "integrity": "sha512-kbB5yXS47dTIdO/lfbbXlzhvHFturbux4EpP0+6H78Lk0Bn4QXiZQW7rmZY1xBCY16mNcCb8Yt0mhz85hTnSVA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.30.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-knex": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-knex/-/instrumentation-knex-0.49.0.tgz", + "integrity": "sha512-NKsRRT27fbIYL4Ix+BjjP8h4YveyKc+2gD6DMZbr5R5rUeDqfC8+DTfIt3c3ex3BIc5Vvek4rqHnN7q34ZetLQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.33.1" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-koa": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-koa/-/instrumentation-koa-0.52.0.tgz", + "integrity": "sha512-JJSBYLDx/mNSy8Ibi/uQixu2rH0bZODJa8/cz04hEhRaiZQoeJ5UrOhO/mS87IdgVsHrnBOsZ6vDu09znupyuA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-lru-memoizer": { + "version": "0.49.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-lru-memoizer/-/instrumentation-lru-memoizer-0.49.0.tgz", + "integrity": "sha512-ctXu+O/1HSadAxtjoEg2w307Z5iPyLOMM8IRNwjaKrIpNAthYGSOanChbk1kqY6zU5CrpkPHGdAT6jk8dXiMqw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongodb": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.57.0.tgz", + "integrity": "sha512-KD6Rg0KSHWDkik+qjIOWoksi1xqSpix8TSPfquIK1DTmd9OTFb5PHmMkzJe16TAPVEuElUW8gvgP59cacFcrMQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mongoose": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongoose/-/instrumentation-mongoose-0.51.0.tgz", + "integrity": "sha512-gwWaAlhhV2By7XcbyU3DOLMvzsgeaymwP/jktDC+/uPkCmgB61zurwqOQdeiRq9KAf22Y2dtE5ZLXxytJRbEVA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql": { + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql/-/instrumentation-mysql-0.50.0.tgz", + "integrity": "sha512-duKAvMRI3vq6u9JwzIipY9zHfikN20bX05sL7GjDeLKr2qV0LQ4ADtKST7KStdGcQ+MTN5wghWbbVdLgNcB3rA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/mysql": "2.15.27" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-mysql2": { + "version": "0.51.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mysql2/-/instrumentation-mysql2-0.51.0.tgz", + "integrity": "sha512-zT2Wg22Xn43RyfU3NOUmnFtb5zlDI0fKcijCj9AcK9zuLZ4ModgtLXOyBJSSfO+hsOCZSC1v/Fxwj+nZJFdzLQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@opentelemetry/sql-common": "^0.41.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-pg": { + "version": "0.57.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-pg/-/instrumentation-pg-0.57.0.tgz", + "integrity": "sha512-dWLGE+r5lBgm2A8SaaSYDE3OKJ/kwwy5WLyGyzor8PLhUL9VnJRiY6qhp4njwhnljiLtzeffRtG2Mf/YyWLeTw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.34.0", + "@opentelemetry/sql-common": "^0.41.0", + "@types/pg": "8.15.5", + "@types/pg-pool": "2.0.6" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-redis": { + "version": "0.53.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-redis/-/instrumentation-redis-0.53.0.tgz", + "integrity": "sha512-WUHV8fr+8yo5RmzyU7D5BIE1zwiaNQcTyZPwtxlfr7px6NYYx7IIpSihJK7WA60npWynfxxK1T67RAVF0Gdfjg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/redis-common": "^0.38.0", + "@opentelemetry/semantic-conventions": "^1.27.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-tedious": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-tedious/-/instrumentation-tedious-0.23.0.tgz", + "integrity": "sha512-3TMTk/9VtlRonVTaU4tCzbg4YqW+Iq/l5VnN2e5whP6JgEg/PKfrGbqQ+CxQWNLfLaQYIUgEZqAn5gk/inh1uQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/semantic-conventions": "^1.27.0", + "@types/tedious": "^4.0.14" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/instrumentation-undici": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-undici/-/instrumentation-undici-0.15.0.tgz", + "integrity": "sha512-sNFGA/iCDlVkNjzTzPRcudmI11vT/WAfAguRdZY9IspCw02N4WSC72zTuQhSMheh2a1gdeM9my1imnKRvEEvEg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0", + "@opentelemetry/instrumentation": "^0.204.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.7.0" + } + }, + "node_modules/@opentelemetry/redis-common": { + "version": "0.38.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/redis-common/-/redis-common-0.38.2.tgz", + "integrity": "sha512-1BCcU93iwSRZvDAgwUxC/DV4T/406SkMfxGqu5ojc3AvNI+I9GhV7v0J1HljsczuuhcnFLYqD5VmwVXfCGHzxA==", + "license": "Apache-2.0", + "engines": { + "node": "^18.19.0 || >=20.6.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.2.0.tgz", + "integrity": "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-2.2.0.tgz", + "integrity": "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw==", + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@opentelemetry/core": "2.2.0", + "@opentelemetry/resources": "2.2.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.37.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.37.0.tgz", + "integrity": "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA==", + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sql-common": { + "version": "0.41.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/sql-common/-/sql-common-0.41.2.tgz", + "integrity": "sha512-4mhWm3Z8z+i508zQJ7r6Xi7y4mmoJpdvH0fZPFRkWrdp5fq7hhZ2HhYokEOLkfqSMgPR4Z9EyB3DBkbKGOqZiQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "^2.0.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.0.tgz", + "integrity": "sha512-vsJDAkYR6qCPu+ioGScGiMYR7LvZYIXh/dlQeviqoTWNCVfKTLYD/LkNWH4Mxsv2a5vpIRc77FN5DnmK1eBggQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@playwright/test": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@prisma/instrumentation": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/@prisma/instrumentation/-/instrumentation-6.15.0.tgz", + "integrity": "sha512-6TXaH6OmDkMOQvOxwLZ8XS51hU2v4A3vmE2pSijCIiGRJYyNeMcL6nMHQMyYdZRD8wl7LF3Wzc+AMPMV/9Oo7A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/instrumentation": "^0.52.0 || ^0.53.0 || ^0.54.0 || ^0.55.0 || ^0.56.0 || ^0.57.0" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.8" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@prisma/instrumentation/node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@prisma/instrumentation/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@rc-component/async-validator": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@rc-component/async-validator/-/async-validator-5.0.4.tgz", + "integrity": "sha512-qgGdcVIF604M9EqjNF0hbUTz42bz/RDtxWdWuU5EQe3hi7M8ob54B6B35rOsvX5eSvIHIzT9iH1R3n+hk3CGfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.4" + }, + "engines": { + "node": ">=14.x" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-2.0.1.tgz", + "integrity": "sha512-WcZYwAThV/b2GISQ8F+7650r5ZZJ043E57aVBFkQ+kSY4C6wdofXgB0hBx+GPGpIU0Z81eETNoDUJMr7oy/P8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6", + "@babel/runtime": "^7.23.6", + "classnames": "^2.2.6", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.0.tgz", + "integrity": "sha512-jS4E7T9Li2GuYwI6PyiVXmxTiM6b07rlD9Ge8uGZSCz3WlzcG5ZK7g5bbuKNeZ9pgUuPK/5guV781ujdVpm4HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/qrcode": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rc-component/qrcode/-/qrcode-1.0.1.tgz", + "integrity": "sha512-g8eeeaMyFXVlq8cZUeaxCDhfIYjpao0l9cvm5gFwKXy/Vm1yDWV7h2sjH5jHYzdFedlVKBpATFB1VKMrHzwaWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "classnames": "^2.3.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.15.1.tgz", + "integrity": "sha512-Tr2t7J1DKZUpfJuDZWHxyxWpfmj8EZrqSgyMZ+BCdvKZ6r1UDsfU46M/iWAAFBy961Ssfom2kv5f3UcjIL2CmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-2.3.0.tgz", + "integrity": "sha512-iwaxZyzOuK0D7lS+0AQEtW52zUWxoGqTGkke3dRyb8pYiShmRpCjB/8TzPI4R6YySCH7Vm9BZj/31VPiiQTLBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.44.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.1.tgz", + "integrity": "sha512-sETJ3qO72y7L7WiR5K54UFLT3jRzAtqeBPVO15xC3bGA6kDqCH8m/v7BKCPH4czydXzz/1lPEGLvew7GjOO3Qw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^10.0.3", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-beta.38", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.38.tgz", + "integrity": "sha512-N/ICGKleNhA5nc9XXQG/kkKHJ7S55u0x0XUJbbkmdCnFuoRkM1Il12q9q0eX19+M7KKUEPw/daUPIRnxhcxAIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz", + "integrity": "sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz", + "integrity": "sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz", + "integrity": "sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz", + "integrity": "sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz", + "integrity": "sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz", + "integrity": "sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz", + "integrity": "sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz", + "integrity": "sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz", + "integrity": "sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz", + "integrity": "sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz", + "integrity": "sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz", + "integrity": "sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz", + "integrity": "sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz", + "integrity": "sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz", + "integrity": "sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz", + "integrity": "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz", + "integrity": "sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz", + "integrity": "sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz", + "integrity": "sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz", + "integrity": "sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz", + "integrity": "sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz", + "integrity": "sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@sentry-internal/browser-utils": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.17.0.tgz", + "integrity": "sha512-jXC7dtItZYNGP+K9Lo+3MWaWaGVI6uDIPGB9BAZkZntc/1lGfhMPm7Fo2qb1N1bUP0vOTJ2TmSUA8GNxyxgekQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/feedback": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.17.0.tgz", + "integrity": "sha512-KIIF/dDQqYENbx4vn6B0evy/qx1QtEZsSZRvXNX6tUm14CCyrZeDymBMyEzu8RQ5PeZXibbPEkz7xOXiG3q+eQ==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.17.0.tgz", + "integrity": "sha512-9kirOPp3wbf+TMyHmA8iStKAysklZPcrPlB0v2zh0qRj1zNFY0xAD2WSgxuCvD9rEo5qKhmAKcaT7Ujin64uSw==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.17.0", + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry-internal/replay-canvas": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.17.0.tgz", + "integrity": "sha512-GXKZIraXrboP03+XS+KwkkKVJO+cSlM0HrfjePSfFqiNbbnjRhOLekoLuDvvH/ZEXPUoUJD1We5IPBg+sZZQfQ==", + "license": "MIT", + "dependencies": { + "@sentry-internal/replay": "10.17.0", + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/babel-plugin-component-annotate": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-4.5.0.tgz", + "integrity": "sha512-9sn9tJFtNnhSitPXW8hTuteefGMBbnPFyDER8dz+2sgdvcdq7T99lEwprMf8gUv5JCiDKIvtLe20Sf/4KPAahA==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/browser": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.17.0.tgz", + "integrity": "sha512-X4OiGECzkp6tIyAKXB/9beBC2oX1xKOEkDo4v/phIKGPzrmQ4o55j2a6/V20jSfSN7w+kfZ56ILE71SzC9w1aQ==", + "license": "MIT", + "dependencies": { + "@sentry-internal/browser-utils": "10.17.0", + "@sentry-internal/feedback": "10.17.0", + "@sentry-internal/replay": "10.17.0", + "@sentry-internal/replay-canvas": "10.17.0", + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/bundler-plugin-core": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-4.5.0.tgz", + "integrity": "sha512-LTgYe7qGgAP0BpsyCTpjk756l6wZUv3MtCE+G0qzlpsQ2AljYe2bN4qjDy0bQrsPo0QzNQm+S6d0zogcJj/tqw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.5", + "@sentry/babel-plugin-component-annotate": "4.5.0", + "@sentry/cli": "^2.51.0", + "dotenv": "^16.3.1", + "find-up": "^5.0.0", + "glob": "^9.3.2", + "magic-string": "0.30.8", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sentry/bundler-plugin-core/node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry/cli": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.56.1.tgz", + "integrity": "sha512-VDAIg+gmjNtJS5VUZQMDSK9RaKC9hYQi3PoXpNa+owNfQNk60bCi8z8jkbWRcKbNGn3V51WqvrQAqLoNAdPc9w==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "https-proxy-agent": "^5.0.0", + "node-fetch": "^2.6.7", + "progress": "^2.0.3", + "proxy-from-env": "^1.1.0", + "which": "^2.0.2" + }, + "bin": { + "sentry-cli": "bin/sentry-cli" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@sentry/cli-darwin": "2.56.1", + "@sentry/cli-linux-arm": "2.56.1", + "@sentry/cli-linux-arm64": "2.56.1", + "@sentry/cli-linux-i686": "2.56.1", + "@sentry/cli-linux-x64": "2.56.1", + "@sentry/cli-win32-arm64": "2.56.1", + "@sentry/cli-win32-i686": "2.56.1", + "@sentry/cli-win32-x64": "2.56.1" + } + }, + "node_modules/@sentry/cli-darwin": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.56.1.tgz", + "integrity": "sha512-zfhT8MrvB5x/xRdIVGwg+sG0Cx3i0G6RH2zCrdQ/moWn8TfkwsM0O1k/AxpwbpcRfAHCkVb04CU/yKciKwg2KA==", + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.56.1.tgz", + "integrity": "sha512-fNB/Ng11HrkGOSEIDg+fc3zfTCV7q6kJddp6ndK3QlYFsCffRSnclaX1SMp+mqxdWkHqe1kkp85OY8G/x5uAWw==", + "cpu": [ + "arm" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-arm64": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.56.1.tgz", + "integrity": "sha512-AypXIwZvOMJb9RgjI/98hTAd06FcOjqjIm6G9IR0OI4pJCOcaAXz9NKXdJqxpZd7phSMJnD+Bx/8iYOUPeY73A==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-i686": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.56.1.tgz", + "integrity": "sha512-vnH+WJEsUq7Lf7xc9udzE/M4hoDXXsniFFYr/7BvdnXtCQlNNaWFMXHbEDYAql3baIlHkWoG8cEHWuB/YKyniw==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-linux-x64": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.56.1.tgz", + "integrity": "sha512-3/BlKe5Vdnia36MeovghHJD8lbcum5TFIxLp+PSfH2sVb09+5Jo0L95oRTI2JkD8Fs+QNssvTqTxJj5eIo/n+A==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "linux", + "freebsd", + "android" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-arm64": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-arm64/-/cli-win32-arm64-2.56.1.tgz", + "integrity": "sha512-Gg8RV7CV7Tz4fiR1EN1Af5AVhJsnEXiZvfvfQXI4lp51MKAhcxZIMtEfg9HaWsn3Dm/wgwYBinyeywfWbTXYDg==", + "cpu": [ + "arm64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-i686": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.56.1.tgz", + "integrity": "sha512-6u6a060yC3i76Ze1apqgWr5luQSyhuD5ND84eWfh/UbddsEa42UHjoVHOiBwmpZqf/hvNZAtzLnE4NCvU4zOMg==", + "cpu": [ + "x86", + "ia32" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/cli-win32-x64": { + "version": "2.56.1", + "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.56.1.tgz", + "integrity": "sha512-11cdflajBrDWlRZqI9MOu7ok2vnPzFjKmbU3YvBYWQapNE+HHAsWdsRL/u/P1RmU62vj7Y42iSUcj6x1SNrdPw==", + "cpu": [ + "x64" + ], + "license": "BSD-3-Clause", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@sentry/core": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.17.0.tgz", + "integrity": "sha512-UVIvxSzS0n5QbIDPyFf0WX9I77Of1bcr6a0sCEKfjhJGmGQ8mFWoWgR2gF4wcPw60XUrzbryCr79eOsIHLQ5cw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/electron": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@sentry/electron/-/electron-7.2.0.tgz", + "integrity": "sha512-MuLJhjhklVVU3iSN/XfRShZX2Ng6sWrffiSQYIjyYy56WY/0xpEEXG5EKzM9RvrLn2D5abKpdnty/ql6rrPZ3g==", + "license": "MIT", + "dependencies": { + "@sentry/browser": "10.17.0", + "@sentry/core": "10.17.0", + "@sentry/node": "10.17.0" + }, + "peerDependencies": { + "@sentry/node-native": "10.17.0" + }, + "peerDependenciesMeta": { + "@sentry/node-native": { + "optional": true + } + } + }, + "node_modules/@sentry/node": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-10.17.0.tgz", + "integrity": "sha512-rM+ANC4NKkYHAFa73lqBXq024/YrflcUKBxkqSuo/0jc/Q/svLZfoZ8FW0IVZ4uhXXFZL3PZbkceZYmoOG9ePg==", + "license": "MIT", + "dependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^2.1.0", + "@opentelemetry/core": "^2.1.0", + "@opentelemetry/instrumentation": "^0.204.0", + "@opentelemetry/instrumentation-amqplib": "0.51.0", + "@opentelemetry/instrumentation-connect": "0.48.0", + "@opentelemetry/instrumentation-dataloader": "0.22.0", + "@opentelemetry/instrumentation-express": "0.53.0", + "@opentelemetry/instrumentation-fs": "0.24.0", + "@opentelemetry/instrumentation-generic-pool": "0.48.0", + "@opentelemetry/instrumentation-graphql": "0.52.0", + "@opentelemetry/instrumentation-hapi": "0.51.0", + "@opentelemetry/instrumentation-http": "0.204.0", + "@opentelemetry/instrumentation-ioredis": "0.52.0", + "@opentelemetry/instrumentation-kafkajs": "0.14.0", + "@opentelemetry/instrumentation-knex": "0.49.0", + "@opentelemetry/instrumentation-koa": "0.52.0", + "@opentelemetry/instrumentation-lru-memoizer": "0.49.0", + "@opentelemetry/instrumentation-mongodb": "0.57.0", + "@opentelemetry/instrumentation-mongoose": "0.51.0", + "@opentelemetry/instrumentation-mysql": "0.50.0", + "@opentelemetry/instrumentation-mysql2": "0.51.0", + "@opentelemetry/instrumentation-pg": "0.57.0", + "@opentelemetry/instrumentation-redis": "0.53.0", + "@opentelemetry/instrumentation-tedious": "0.23.0", + "@opentelemetry/instrumentation-undici": "0.15.0", + "@opentelemetry/resources": "^2.1.0", + "@opentelemetry/sdk-trace-base": "^2.1.0", + "@opentelemetry/semantic-conventions": "^1.37.0", + "@prisma/instrumentation": "6.15.0", + "@sentry/core": "10.17.0", + "@sentry/node-core": "10.17.0", + "@sentry/opentelemetry": "10.17.0", + "import-in-the-middle": "^1.14.2", + "minimatch": "^9.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@sentry/node-core": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry/node-core/-/node-core-10.17.0.tgz", + "integrity": "sha512-x6av2pFtsAeN+nZKkhI07cOCugTKux908DCGBlwQEw8ZjghcO5jn3unfAlKZqxZ0ktWgBcSrCM/iJ5Gk2nxPFg==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.17.0", + "@sentry/opentelemetry": "10.17.0", + "import-in-the-middle": "^1.14.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", + "@opentelemetry/core": "^1.30.1 || ^2.1.0", + "@opentelemetry/instrumentation": ">=0.57.1 <1", + "@opentelemetry/resources": "^1.30.1 || ^2.1.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", + "@opentelemetry/semantic-conventions": "^1.37.0" + } + }, + "node_modules/@sentry/opentelemetry": { + "version": "10.17.0", + "resolved": "https://registry.npmjs.org/@sentry/opentelemetry/-/opentelemetry-10.17.0.tgz", + "integrity": "sha512-kZONokjkIQjhDUEZLsi7TZ1Bay0g4VFC2rT1MvZqa1fkFZff7Th9qQr0Lv7gt3nrbD6qIctEzmpf75OQN1cR8A==", + "license": "MIT", + "dependencies": { + "@sentry/core": "10.17.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/context-async-hooks": "^1.30.1 || ^2.1.0", + "@opentelemetry/core": "^1.30.1 || ^2.1.0", + "@opentelemetry/sdk-trace-base": "^1.30.1 || ^2.1.0", + "@opentelemetry/semantic-conventions": "^1.37.0" + } + }, + "node_modules/@sentry/vite-plugin": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-4.5.0.tgz", + "integrity": "sha512-8AcTuAmu2NFCkSgVroCeu/ExZeMDVGdgrXq9MzgE5LT2bcomKsHiAifhitq64QwFEfL6CFt3TYEsw0rm0AoRhQ==", + "license": "MIT", + "dependencies": { + "@sentry/bundler-plugin-core": "4.5.0", + "unplugin": "1.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.7.tgz", + "integrity": "sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", + "integrity": "sha512-mFNylyeyqN93lfe/9CSxOGREz8cpzAhH+E93xJ4xWQf62V8sQ/24reV2nyzUWM6H6Xji+GGHpkbLe7pVoUEskg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz", + "integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^5.0.0", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.6.tgz", + "integrity": "sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "license": "MIT" + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mysql": { + "version": "2.15.27", + "resolved": "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.27.tgz", + "integrity": "sha512-YfWiV16IY0OeBfBCk8+hXKmdTKrKlwKN1MNKAPBu5JYxLwBEZl7QzeEpGnlZb3VMGJrrGmB84gXiH+ofs/TezA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "24.9.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.9.1.tgz", + "integrity": "sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg==", + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/node-cron": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", + "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/pg": { + "version": "8.15.5", + "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz", + "integrity": "sha512-LF7lF6zWEKxuT3/OR8wAZGzkg4ENGXFNyiV/JeOt9z5B+0ZVwbql9McqX5c/WStFq1GaGso7H1AzP/qSzmlCKQ==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "pg-protocol": "*", + "pg-types": "^2.2.0" + } + }, + "node_modules/@types/pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ==", + "license": "MIT", + "dependencies": { + "@types/pg": "*" + } + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.2.tgz", + "integrity": "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.2", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.2.tgz", + "integrity": "sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" + } + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, + "node_modules/@types/tedious": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/@types/tedious/-/tedious-4.0.14.tgz", + "integrity": "sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/xml2js": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.14.tgz", + "integrity": "sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/type-utils": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.46.2", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.2", + "@typescript-eslint/types": "^8.46.2", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.46.2", + "@typescript-eslint/tsconfig-utils": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.46.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/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/@vitejs/plugin-react": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.4.tgz", + "integrity": "sha512-La0KD0vGkVkSk6K+piWDKRUyg8Rl5iAIKRMH0vMJI0Eg47bq1eOxmoObAaQG37WMW9MSyk7Cs8EIWwJC1PtzKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.28.4", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-beta.38", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.17.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/@wry/caches": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz", + "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/context": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz", + "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/equality": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz", + "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@wry/trie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz", + "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.11.tgz", + "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/7zip-bin": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.2.0.tgz", + "integrity": "sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.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==", + "license": "MIT", + "peer": true, + "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==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "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/antd": { + "version": "5.27.6", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.27.6.tgz", + "integrity": "sha512-70HrjVbzDXvtiUQ5MP1XdNudr/wGAk9Ivaemk6f36yrAeJurJSmZ8KngOIilolLRHdGuNc6/Vk+4T1OZpSjpag==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@ant-design/colors": "^7.2.1", + "@ant-design/cssinjs": "^1.23.0", + "@ant-design/cssinjs-utils": "^1.1.3", + "@ant-design/fast-color": "^2.0.6", + "@ant-design/icons": "^5.6.1", + "@ant-design/react-slick": "~1.1.2", + "@babel/runtime": "^7.26.0", + "@rc-component/color-picker": "~2.0.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/qrcode": "~1.0.1", + "@rc-component/tour": "~1.15.1", + "@rc-component/trigger": "^2.3.0", + "classnames": "^2.5.1", + "copy-to-clipboard": "^3.3.3", + "dayjs": "^1.11.11", + "rc-cascader": "~3.34.0", + "rc-checkbox": "~3.5.0", + "rc-collapse": "~3.9.0", + "rc-dialog": "~9.6.0", + "rc-drawer": "~7.3.0", + "rc-dropdown": "~4.2.1", + "rc-field-form": "~2.7.0", + "rc-image": "~7.12.0", + "rc-input": "~1.8.0", + "rc-input-number": "~9.5.0", + "rc-mentions": "~2.20.0", + "rc-menu": "~9.16.1", + "rc-motion": "^2.9.5", + "rc-notification": "~5.6.4", + "rc-pagination": "~5.1.0", + "rc-picker": "~4.11.3", + "rc-progress": "~4.0.0", + "rc-rate": "~2.13.1", + "rc-resize-observer": "^1.4.3", + "rc-segmented": "~2.7.0", + "rc-select": "~14.16.8", + "rc-slider": "~11.1.9", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.54.0", + "rc-tabs": "~15.7.0", + "rc-textarea": "~1.10.2", + "rc-tooltip": "~6.4.0", + "rc-tree": "~5.13.1", + "rc-tree-select": "~5.27.0", + "rc-upload": "~4.9.2", + "rc-util": "^5.44.4", + "scroll-into-view-if-needed": "^3.1.0", + "throttle-debounce": "^5.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "5.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-5.0.0-alpha.12.tgz", + "integrity": "sha512-j87o0j6LqPL3QRr8yid6c+Tt5gC7xNfYo6uQIQkorAC6MpeayVMZrEDzKmJJ/Hlv7EnOQpaRm53k6ktDYZyB6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "26.0.12", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-26.0.12.tgz", + "integrity": "sha512-+/CEPH1fVKf6HowBUs6LcAIoRcjeqgvAeoSE+cl7Y7LndyQ9ViGPYibNk7wmhMHzNgHIuIbw4nWADPO+4mjgWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/asar": "3.2.18", + "@electron/fuses": "^1.8.0", + "@electron/notarize": "2.5.0", + "@electron/osx-sign": "1.3.1", + "@electron/rebuild": "3.7.0", + "@electron/universal": "2.0.1", + "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", + "async-exit-hook": "^2.0.1", + "builder-util": "26.0.11", + "builder-util-runtime": "9.3.1", + "chromium-pickle-js": "^0.2.0", + "config-file-ts": "0.2.8-rc1", + "debug": "^4.3.4", + "dotenv": "^16.4.5", + "dotenv-expand": "^11.0.6", + "ejs": "^3.1.8", + "electron-publish": "26.0.11", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^5.0.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.3", + "lazy-val": "^1.0.5", + "minimatch": "^10.0.0", + "plist": "3.1.0", + "resedit": "^1.7.0", + "semver": "^7.3.8", + "tar": "^6.1.12", + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "dmg-builder": "26.0.12", + "electron-builder-squirrel-windows": "26.0.12" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/app-builder-lib/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/app-builder-lib/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/app-builder-lib/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/app-builder-lib/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/archiver-utils/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/archiver-utils/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/archiver/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/archiver/node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atomically": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-2.0.3.tgz", + "integrity": "sha512-kU6FmrwZ3Lx7/7y3hPS5QnbJfaohcIul5fGqf7ok+4KklIEk9tJ0C2IQPdacSbVUWv6zVHXEBWoWd6NrVMT7Cw==", + "dev": true, + "dependencies": { + "stubborn-fs": "^1.2.5", + "when-exit": "^2.1.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/axios": { + "version": "1.12.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.12.2.tgz", + "integrity": "sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "dev": true, + "license": "Apache-2.0" + }, + "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==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.4.tgz", + "integrity": "sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==", + "dev": true, + "license": "Apache-2.0", + "optional": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.8.19", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.19.tgz", + "integrity": "sha512-zoKGUdu6vb2jd3YOq0nnhEDQVbPcHhco3UImJrv5dSkvxTc2pl2WjOPsjZXDwPDSl5eghIMuY3R6J9NDKF3KcQ==", + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/body-parser/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.26.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.3.tgz", + "integrity": "sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.8.9", + "caniuse-lite": "^1.0.30001746", + "electron-to-chromium": "^1.5.227", + "node-releases": "^2.0.21", + "update-browserslist-db": "^1.1.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "26.0.11", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-26.0.11.tgz", + "integrity": "sha512-xNjXfsldUEe153h1DraD0XvDOpqGR0L5eKFkdReB7eFW5HqysDZFfly4rckda6y9dF39N3pkPlOblcfHKGw+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "7zip-bin": "~5.2.0", + "app-builder-bin": "5.0.0-alpha.12", + "builder-util-runtime": "9.3.1", + "chalk": "^4.1.2", + "cross-spawn": "^7.0.6", + "debug": "^4.3.4", + "fs-extra": "^10.1.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "sanitize-filename": "^1.6.3", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0", + "tiny-async-pool": "1.3.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.3.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.3.1.tgz", + "integrity": "sha512-2/egrNDDnRaxVwK3A+cJq6UOlqOdedGA7JPqCeJjN2Zjk1/QB/6QUi3b714ScIGS7HafFXTyzJEOr5b44I3kvQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/builder-util/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/builder-util/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/builder-util/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "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==", + "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/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "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/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/compress-commons/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "dev": true, + "license": "MIT" + }, + "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/conf": { + "version": "15.0.2", + "resolved": "https://registry.npmjs.org/conf/-/conf-15.0.2.tgz", + "integrity": "sha512-JBSrutapCafTrddF9dH3lc7+T2tBycGF4uPkI4Js+g4vLLEhG6RZcFi3aJd5zntdf5tQxAejJt8dihkoQ/eSJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "atomically": "^2.0.3", + "debounce-fn": "^6.0.0", + "dot-prop": "^10.0.0", + "env-paths": "^3.0.0", + "json-schema-typed": "^8.0.1", + "semver": "^7.7.2", + "uint8array-extras": "^1.5.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/ajv": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/conf/node_modules/env-paths": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-3.0.0.tgz", + "integrity": "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/conf/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/config-file-ts": { + "version": "0.2.8-rc1", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.8-rc1.tgz", + "integrity": "sha512-GtNECbVI82bT4RiDIzBSVuTKoSHufnU7Ce7/42bkWZJZFLjmDF2WBpVsvRkhKCfKBnTBb3qZrBwPpFBU/Myvhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.3.12", + "typescript": "^5.4.3" + } + }, + "node_modules/config-file-ts/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/config-file-ts/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/crc32-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/cross-dirname": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cross-dirname/-/cross-dirname-0.1.0.tgz", + "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/cross-env": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-10.1.0.tgz", + "integrity": "sha512-GsYosgnACZTADcmEyJctkJIoqAhHjttw7RsFrVoJNXbsWWqaq6Ym+7kZjq6mS45O0jij6vtiReppKQEtqWy6Dw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@epic-web/invariant": "^1.0.0", + "cross-spawn": "^7.0.6" + }, + "bin": { + "cross-env": "dist/bin/cross-env.js", + "cross-env-shell": "dist/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.18", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz", + "integrity": "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA==", + "license": "MIT", + "peer": true + }, + "node_modules/dbffile": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/dbffile/-/dbffile-1.12.0.tgz", + "integrity": "sha512-repLNtp1jyODRyAbqSaCiComsLi9/2w+ljYC760TXf69ExFVoJzdDr5STBx21gunM59RipYK5zHeDIuGf1LA8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.4.24" + } + }, + "node_modules/debounce-fn": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-6.0.0.tgz", + "integrity": "sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-function": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-diff": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-0.3.8.tgz", + "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==", + "dev": true, + "license": "MIT" + }, + "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/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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==", + "devOptional": 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==", + "devOptional": 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/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT", + "optional": true + }, + "node_modules/dir-compare": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-4.2.0.tgz", + "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5", + "p-limit": "^3.1.0 " + } + }, + "node_modules/dir-compare/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/dmg-builder": { + "version": "26.0.12", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-26.0.12.tgz", + "integrity": "sha512-59CAAjAhTaIMCN8y9kD573vDkxbs1uhDcrFLHSgutYdPcGOU35Rf95725snvzEOy4BFB7+eLJ8djCNPmGwG67w==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "26.0.12", + "builder-util": "26.0.11", + "builder-util-runtime": "9.3.1", + "fs-extra": "^10.1.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-builder/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dmg-builder/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/dmg-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dot-prop": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-10.1.0.tgz", + "integrity": "sha512-MVUtAugQMOff5RnBy2d9N31iG0lNwg1qAoAOn7pOK5wf94WIaE3My2p3uwTQuvS2AcqchkcR3bHByjaM0mmi7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^5.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dotenv-expand": { + "version": "11.0.7", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-11.0.7.tgz", + "integrity": "sha512-zIHwmZPRshsCdpMDyVsqGmgyP0yT8GAgXUnkdAoJisxvf33k7yO6OuoKmcTGuXPWSsm8Oh88nZicRLA9Y0rUeA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "dotenv": "^16.4.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "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==", + "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/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "38.3.0", + "resolved": "https://registry.npmjs.org/electron/-/electron-38.3.0.tgz", + "integrity": "sha512-Wij4AzX4SAV0X/ktq+NrWrp5piTCSS8F6YWh1KAcG+QRtNzyns9XLKERP68nFHIwfprhxF2YCN2uj7nx9DaeJw==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^22.7.7", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "26.0.12", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-26.0.12.tgz", + "integrity": "sha512-cD1kz5g2sgPTMFHjLxfMjUK5JABq3//J4jPswi93tOPFz6btzXYtK5NrDt717NRbukCUDOrrvmYVOWERlqoiXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "26.0.12", + "builder-util": "26.0.11", + "builder-util-runtime": "9.3.1", + "chalk": "^4.1.2", + "dmg-builder": "26.0.12", + "fs-extra": "^10.1.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder-squirrel-windows": { + "version": "26.0.12", + "resolved": "https://registry.npmjs.org/electron-builder-squirrel-windows/-/electron-builder-squirrel-windows-26.0.12.tgz", + "integrity": "sha512-kpwXM7c/ayRUbYVErQbsZ0nQZX4aLHQrPEG9C4h9vuJCXylwFH8a7Jgi2VpKIObzCXO7LKHiCw4KdioFLFOgqA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "app-builder-lib": "26.0.12", + "builder-util": "26.0.11", + "electron-winstaller": "5.4.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-builder/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-builder/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-log": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.3.tgz", + "integrity": "sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/electron-publish": { + "version": "26.0.11", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-26.0.11.tgz", + "integrity": "sha512-a8QRH0rAPIWH9WyyS5LbNvW9Ark6qe63/LqDB7vu2JXYpi0Gma5Q60Dh4tmTqhOBQt0xsrzD8qE7C+D7j+B24A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "26.0.11", + "builder-util-runtime": "9.3.1", + "chalk": "^4.1.2", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-publish/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-publish/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-store": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-11.0.2.tgz", + "integrity": "sha512-4VkNRdN+BImL2KcCi41WvAYbh6zLX5AUTi4so68yPqiItjbgTjqpEnGAqasgnG+lB6GuAyUltKwVopp6Uv+gwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "conf": "^15.0.2", + "type-fest": "^5.0.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.237", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz", + "integrity": "sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg==", + "license": "ISC" + }, + "node_modules/electron-updater": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.6.2.tgz", + "integrity": "sha512-Cr4GDOkbAUqRHP5/oeOmH/L2Bn6+FQPxVLZtPbcmKZC63a1F3uu5EefYOssgZXG3u/zBlubbJ5PJdITdMVggbw==", + "license": "MIT", + "dependencies": { + "builder-util-runtime": "9.3.1", + "fs-extra": "^10.1.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.6.3", + "tiny-typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-updater/node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/electron-updater/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/electron-updater/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/electron-vite": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/electron-vite/-/electron-vite-4.0.1.tgz", + "integrity": "sha512-QqacJbA8f1pmwUTqki1qLL5vIBaOQmeq13CZZefZ3r3vKVaIoC7cpoTgE+KPKxJDFTax+iFZV0VYvLVWPiQ8Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.27.7", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "cac": "^6.7.14", + "esbuild": "^0.25.5", + "magic-string": "^0.30.17", + "picocolors": "^1.1.1" + }, + "bin": { + "electron-vite": "bin/electron-vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@swc/core": "^1.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } + } + }, + "node_modules/electron-winstaller": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", + "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/asar": "^3.2.1", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.21", + "temp": "^0.9.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "@electron/windows-sign": "^1.1.2" + } + }, + "node_modules/electron-winstaller/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "22.18.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.12.tgz", + "integrity": "sha512-BICHQ67iqxQGFSzfCFTT7MRQ5XcBjG5aeKh5Ok38UBbPe5fxTyE+aHFxwVrGyr8GNlqFMLKD1D3P2K/1ks8tog==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/electron/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT", + "optional": true + }, + "node_modules/esbuild": { + "version": "0.25.11", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.11.tgz", + "integrity": "sha512-KohQwyzrKTQmhXDW1PjCv3Tyspn9n5GcY2RTDqeORIdIJY8yKIF7sTSopFmn/wpMPW4rdPXI0UE5LJLuq3bx0Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.11", + "@esbuild/android-arm": "0.25.11", + "@esbuild/android-arm64": "0.25.11", + "@esbuild/android-x64": "0.25.11", + "@esbuild/darwin-arm64": "0.25.11", + "@esbuild/darwin-x64": "0.25.11", + "@esbuild/freebsd-arm64": "0.25.11", + "@esbuild/freebsd-x64": "0.25.11", + "@esbuild/linux-arm": "0.25.11", + "@esbuild/linux-arm64": "0.25.11", + "@esbuild/linux-ia32": "0.25.11", + "@esbuild/linux-loong64": "0.25.11", + "@esbuild/linux-mips64el": "0.25.11", + "@esbuild/linux-ppc64": "0.25.11", + "@esbuild/linux-riscv64": "0.25.11", + "@esbuild/linux-s390x": "0.25.11", + "@esbuild/linux-x64": "0.25.11", + "@esbuild/netbsd-arm64": "0.25.11", + "@esbuild/netbsd-x64": "0.25.11", + "@esbuild/openbsd-arm64": "0.25.11", + "@esbuild/openbsd-x64": "0.25.11", + "@esbuild/openharmony-arm64": "0.25.11", + "@esbuild/sunos-x64": "0.25.11", + "@esbuild/win32-arm64": "0.25.11", + "@esbuild/win32-ia32": "0.25.11", + "@esbuild/win32-x64": "0.25.11" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", + "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.1", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.38.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.1.tgz", + "integrity": "sha512-4EQQr6wXwS+ZJSzaR5ZCrYgLxqvUjdXctaEtBqHcbkW944B1NQyO4qpdHQbXBONfwxXdkAY81HH4+LUfrg+zPw==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.5.tgz", + "integrity": "sha512-IKKP8R87pJyMl7WWamLgPkloB16dagPIdd2FjBDbyRYPKo93wS/NbCOPh6gH+ieNLC+XZrhJt/kWj0PS/DFdmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.10.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", + "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.22.4 || ^4.0.0", + "zod-validation-error": "^3.0.3 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.24.tgz", + "integrity": "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/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/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/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/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "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/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/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.3.tgz", + "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "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-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-fifo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", + "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "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/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/firebase": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/firebase/-/firebase-12.4.0.tgz", + "integrity": "sha512-/chNgDQ6ppPPGOQO4jctxOa/5JeQxuhaxA7Y90K0I+n/wPfoO8mRveedhVUdo7ExLcWUivnnow/ouSLYSI5Icw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@firebase/ai": "2.4.0", + "@firebase/analytics": "0.10.19", + "@firebase/analytics-compat": "0.2.25", + "@firebase/app": "0.14.4", + "@firebase/app-check": "0.11.0", + "@firebase/app-check-compat": "0.4.0", + "@firebase/app-compat": "0.5.4", + "@firebase/app-types": "0.9.3", + "@firebase/auth": "1.11.0", + "@firebase/auth-compat": "0.6.0", + "@firebase/data-connect": "0.3.11", + "@firebase/database": "1.1.0", + "@firebase/database-compat": "2.1.0", + "@firebase/firestore": "4.9.2", + "@firebase/firestore-compat": "0.4.2", + "@firebase/functions": "0.13.1", + "@firebase/functions-compat": "0.4.1", + "@firebase/installations": "0.6.19", + "@firebase/installations-compat": "0.2.19", + "@firebase/messaging": "0.12.23", + "@firebase/messaging-compat": "0.2.23", + "@firebase/performance": "0.7.9", + "@firebase/performance-compat": "0.2.22", + "@firebase/remote-config": "0.7.0", + "@firebase/remote-config-compat": "0.2.20", + "@firebase/storage": "0.14.0", + "@firebase/storage-compat": "0.4.0", + "@firebase/util": "1.13.0" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz", + "integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/form-data/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/forwarded-parse": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/forwarded-parse/-/forwarded-parse-2.1.2.tgz", + "integrity": "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==", + "license": "MIT" + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "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==", + "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==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz", + "integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "minimatch": "^8.0.2", + "minipass": "^4.2.4", + "path-scurry": "^1.6.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz", + "integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-agent/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/graphql": { + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.11.0.tgz", + "integrity": "sha512-mS1lbMsxgQj6hge1XZ6p7GPhbrtFwUFYi3wRzXAC/FmYnyXMTvvI3td3rjmQ2u8ewXueaSvRPWaEcgVVOT9Jnw==", + "license": "MIT", + "peer": true, + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-request": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-7.3.1.tgz", + "integrity": "sha512-GdinBsBVYrWzwEvOlzadrV5j8mdOc9ZT8In9QyRIZaxbhkTL08j35yNbPp96jAacYzjeD/hKKy2E2RGI7c7Yug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.2.0" + }, + "peerDependencies": { + "graphql": "14 - 16" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "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==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "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==", + "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==", + "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", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/hoist-non-react-statics": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", + "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", + "license": "BSD-3-Clause", + "dependencies": { + "react-is": "^16.7.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/html-parse-stringify": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz", + "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-parser-js": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz", + "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/i18next": { + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.6.0.tgz", + "integrity": "sha512-tTn8fLrwBYtnclpL5aPXK/tAYBLWVvoHM1zdfXoRNLcI+RvtMsoZRV98ePlaW3khHYKuNh/Q65W/+NVFUeIwVw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.27.6" + }, + "peerDependencies": { + "typescript": "^5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true, + "license": "ISC" + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "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/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ip-address": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.0.1.tgz", + "integrity": "sha512-NWv9YLW4PoW2B7xtzaS3NCot75m6nK7Icdv0o3lfMceJVRfSoQwqD4wEH5rLwoKJwUiZ/rfpiVBhnaF0FK4HoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "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-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "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-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true, + "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-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.6.tgz", + "integrity": "sha512-I+NmIfBHUl+r2wcDd6JwE9yWje/PIVY/R5/CmV8dXLZd5K+L9X2klAOwfAHNnondLXkbHyTAleQAWonpTJBTtw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-8.0.1.tgz", + "integrity": "sha512-XQmWYj2Sm4kn4WeTYvmpKEbyPsL7nBsb647c7pMe6l02/yx2+Jfc4dT6UZkEXnIUb5LhD55r2HPsJ1milQ4rDg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC", + "optional": true + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, + "engines": { + "node": ">= 0.6.3" + } + }, + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.17", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", + "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/make-fetch-happen/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/make-fetch-happen/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/make-fetch-happen/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-function": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", + "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz", + "integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-collect/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-fetch/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-fetch/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-flush/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-flush/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-pipeline/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-abi": { + "version": "3.78.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz", + "integrity": "sha512-E2wEyrgX/CqvicaQYU3Ze1PFGjc4QYPGsjUrlYkqAE0WjHEZwgOsGMPMzkMse4LjJbDmaEuDX3CM036j5K2DSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-api-version": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-api-version/-/node-api-version-0.2.1.tgz", + "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + } + }, + "node_modules/node-api-version/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-cron": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-4.2.1.tgz", + "integrity": "sha512-lgimEHPE/QDgFlywTd8yTR61ptugX3Qer29efeyWw2rv259HtGBNn1vZVmp8lB9uo9wC0t/AT4iGqXxia+CJFg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-releases": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz", + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==", + "license": "MIT" + }, + "node_modules/nopt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", + "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "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==", + "devOptional": 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/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optimism": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz", + "integrity": "sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==", + "license": "MIT", + "dependencies": { + "@wry/caches": "^1.0.0", + "@wry/context": "^0.7.0", + "@wry/trie": "^0.5.0", + "tslib": "^2.3.0" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pe-library": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pe-library/-/pe-library-0.4.1.tgz", + "integrity": "sha512-eRWB5LBz7PpDu4PUlwT0PhnQfTQJlDDdPa35urV4Osrm0t0AqQFGn+UIkU3klZvwJ8KPO3VbBFsXquA6p6kqZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pg-protocol": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz", + "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==", + "license": "MIT" + }, + "node_modules/pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", + "dependencies": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/playwright": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.56.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/plist": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "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.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-date": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", + "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", + "dependencies": { + "xtend": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postject": { + "version": "1.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/postject/-/postject-1.0.0-alpha.6.tgz", + "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "commander": "^9.4.0" + }, + "bin": { + "postject": "dist/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/postject/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/proc-log": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/proc-log/-/proc-log-2.0.1.tgz", + "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.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/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc-cascader": { + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.34.0.tgz", + "integrity": "sha512-KpXypcvju9ptjW9FaN2NFcA2QH9E9LHKq169Y0eWtH4e/wHQ5Wh5qZakAgvb8EKZ736WZ3B0zLLOBsrsja5Dag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "^2.3.1", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.5.0.tgz", + "integrity": "sha512-aOAQc3E98HteIIsSqm6Xk2FPKIER6+5vyEFMZfo73TqM+VVAIqOkHoPjgKLqSNtVLWScoaM7vY2ZrGEheI79yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.9.0.tgz", + "integrity": "sha512-swDdz4QZ4dFTo4RAUMLL50qP0EY62N2kvmk2We5xYdRwcRn8WcYtuetCJpwpaCbUfUt5+huLpVxhvmnK+PHrkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.6.0.tgz", + "integrity": "sha512-ApoVi9Z8PaCQg6FsUzS8yvBEQy0ZL2PkuvAgrmohPkN3okps5WZ5WQWPc1RNuiOKaAYv8B97ACdsFU5LizzCqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-7.3.0.tgz", + "integrity": "sha512-DX6CIgiBWNpJIMGFO8BAISFkxiuKitoizooj4BDyee8/SnBn0zwO2FHrNDpqqepj0E/TFTDpmEBCyFuTgC7MOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.9", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.38.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.2.1.tgz", + "integrity": "sha512-YDAlXsPv3I1n42dv1JpdM7wJ+gSUBfeyPK59ZpBD9jQhK9jVuxpjj3NmWQHOBceA1zEPVX84T2wbdb2SD0UjmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-util": "^5.44.1" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-2.7.0.tgz", + "integrity": "sha512-hgKsCay2taxzVnBPZl+1n4ZondsV78G++XVsMIJCAoioMjlMQR9YwAp7JZDIECzIu2Z66R+f4SFIRrO2DjDNAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/async-validator": "^5.0.3", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.12.0", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.12.0.tgz", + "integrity": "sha512-cZ3HTyyckPnNnUb9/DRqduqzLfrQRyi+CdHjdqgsyDpI3Ln5UX1kXnAhPBSJj9pVRzwRFgqkN7p9b6HBDjmu/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.6.0", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.8.0.tgz", + "integrity": "sha512-KXvaTbX+7ha8a/k+eg6SYRVERK0NddX8QX7a7AnRvUa/rEH0CNMlpcBzBkhI0wp2C8C4HlMoYl8TImSN+fuHKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-9.5.0.tgz", + "integrity": "sha512-bKaEvB5tHebUURAEXw35LDcnRZLq3x1k7GxfAqBMzmpHkDGzjAtnUL8y4y5N15rIFIg5IJgwr211jInl3cipag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.8.0", + "rc-util": "^5.40.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.20.0.tgz", + "integrity": "sha512-w8HCMZEh3f0nR8ZEd466ATqmXFCMGMN5UFCzEUL0bM/nGw/wOS2GgRzKBcm19K++jDyuWCOJOdgcKGXU3fXfbQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.6", + "rc-input": "~1.8.0", + "rc-menu": "~9.16.0", + "rc-textarea": "~1.10.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.16.1", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.16.1.tgz", + "integrity": "sha512-ghHx6/6Dvp+fw8CJhDUHFHDJ84hJE3BXNCzSgLdmNiFErWSOaZNsihDAsKq9ByTALo/xkNIwtDFGIl6r+RPXBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.0.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.6.4", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.6.4.tgz", + "integrity": "sha512-KcS4O6B4qzM3KH7lkwOB7ooLPZ4b6J+VMmQgT51VZCeEcmghdeR4IrMcFq0LG+RPdnbe/ArT086tGM8Snimgiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.4.1.tgz", + "integrity": "sha512-3MoPQQPV1uKyOMVNd6SZfONi+f3st0r8PksexIdBTeIYbMX0Jr+k7pHEDvsXtR4BpCv90/Pv2MovVNhktKrwvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-5.1.0.tgz", + "integrity": "sha512-8416Yip/+eclTFdHXLKTxZvn70duYVGTvUUWbckCCZoIl3jagqke3GLsFrMs0bsQBikiYpZLD9206Ej4SOdOXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.38.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-4.11.3.tgz", + "integrity": "sha512-MJ5teb7FlNE0NFHTncxXQ62Y5lytq6sh5nUw0iH8OkHL/TjARSEvSHpr940pWgjGANpjCwyMdvsEV55l5tYNSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.2.1", + "rc-overflow": "^1.3.2", + "rc-resize-observer": "^1.4.0", + "rc-util": "^5.43.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-4.0.0.tgz", + "integrity": "sha512-oofVMMafOCokIUIBnZLNcOZFsABaUw8PPrf1/y0ZBvKZNpOiu5h4AO9vv11Sw0p4Hb3D0yGWuEattcQGtNJ/aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.13.1.tgz", + "integrity": "sha512-QUhQ9ivQ8Gy7mtMZPAjLbxBt5y9GRp65VcUyGUMF3N3fhiftivPHdpuDIaWIMOTEprAjZPC08bls1dQB+I1F2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.7.0.tgz", + "integrity": "sha512-liijAjXz+KnTRVnxxXG2sYDGd6iLL7VpGGdR8gwoxAXy2KglviKCxLWZdjKYJzYzGSUwKDSTdYk8brj54Bn5BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.16.8", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.16.8.tgz", + "integrity": "sha512-NOV5BZa1wZrsdkKaiK7LHRuo5ZjZYMDxPP6/1+09+FB4KoNi8jcG1ZqLE3AVCxEsYMBe65OBx71wFoHRTP3LRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^2.1.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "11.1.9", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-11.1.9.tgz", + "integrity": "sha512-h8IknhzSh3FEM9u8ivkskh+Ef4Yo4JRIY2nj7MrH6GQmrwV6mcpJf5/4KgH5JaVI1H3E52yCdpOlVyGZIeph5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.54.0", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.54.0.tgz", + "integrity": "sha512-/wDTkki6wBTjwylwAGjpLKYklKo9YgjZwAU77+7ME5mBoS32Q4nAwoqhA2lSge6fobLW3Tap6uc5xfwaL2p0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.44.3", + "rc-virtual-list": "^3.14.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "15.7.0", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-15.7.0.tgz", + "integrity": "sha512-ZepiE+6fmozYdWf/9gVp7k56PKHB1YYoDsKeQA1CBlJ/POIhjkcYiv0AGP0w2Jhzftd3AVvZP/K+V+Lpi2ankA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.2.0", + "rc-menu": "~9.16.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.10.2.tgz", + "integrity": "sha512-HfaeXiaSlpiSp0I/pvWpecFEHpVysZ9tpDLNkxQbMvMz6gsr7aVZ7FpWP9kt4t7DB+jJXesYS0us1uPZnlRnwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.8.0", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.4.0.tgz", + "integrity": "sha512-kqyivim5cp8I5RkHmpsp1Nn/Wk+1oeloMv9c7LXNgDxUpGm+RbXJGL+OPvDlcRnx9DBeOe4wyOIl4OKUERyH1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^2.0.0", + "classnames": "^2.3.1", + "rc-util": "^5.44.3" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.13.1", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.13.1.tgz", + "integrity": "sha512-FNhIefhftobCdUJshO7M8uZTA9F4OPGVXqGfZkkD/5soDeOhwO06T/aKTrg0WD8gRg/pyfq+ql3aMymLHCTC4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.27.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.27.0.tgz", + "integrity": "sha512-2qTBTzwIT7LRI1o7zLyrCzmo5tQanmyGbSaGTIf7sYimCklAToVVfpMC6OAldSKolcnjorBYPNSKQqJmN3TCww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.7", + "classnames": "2.x", + "rc-select": "~14.16.2", + "rc-tree": "~5.13.0", + "rc-util": "^5.43.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.9.2.tgz", + "integrity": "sha512-nHx+9rbd1FKMiMRYsqQ3NkXUv7COHPBo3X1Obwq9SWS6/diF/A0aJ5OHubvwUAIDs+4RMleljV0pcrNUc823GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/rc-virtual-list": { + "version": "3.18.5", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.18.5.tgz", + "integrity": "sha512-1FuxVSxhzTj3y8k5xMPbhXCB0t2TOiI3Tq+qE2Bu+GGV7f+ECVuQl4OUg6lZ2qT5fordTW7CBpr9czdzXCI7Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/react-error-boundary": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/react-error-boundary/-/react-error-boundary-6.0.0.tgz", + "integrity": "sha512-gdlJjD7NWr0IfkPlaREN2d9uUZUlksrfOx7SX62VRerwXbMY6ftGCIZua1VG1aXFNOimhISsTq+Owp725b9SiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "peerDependencies": { + "react": ">=16.13.1" + } + }, + "node_modules/react-i18next": { + "version": "16.1.4", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-16.1.4.tgz", + "integrity": "sha512-0UUKZDHjKnLk6dfbYXEZ9CVqLMpNiul+dHbPVQo2z2t1GkdirkeHXb/TtdsNuv+nyNOTDl1Jp6F6uwf9M3DMcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.27.6", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 25.5.2", + "react": ">= 16.8.0", + "typescript": "^5" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", + "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-router": { + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.9.4.tgz", + "integrity": "sha512-SD3G8HKviFHg9xj7dNODUKDFgpG4xqD5nhyd0mYoB5iISepuZAvzSr8ywxgxKJ52yRzf/HWtVHc9AWwoTbljvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router/node_modules/cookie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", + "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/read-binary-file-arch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", + "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "bin": { + "read-binary-file-arch": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/redux-logger": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/redux-logger/-/redux-logger-3.0.6.tgz", + "integrity": "sha512-JoCIok7bg/XpqA1JqCqXFypuqBbQzGQySrhFzewB7ThcnysTO30l4VCst86AuB9T9tuT03MAA56Jw2PNhRSNCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-diff": "^0.3.5" + } + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rehackt": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz", + "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "*" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "react": { + "optional": true + } + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/require-in-the-middle/node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resedit": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz", + "integrity": "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pe-library": "^0.4.1" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jet2jet" + } + }, + "node_modules/reselect": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "dev": true, + "license": "MIT" + }, + "node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "detect-node": "^2.0.4", + "globalthis": "^1.0.1", + "json-stringify-safe": "^5.0.1", + "semver-compare": "^1.0.0", + "sprintf-js": "^1.1.2" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/rollup": { + "version": "4.52.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.5.tgz", + "integrity": "sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.52.5", + "@rollup/rollup-android-arm64": "4.52.5", + "@rollup/rollup-darwin-arm64": "4.52.5", + "@rollup/rollup-darwin-x64": "4.52.5", + "@rollup/rollup-freebsd-arm64": "4.52.5", + "@rollup/rollup-freebsd-x64": "4.52.5", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.5", + "@rollup/rollup-linux-arm-musleabihf": "4.52.5", + "@rollup/rollup-linux-arm64-gnu": "4.52.5", + "@rollup/rollup-linux-arm64-musl": "4.52.5", + "@rollup/rollup-linux-loong64-gnu": "4.52.5", + "@rollup/rollup-linux-ppc64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-gnu": "4.52.5", + "@rollup/rollup-linux-riscv64-musl": "4.52.5", + "@rollup/rollup-linux-s390x-gnu": "4.52.5", + "@rollup/rollup-linux-x64-gnu": "4.52.5", + "@rollup/rollup-linux-x64-musl": "4.52.5", + "@rollup/rollup-openharmony-arm64": "4.52.5", + "@rollup/rollup-win32-arm64-msvc": "4.52.5", + "@rollup/rollup-win32-ia32-msvc": "4.52.5", + "@rollup/rollup-win32-x64-gnu": "4.52.5", + "@rollup/rollup-win32-x64-msvc": "4.52.5", + "fsevents": "~2.3.2" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", + "license": "ISC" + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT", + "optional": true + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/node_modules/type-fest": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", + "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/set-cookie-parser": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", + "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "dev": true, + "license": "MIT" + }, + "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/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true, + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.7", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz", + "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ip-address": "^10.0.1", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "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", + "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", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ssri/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ssri/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamx": { + "version": "2.22.0", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.0.tgz", + "integrity": "sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stubborn-fs": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/stubborn-fs/-/stubborn-fs-1.2.5.tgz", + "integrity": "sha512-H2N9c26eXjzL/S/K+i/RHHcFanE74dptvvjM8iwzwbVcWY/zjBbgRqF3K0DY4+OD+uTTASTBvDoxPDaPN02D7g==", + "dev": true + }, + "node_modules/stylis": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.6.tgz", + "integrity": "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "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", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/synckit": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.10.3.tgz", + "integrity": "sha512-R1urvuyiTaWfeCggqEvpDJwAlDVdsT9NM+IP//Tk2x7qHCkSvBk/fwFgw/TLAHzZlrAnnazMcRw0ZD8HlYFTEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.2.0", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/temp": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.4.tgz", + "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^0.5.1", + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/temp-file/node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/temp-file/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/temp/node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/temp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/temp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/temp/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/text-decoder": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz", + "integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "b4a": "^1.6.4" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tiny-async-pool": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tiny-async-pool/-/tiny-async-pool-1.3.0.tgz", + "integrity": "sha512-01EAw5EDrcVrdgyCLgoSPvqznC0sVxDSVeiOz09FUpjh71G79VCqneOr+xvt7T1r76CF6ZZfPjHorN2+d+3mqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.5.0" + } + }, + "node_modules/tiny-async-pool/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-invariant": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz", + "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==", + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "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/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.1.0.tgz", + "integrity": "sha512-wQ531tuWvB6oK+pchHIu5lHe5f5wpSCqB8Kf4dWQRbOYc9HTge7JL0G4Qd44bh6QuJCccIzL3bugb8GI0MwHrg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.46.2.tgz", + "integrity": "sha512-vbw8bOmiuYNdzzV3lsiWv6sRwjyuKJMQqWulBOU7M0RrxedXledX8G8kBbQeiOYDnTfiXz0Y4081E1QMNB6iQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.46.2", + "@typescript-eslint/parser": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/uint8array-extras": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz", + "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unplugin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.0.1.tgz", + "integrity": "sha512-aqrHaVBWW1JVKBHmGo33T5TxeL0qWzfvjWokObHA9bYmN7eNDkwOxmLjhioHl9878qDFMAaT51XNroRyuz7WxA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.8.1", + "chokidar": "^3.5.3", + "webpack-sources": "^3.2.3", + "webpack-virtual-modules": "^0.5.0" + } + }, + "node_modules/unplugin/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/unplugin/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/unplugin/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz", + "integrity": "sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/vite": { + "version": "7.1.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.11.tgz", + "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "esbuild": "^0.25.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web-vitals": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-4.2.4.tgz", + "integrity": "sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/webpack-sources": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", + "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.5.0.tgz", + "integrity": "sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==", + "license": "MIT" + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/when-exit": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/when-exit/-/when-exit-2.1.4.tgz", + "integrity": "sha512-4rnvd3A1t16PWzrBUcSDZqcAmsUIy4minDXT/CZ8F2mVDgd65i4Aalimgz1aQkRGU0iH5eT5+6Rx2TK8o443Pg==", + "dev": true, + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "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/winax": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/winax/-/winax-3.6.2.tgz", + "integrity": "sha512-KvNO9lBBW//F4k4kE3QzKWHyGchMswrwSC2TD/rS4BYLaypECPCRXQIyjmQHVteK7cBEqqdF288brwnig/67Ow==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "nodewscript": "NodeWScript.js" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "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/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xml2js": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz", + "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml2js/node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xmlbuilder2": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-4.0.0.tgz", + "integrity": "sha512-zIoY033NGmbzHX1cYOGKNfeWpZyiGLzXGHNoxQ6tR/R+WqT7mqz+EDtFdPwqnhIms6vHz9BNtMS47DiGPyGfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oozcitak/dom": "^2.0.1", + "@oozcitak/infra": "^2.0.1", + "@oozcitak/util": "^9.0.4", + "js-yaml": "^4.1.0" + }, + "engines": { + "node": ">=20.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", + "license": "MIT" + }, + "node_modules/zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "license": "MIT", + "dependencies": { + "zen-observable": "0.8.15" + } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "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", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/zod": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.12.tgz", + "integrity": "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ==", + "dev": true, + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8042477 --- /dev/null +++ b/package.json @@ -0,0 +1,91 @@ +{ + "name": "bodyshop-desktop", + "version": "1.0.8", + "description": "Shop Management System Partner", + "main": "./out/main/index.js", + "author": "Convenient Brands, LLC", + "homepage": "https://convenient-brands.com", + "scripts": { + "format": "prettier --write .", + "lint": "eslint --cache .", + "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false", + "typecheck:web": "tsc --noEmit -p tsconfig.web.json --composite false", + "typecheck": "npm run typecheck:node && npm run typecheck:web", + "start": "electron-vite preview", + "dev": "electron-vite dev", + "build:imex": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --config electron-builder.imex.yml", + "build:rome": "node deploy/set-artifact-name.js electron-vite build --mode rome && node deploy/set-artifact-name.js electron-builder --config electron-builder.rome.yml", + "build:imex:publish": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --config electron-builder.imex.yml --publish always", + "build:rome:publish": "node deploy/set-artifact-name.js electron-vite build --mode rome && node deploy/set-artifact-name.js electron-builder --config electron-builder.rome.yml --publish always", + "build:imex:linux": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --config electron-builder.imex.yml --linux", + "build:rome:linux": "node deploy/set-artifact-name.js electron-vite build --mode rome && node deploy/set-artifact-name.js electron-builder --config electron-builder.rome.yml --linux", + "postinstall": "electron-builder install-app-deps", + "build:unpack": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --dir", + "build:win": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --win", + "build:mac": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --mac", + "build:linux": "node deploy/set-artifact-name.js electron-vite build --mode imex && node deploy/set-artifact-name.js electron-builder --linux" + }, + "dependencies": { + "@apollo/client": "^3.13.6", + "@electron-toolkit/preload": "^3.0.2", + "@electron-toolkit/utils": "^4.0.0", + "@sentry/electron": "^7.2.0", + "@sentry/vite-plugin": "^4.5.0", + "axios": "^1.12.2", + "dayjs": "^1.11.18", + "electron-log": "^5.4.3", + "electron-updater": "^6.6.2", + "winax": "^3.6.2" + }, + "devDependencies": { + "@ant-design/v5-patch-for-react-19": "^1.0.3", + "@electron-toolkit/eslint-config-prettier": "^3.0.0", + "@electron-toolkit/eslint-config-ts": "^3.1.0", + "@electron-toolkit/tsconfig": "^2.0.0", + "@playwright/test": "^1.56.1", + "@reduxjs/toolkit": "^2.9.1", + "@types/cors": "^2.8.19", + "@types/express": "^5.0.3", + "@types/lodash": "^4.17.20", + "@types/node": "^24.9.1", + "@types/node-cron": "^3.0.11", + "@types/react": "^19.2.2", + "@types/react-dom": "^19.2.2", + "@types/xml2js": "^0.4.14", + "@vitejs/plugin-react": "^5.0.4", + "antd": "^5.27.6", + "archiver": "^7.0.1", + "chokidar": "^4.0.3", + "cors": "^2.8.5", + "cross-env": "^10.1.0", + "dbffile": "^1.12.0", + "electron": "^38.3.0", + "electron-builder": "^26.0.12", + "electron-store": "^11.0.2", + "electron-vite": "^4.0.1", + "eslint": "^9.38.0", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-refresh": "^0.4.24", + "express": "^5.1.0", + "firebase": "^12.4.0", + "graphql": "^16.11.0", + "graphql-request": "^7.3.1", + "i18next": "^25.6.0", + "lodash": "^4.17.21", + "node-cron": "^4.2.1", + "playwright": "^1.56.1", + "prettier": "^3.6.2", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-error-boundary": "^6.0.0", + "react-i18next": "^16.1.4", + "react-redux": "^9.2.0", + "react-router": "^7.9.4", + "redux-logger": "^3.0.6", + "typescript": "^5.9.3", + "vite": "7.1.11", + "xml2js": "^0.6.2", + "xmlbuilder2": "^4.0.0" + } +} diff --git a/playwright.config.ts b/playwright.config.ts new file mode 100644 index 0000000..b0d9b0d --- /dev/null +++ b/playwright.config.ts @@ -0,0 +1,80 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// import dotenv from 'dotenv'; +// import path from 'path'; +// dotenv.config({ path: path.resolve(__dirname, '.env') }); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + //testDir: './tests/**/*', + //testMatch: '**/*.test.ts', + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://127.0.0.1:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + + { + name: "firefox", + use: { ...devices["Desktop Firefox"] }, + }, + + { + name: "webkit", + use: { ...devices["Desktop Safari"] }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { ...devices['Pixel 5'] }, + // }, + // { + // name: 'Mobile Safari', + // use: { ...devices['iPhone 12'] }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { ...devices['Desktop Edge'], channel: 'msedge' }, + // }, + // { + // name: 'Google Chrome', + // use: { ...devices['Desktop Chrome'], channel: 'chrome' }, + // }, + ], + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: "npm run start", + // url: "http://127.0.0.1:3000", + // reuseExistingServer: !process.env.CI, + // }, +}); diff --git a/resources/Interop.QBFC16.dll b/resources/Interop.QBFC16.dll new file mode 100644 index 0000000..ba70ed2 Binary files /dev/null and b/resources/Interop.QBFC16.dll differ diff --git a/resources/Interop.QBXMLRP2.dll b/resources/Interop.QBXMLRP2.dll new file mode 100644 index 0000000..c7863b7 Binary files /dev/null and b/resources/Interop.QBXMLRP2.dll differ diff --git a/resources/QBFC16.dll b/resources/QBFC16.dll new file mode 100644 index 0000000..95394f3 Binary files /dev/null and b/resources/QBFC16.dll differ diff --git a/resources/icon.png b/resources/icon.png new file mode 100644 index 0000000..dd32a22 Binary files /dev/null and b/resources/icon.png differ diff --git a/resources/ro-icon.png b/resources/ro-icon.png new file mode 100644 index 0000000..f9a7f41 Binary files /dev/null and b/resources/ro-icon.png differ diff --git a/scripts/imex-shop-partner.desktop b/scripts/imex-shop-partner.desktop new file mode 100644 index 0000000..1085305 --- /dev/null +++ b/scripts/imex-shop-partner.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=ImEX Shop Partner +Exec=/opt/ImEX%20Shop%20Partner/ShopPartner %u +Type=Application +Terminal=false +Icon=imex-shop-partner +Categories=Utility; +MimeType=x-scheme-handler/imexmedia; \ No newline at end of file diff --git a/scripts/installer.nsh b/scripts/installer.nsh new file mode 100644 index 0000000..0333f74 --- /dev/null +++ b/scripts/installer.nsh @@ -0,0 +1,13 @@ +!macro customInstall + ; Register imexmedia protocol + WriteRegStr HKCR "imexmedia" "" "URL:ImEX Shop Partner Protocol" + WriteRegStr HKCR "imexmedia" "URL Protocol" "" + WriteRegStr HKCR "imexmedia\\shell" "" "" + WriteRegStr HKCR "imexmedia\\shell\\open" "" "" + WriteRegStr HKCR "imexmedia\\shell\\open\\command" "" '"$INSTDIR\ShopPartner.exe" "%1"' +!macroend + +!macro customUnInstall + ; Remove imexmedia protocol + DeleteRegKey HKCR "imexmedia" +!macroend \ No newline at end of file diff --git a/scripts/rome-shop-partner.desktop b/scripts/rome-shop-partner.desktop new file mode 100644 index 0000000..5fe6a89 --- /dev/null +++ b/scripts/rome-shop-partner.desktop @@ -0,0 +1,8 @@ +[Desktop Entry] +Name=Rome Shop Partner +Exec=/opt/Rome%20Shop%20Partner/ShopPartner %u +Type=Application +Terminal=false +Icon=rome-shop-partner +Categories=Utility; +MimeType=x-scheme-handler/imexmedia; \ No newline at end of file diff --git a/src/env.d.ts b/src/env.d.ts new file mode 100644 index 0000000..c2e6c8b --- /dev/null +++ b/src/env.d.ts @@ -0,0 +1,12 @@ +/// + +export interface ImportMetaEnv { + readonly VITE_FIREBASE_CONFIG: string; + readonly VITE_GRAPHQL_ENDPOINT: string; + readonly VITE_FIREBASE_CONFIG_TEST: string; + readonly VITE_GRAPHQL_ENDPOINT_TEST: string; +} + +export interface ImportMeta { + readonly env: ImportMetaEnv; +} diff --git a/src/main/decoder/decode-ad1.interface.ts b/src/main/decoder/decode-ad1.interface.ts new file mode 100644 index 0000000..d6a72c7 --- /dev/null +++ b/src/main/decoder/decode-ad1.interface.ts @@ -0,0 +1,149 @@ +import { UUID } from "crypto"; + +export interface DecodedAd1 { + // Insurance company information + ins_co_id?: string; + ins_co_nm?: string; + ins_addr1?: string; + ins_addr2?: string; + ins_city?: string; + ins_st?: string; + ins_zip?: string; + ins_ctry?: string; + ins_ea?: string; + ins_ph1?: string; + ins_ph1x?: string; + ins_ph2?: string; + ins_ph2x?: string; + ins_fax?: string; + ins_faxx?: string; + ins_ct_ln?: string; + ins_ct_fn?: string; + ins_title?: string; + ins_ct_ph?: string; + ins_ct_phx?: string; + + // Policy information + policy_no?: string; + ded_amt?: string; + ded_status?: string; + asgn_no?: string; + asgn_date?: Date | string; + asgn_type?: string; + + // Claim information + clm_no?: string; + clm_ofc_id?: string; + clm_ofc_nm?: string; + clm_addr1?: string; + clm_addr2?: string; + clm_city?: string; + clm_st?: string; + clm_zip?: string; + clm_ctry?: string; + clm_ph1?: string; + clm_ph1x?: string; + clm_ph2?: string; + clm_ph2x?: string; + clm_fax?: string; + clm_faxx?: string; + clm_ct_ln?: string; + clm_ct_fn?: string; + clm_title?: string; + clm_ct_ph?: string; + clm_ct_phx?: string; + clm_ea?: string; + + // Payment information + payee_nms?: string; + pay_type?: string; + pay_date?: string; + pay_chknm?: string; + pay_amt?: string; + + // Agent information + agt_co_id?: string; + agt_co_nm?: string; + agt_addr1?: string; + agt_addr2?: string; + agt_city?: string; + agt_st?: string; + agt_zip?: string; + agt_ctry?: string; + agt_ph1?: string; + agt_ph1x?: string; + agt_ph2?: string; + agt_ph2x?: string; + agt_fax?: string; + agt_faxx?: string; + agt_ct_ln?: string; + agt_ct_fn?: string; + agt_ct_ph?: string; + agt_ct_phx?: string; + agt_ea?: string; + agt_lic_no?: string; + + // Loss information + loss_date?: string; + loss_type?: string; + loss_desc?: string; + theft_ind?: string; + cat_no?: string; + tlos_ind?: string; + cust_pr?: string; + loss_cat?: string; + + // Insured information + insd_ln?: string; + insd_fn?: string; + insd_title?: string; + insd_co_nm?: string; + insd_addr1?: string; + insd_addr2?: string; + insd_city?: string; + insd_st?: string; + insd_zip?: string; + insd_ctry?: string; + insd_ph1?: string; + insd_ph2?: string; + insd_fax?: string; + insd_faxx?: string; + insd_ea?: string; + + // Owner information + ownr_ln?: string; + ownr_fn?: string; + ownr_title?: string; + ownr_co_nm?: string; + ownr_addr1?: string; + ownr_addr2?: string; + ownr_city?: string; + ownr_st?: string; + ownr_zip?: string; + ownr_ctry?: string; + ownr_ph1?: string; + ownr_ph2?: string; + ownr_ea?: string; + + // Owner data object - referenced in the code + owner: { + data: OwnerRecordInterface; + }; +} + +export interface OwnerRecordInterface { + ownr_ln?: string; + ownr_fn?: string; + ownr_title?: string; + ownr_co_nm?: string; + ownr_addr1?: string; + ownr_addr2?: string; + ownr_city?: string; + ownr_st?: string; + ownr_zip?: string; + ownr_ctry?: string; + ownr_ph1?: string; + ownr_ph2?: string; + ownr_ea?: string; + shopid: UUID; +} diff --git a/src/main/decoder/decode-ad1.ts b/src/main/decoder/decode-ad1.ts new file mode 100644 index 0000000..bbf515f --- /dev/null +++ b/src/main/decoder/decode-ad1.ts @@ -0,0 +1,237 @@ +import { platform } from "@electron-toolkit/utils"; +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import store from "../store/store"; +import { DecodedAd1, OwnerRecordInterface } from "./decode-ad1.interface"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeAD1 = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}A.AD1`); + } catch { + // log.debug("Error opening AD1 File.", errorTypeCheck(error)); + dbf = await DBFFile.open(`${extensionlessFilePath}.AD1`); + // log.debug("Trying to find AD1 file using regular CIECA Id."); + } + + if (!dbf) { + log.error(`Could not find any AD1 files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any AD1 files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["a.ad1", ".ad1"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any AD1 files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any AD1 files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening AD1 File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(1); + + //AD1 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + const rawAd1Data: DecodedAd1 = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "INS_CO_ID", + "INS_CO_NM", + "INS_ADDR1", + "INS_ADDR2", + "INS_CITY", + "INS_ST", + "INS_ZIP", + "INS_CTRY", + "INS_EA", + "POLICY_NO", + "DED_AMT", + "DED_STATUS", + "ASGN_NO", + "ASGN_DATE", + "ASGN_TYPE", + "CLM_NO", + "CLM_OFC_ID", + "CLM_OFC_NM", + "CLM_ADDR1", + "CLM_ADDR2", + "CLM_CITY", + "CLM_ST", + "CLM_ZIP", + "CLM_CTRY", + "CLM_PH1", + "CLM_PH1X", + "CLM_PH2", + "CLM_PH2X", + "CLM_FAX", + "CLM_FAXX", + "CLM_CT_LN", + "CLM_CT_FN", + "CLM_TITLE", + "CLM_CT_PH", + "CLM_CT_PHX", + "CLM_EA", + "PAYEE_NMS", + "PAY_TYPE", + "PAY_DATE", + "PAY_CHKNM", + "PAY_AMT", + "AGT_CO_ID", + "AGT_CO_NM", + "AGT_ADDR1", + "AGT_ADDR2", + "AGT_CITY", + "AGT_ST", + "AGT_ZIP", + "AGT_CTRY", + "AGT_PH1", + "AGT_PH1X", + "AGT_PH2", + "AGT_PH2X", + "AGT_FAX", + "AGT_FAXX", + "AGT_CT_LN", + "AGT_CT_FN", + "AGT_CT_PH", + "AGT_CT_PHX", + "AGT_EA", + "AGT_LIC_NO", + "LOSS_DATE", + "LOSS_TYPE", + "LOSS_DESC", + "THEFT_IND", + "CAT_NO", + "TLOS_IND", + "CUST_PR", + "INSD_LN", + "INSD_FN", + "INSD_TITLE", + "INSD_CO_NM", + "INSD_ADDR1", + "INSD_ADDR2", + "INSD_CITY", + "INSD_ST", + "INSD_ZIP", + "INSD_CTRY", + "INSD_PH1", + //"INSD_PH1X", + "INSD_PH2", + //"INSD_PH2X", + "INSD_FAX", + "INSD_FAXX", + "INSD_EA", + "OWNR_LN", + "OWNR_FN", + "OWNR_TITLE", + "OWNR_CO_NM", + "OWNR_ADDR1", + "OWNR_ADDR2", + "OWNR_CITY", + "OWNR_ST", + "OWNR_ZIP", + "OWNR_CTRY", + "OWNR_PH1", + //"OWNR_PH1X", + "OWNR_PH2", + //"OWNR_PH2X", + //"OWNR_FAX", + //"OWNR_FAXX", + "OWNR_EA", + "INS_PH1", + "INS_PH1X", + "INS_PH2", + "INS_PH2X", + "INS_FAX", + "INS_FAXX", + "INS_CT_LN", + "INS_CT_FN", + "INS_TITLE", + "INS_CT_PH", + "INS_CT_PHX", + "LOSS_CAT", + ]), + ); + + //Copy specific logic for manipulation. + //If ownr_ph1 is missing, use ownr_ph2 + if (rawAd1Data.asgn_date) { + const newAsgnDate = new Date(rawAd1Data.asgn_date); + rawAd1Data.asgn_date = newAsgnDate.toISOString().split("T")[0]; + } + + if (!rawAd1Data.ownr_ph1 || _.isEmpty(rawAd1Data.ownr_ph1)) { + rawAd1Data.ownr_ph1 = rawAd1Data.ownr_ph2; + } + if (rawAd1Data.clm_no === "") { + rawAd1Data.clm_no = undefined; + } + let ownerRecord: OwnerRecordInterface; + //Check if the owner information is there. If not, use the insured information as a fallback. + if ( + _.isEmpty(rawAd1Data.ownr_ln) && + _.isEmpty(rawAd1Data.ownr_fn) && + _.isEmpty(rawAd1Data.ownr_co_nm) + ) { + //They're all empty. Using the insured information as a fallback. + // Build up the owner record to insert it alongside the job. + //TODO: Verify that this should be the insured, and not the claimant. + ownerRecord = { + ownr_ln: rawAd1Data.insd_ln, + ownr_fn: rawAd1Data.insd_fn, + ownr_title: rawAd1Data.insd_title, + ownr_co_nm: rawAd1Data.insd_co_nm, + ownr_addr1: rawAd1Data.insd_addr1, + ownr_addr2: rawAd1Data.insd_addr2, + ownr_city: rawAd1Data.insd_city, + ownr_st: rawAd1Data.insd_st, + ownr_zip: rawAd1Data.insd_zip, + ownr_ctry: rawAd1Data.insd_ctry, + ownr_ph1: rawAd1Data.insd_ph1, + ownr_ph2: rawAd1Data.insd_ph2, + ownr_ea: rawAd1Data.insd_ea, + shopid: store.get("app.bodyshop.id"), + }; + } else { + //Use the owner information. + ownerRecord = { + ownr_ln: rawAd1Data.ownr_ln, + ownr_fn: rawAd1Data.ownr_fn, + ownr_title: rawAd1Data.ownr_title, + ownr_co_nm: rawAd1Data.ownr_co_nm, + ownr_addr1: rawAd1Data.ownr_addr1, + ownr_addr2: rawAd1Data.ownr_addr2, + ownr_city: rawAd1Data.ownr_city, + ownr_st: rawAd1Data.ownr_st, + ownr_zip: rawAd1Data.ownr_zip, + ownr_ctry: rawAd1Data.ownr_ctry, + ownr_ph1: rawAd1Data.ownr_ph1, + ownr_ph2: rawAd1Data.ownr_ph2, + ownr_ea: rawAd1Data.ownr_ea, + shopid: store.get("app.bodyshop.id"), + }; + } + + return { ...rawAd1Data, owner: { data: ownerRecord } }; +}; + +export default DecodeAD1; diff --git a/src/main/decoder/decode-ad2.interface.ts b/src/main/decoder/decode-ad2.interface.ts new file mode 100644 index 0000000..8f803ed --- /dev/null +++ b/src/main/decoder/decode-ad2.interface.ts @@ -0,0 +1,29 @@ +export interface DecodedAD2 { + clmt_ln?: string; + clmt_fn?: string; + clmt_title?: string; + clmt_co_nm?: string; + clmt_addr1?: string; + clmt_addr2?: string; + clmt_city?: string; + clmt_st?: string; + clmt_zip?: string; + clmt_ctry?: string; + clmt_ph1?: string; + clmt_ph2?: string; + clmt_ea?: string; + est_co_id?: string; + est_co_nm?: string; + est_addr1?: string; + est_addr2?: string; + est_city?: string; + est_st?: string; + est_zip?: string; + est_ctry?: string; + est_ph1?: string; + est_ct_ln?: string; + est_ct_fn?: string; + est_ea?: string; + date_estimated?: Date; // This is transformed from insp_date + insp_date?: Date; // This exists initially but gets deleted +} diff --git a/src/main/decoder/decode-ad2.ts b/src/main/decoder/decode-ad2.ts new file mode 100644 index 0000000..adfb2b3 --- /dev/null +++ b/src/main/decoder/decode-ad2.ts @@ -0,0 +1,170 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import { DecodedAD2 } from "./decode-ad2.interface"; +import { platform } from "@electron-toolkit/utils"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeAD2 = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}B.AD2`); + } catch { + dbf = await DBFFile.open(`${extensionlessFilePath}.AD2`); + } + + if (!dbf) { + log.error(`Could not find any AD2 files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any AD2 files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["b.ad2", ".ad2"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any AD2 files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any AD2 files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening AD2 File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(1); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawAd2Data: DecodedAD2 = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "CLMT_LN", //TODO: This claimant info shouldnt be passed back. Just for the owner info. + "CLMT_FN", + "CLMT_TITLE", + "CLMT_CO_NM", + "CLMT_ADDR1", + "CLMT_ADDR2", + "CLMT_CITY", + "CLMT_ST", + "CLMT_ZIP", + "CLMT_CTRY", + "CLMT_PH1", + //"CLMT_PH1X", + "CLMT_PH2", + //"CLMT_PH2X", + //"CLMT_FAX", + //"CLMT_FAXX", + "CLMT_EA", + //"EST_CO_ID", + "EST_CO_NM", + "EST_ADDR1", + "EST_ADDR2", + "EST_CITY", + "EST_ST", + "EST_ZIP", + "EST_CTRY", + "EST_PH1", + //"EST_PH1X", + //"EST_PH2", + //"EST_PH2X", + //"EST_FAX", + //"EST_FAXX", + "EST_CT_LN", + "EST_CT_FN", + "EST_EA", + //"EST_LIC_NO", + //"EST_FILENO", + //"INSP_CT_LN", + //"INSP_CT_FN", + //"INSP_ADDR1", + //"INSP_ADDR2", + //"INSP_CITY", + //"INSP_ST", + //"INSP_ZIP", + //"INSP_CTRY", + //"INSP_PH1", + //"INSP_PH1X", + //"INSP_PH2", + //"INSP_PH2X", + //"INSP_FAX", + //"INSP_FAXX", + //"INSP_EA", + //"INSP_CODE", + //"INSP_DESC", + "INSP_DATE", //RENAME TO date_estimated + //"INSP_TIME", + //"RF_CO_ID", + //"RF_CO_NM", + //"RF_ADDR1", + //"RF_ADDR2", + //"RF_CITY", + //"RF_ST", + //"RF_ZIP", + //"RF_CTRY", + //"RF_PH1", + //"RF_PH1X", + //"RF_PH2", + //"RF_PH2X", + //"RF_FAX", + //"RF_FAXX", + //"RF_CT_LN", + //"RF_CT_FN", + //"RF_EA", + //"RF_TAX_ID", + //"RF_LIC_NO", + //"RF_BAR_NO", + //"RO_IN_DATE", + //"RO_IN_TIME", + //"TAR_DATE", + //"TAR_TIME", + //"RO_CMPDATE", + //"RO_CMPTIME", + //"DATE_OUT", + //"TIME_OUT", + //"RF_ESTIMTR", + //"MKTG_TYPE", + //"MKTG_SRC", + //"LOC_NM", + //"LOC_ADDR1", + //"LOC_ADDR2", + //"LOC_CITY", + //"LOC_ST", + //"LOC_ZIP", + //"LOC_CTRY", + //"LOC_PH1", + //"LOC_PH1X", + //"LOC_PH2", + //"LOC_PH2X", + //"LOC_FAX", + //"LOC_FAXX", + //"LOC_CT_LN", + //"LOC_CT_FN", + //"LOC_TITLE", + //"LOC_PH", + //"LOC_PHX", + //"LOC_EA", + ]), + ); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + rawAd2Data.date_estimated = rawAd2Data.insp_date; + delete rawAd2Data.insp_date; + + return rawAd2Data; +}; +export default DecodeAD2; diff --git a/src/main/decoder/decode-env.interface.ts b/src/main/decoder/decode-env.interface.ts new file mode 100644 index 0000000..0148524 --- /dev/null +++ b/src/main/decoder/decode-env.interface.ts @@ -0,0 +1,5 @@ +export interface DecodedEnv { + est_system?: string; + estfile_id?: string; + ciecaid?: string; +} diff --git a/src/main/decoder/decode-env.ts b/src/main/decoder/decode-env.ts new file mode 100644 index 0000000..de26726 --- /dev/null +++ b/src/main/decoder/decode-env.ts @@ -0,0 +1,68 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedEnv } from "./decode-env.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeEnv = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.ENV`); + } catch (error) { + log.error("Error opening ENV File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any ENV files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any ENV files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".env"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any ENV files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any ENV files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening ENV File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(1); + + //AD2 will always have only 1 row. + + //TODO: Determine if there's any value to capture the whole ENV file. + + const rawEnvData: DecodedEnv = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + //TODO: Several of these fields will fail. Should extend schema to capture them. + //"EST_SYSTEM", + "ESTFILE_ID", + ]), + ); + rawEnvData.ciecaid = rawEnvData.estfile_id; + delete rawEnvData.estfile_id; + + //Apply business logic transfomrations. + + return rawEnvData; +}; +export default DecodeEnv; diff --git a/src/main/decoder/decode-lin.interface.ts b/src/main/decoder/decode-lin.interface.ts new file mode 100644 index 0000000..295dadb --- /dev/null +++ b/src/main/decoder/decode-lin.interface.ts @@ -0,0 +1,54 @@ +export interface DecodedLinLine { + line_no?: string; + line_ind?: string; + line_ref?: string; + tran_code?: string; + db_ref?: string; + unq_seq?: string; + //who_pays?: string; + line_desc?: string; + part_type?: string; + //part_desc_j?: boolean; + glass_flag?: boolean; + oem_partno?: string; + price_inc?: boolean; + alt_part_i?: boolean; + tax_part?: boolean; + db_price?: number; + act_price?: number; + price_j?: boolean; + cert_part?: boolean; + part_qty?: number; + alt_co_id?: string; + alt_partno?: string; + alt_overrd?: boolean; + alt_partm?: string; + prt_dsmk_p?: string; + prt_dsmk_m?: string; + mod_lbr_ty?: string; + db_hrs?: number; + mod_lb_hrs?: number; + lbr_inc?: boolean; + lbr_op?: string; + lbr_hrs_j?: boolean; + lbr_typ_j?: boolean; + lbr_op_j?: boolean; + paint_stg?: string; + paint_tone?: string; + lbr_tax?: boolean; + lbr_amt?: number; + misc_amt?: number; + misc_sublt?: string; + misc_tax?: boolean; + bett_type?: string; + bett_pctg?: string | number; + bett_amt?: number; + bett_tax?: boolean; + op_code_desc?: string; +} + +export interface DecodedLin { + joblines: { + data: DecodedLinLine[]; + }; +} diff --git a/src/main/decoder/decode-lin.ts b/src/main/decoder/decode-lin.ts new file mode 100644 index 0000000..a5b2c1b --- /dev/null +++ b/src/main/decoder/decode-lin.ts @@ -0,0 +1,120 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import store from "../store/store"; +import { DecodedLin, DecodedLinLine } from "./decode-lin.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeLin = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.LIN`); + } catch (error) { + //LIN File only has 1 location. + log.error("Error opening LIN File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any LIN files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any LIN files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["lin"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any LIN files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any LIN files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening LIN File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + const opCodeData = store.get("app.masterdata.opcodes"); //TODO: Type the op codes + + const rawLinData: DecodedLinLine[] = rawDBFRecord.map((record) => { + const singleLineData: DecodedLinLine = deepLowerCaseKeys( + _.pick(record, [ + //TODO: Add typings for EMS File Formats. + "LINE_NO", + "LINE_IND", + "LINE_REF", + "TRAN_CODE", + "DB_REF", + "UNQ_SEQ", + // "WHO_PAYS", + "LINE_DESC", + "PART_TYPE", + //TODO: Believe this was previously broken in partner. Need to confirm. + // system == "M" ? "PART_DESCJ" : "PART_DES_J", + //"PART_DESC_J", + //End Check + "GLASS_FLAG", + "OEM_PARTNO", + "PRICE_INC", + "ALT_PART_I", + "TAX_PART", + "DB_PRICE", + "ACT_PRICE", + "PRICE_J", + "CERT_PART", + "PART_QTY", + "ALT_CO_ID", + "ALT_PARTNO", + "ALT_OVERRD", + "ALT_PARTM", + "PRT_DSMK_P", + "PRT_DSMK_M", + "MOD_LBR_TY", + "DB_HRS", + "MOD_LB_HRS", + "LBR_INC", + "LBR_OP", + "LBR_HRS_J", + "LBR_TYP_J", + "LBR_OP_J", + "PAINT_STG", + "PAINT_TONE", + "LBR_TAX", + "LBR_AMT", + "MISC_AMT", + "MISC_SUBLT", + "MISC_TAX", + "BETT_TYPE", + "BETT_PCTG", + "BETT_AMT", + "BETT_TAX", + ]), + ); + //Apply line by line adjustments. + singleLineData.op_code_desc = opCodeData[singleLineData.lbr_op]?.desc; + + return singleLineData; + }); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + + return { joblines: { data: rawLinData } }; +}; +export default DecodeLin; diff --git a/src/main/decoder/decode-pfh.interface.ts b/src/main/decoder/decode-pfh.interface.ts new file mode 100644 index 0000000..043c08f --- /dev/null +++ b/src/main/decoder/decode-pfh.interface.ts @@ -0,0 +1,15 @@ +export interface DecodedPfh { + tax_prethr: number; + tax_thr_amt?: number; + tax_pstthr?: number; + tax_tow_rt: number; + tax_str_rt: number; + tax_sub_rt: number; + tax_lbr_rt: number; + federal_tax_rate: number; + adj_g_disc?: number; + adj_towdis?: number; + adj_strdis?: number; + tax_predis?: number; + tax_gst_rt?: number; +} diff --git a/src/main/decoder/decode-pfh.ts b/src/main/decoder/decode-pfh.ts new file mode 100644 index 0000000..0a9c724 --- /dev/null +++ b/src/main/decoder/decode-pfh.ts @@ -0,0 +1,94 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedPfh } from "./decode-pfh.interface"; +import { platform } from "os"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePfh = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFH`); + } catch (error) { + log.error("Error opening PFH File.", errorTypeCheck(error)); + dbf = await DBFFile.open(`${extensionlessFilePath}.PFH`); + log.log("Trying to find PFH file using regular CIECA Id."); + } + + if (!dbf) { + log.error(`Could not find any PFH files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFH files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".pfh"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFH files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFH files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFH File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(1); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawPfhData: DecodedPfh = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + //TODO: Several of these fields will fail. Should extend schema to capture them. + //"ID_PRO_NAM", //Remove + "TAX_PRETHR", + "TAX_THRAMT", + "TAX_PSTTHR", + //"TAX_TOW_IN", //Remove + "TAX_TOW_RT", + //"TAX_STR_IN", //Remove + "TAX_STR_RT", + //"TAX_SUB_IN", //Remove + "TAX_SUB_RT", + //"TAX_BTR_IN", //Remove + "TAX_LBR_RT", + "TAX_GST_RT", + //"TAX_GST_IN", //Remove + "ADJ_G_DISC", + "ADJ_TOWDIS", + "ADJ_STRDIS", + //"ADJ_BTR_IN", //Remove + "TAX_PREDIS", + ]), + ); + + //Apply business logic transfomrations. + + //Standardize some of the numbers and divide by 100. + + rawPfhData.tax_prethr = (rawPfhData.tax_prethr ?? 0) / 100; + rawPfhData.tax_pstthr = (rawPfhData.tax_pstthr ?? 0) / 100; + rawPfhData.tax_tow_rt = (rawPfhData.tax_tow_rt ?? 0) / 100; + rawPfhData.tax_str_rt = (rawPfhData.tax_str_rt ?? 0) / 100; + rawPfhData.tax_sub_rt = (rawPfhData.tax_sub_rt ?? 0) / 100; + rawPfhData.tax_lbr_rt = (rawPfhData.tax_lbr_rt ?? 0) / 100; + rawPfhData.federal_tax_rate = (rawPfhData.tax_gst_rt ?? 0) / 100; + delete rawPfhData.tax_gst_rt; + + return rawPfhData; +}; +export default DecodePfh; diff --git a/src/main/decoder/decode-pfl.interface.ts b/src/main/decoder/decode-pfl.interface.ts new file mode 100644 index 0000000..b9a2e2a --- /dev/null +++ b/src/main/decoder/decode-pfl.interface.ts @@ -0,0 +1,57 @@ +//TODO: Clean up this interface. A bit messy as we store the data in very different ways. + +export interface DecodedPflLine { + lbr_type: string; + lbr_desc: string; + lbr_rate: number; + lbr_tax_in: boolean; + lbr_taxp: number; + lbr_adjP: number; + lbr_tx_ty1: string; + lbr_tx_in1: boolean; + lbr_tx_ty2: string; + lbr_tx_in2: boolean; + lbr_tx_ty3: string; + lbr_tx_in3: boolean; + lbr_tx_ty4: string; + lbr_tx_in4: boolean; + lbr_tx_ty5: string; + lbr_tx_in5: boolean; +} + +export interface JobLaborRateFields { + rate_laa: number; + rate_lab: number; + rate_lad: number; + rate_las: number; + rate_lar: number; + rate_lae: number; + rate_lag: number; + rate_laf: number; + rate_lam: number; + rate_lau: number; + rate_la1: number; + rate_la2: number; + rate_la3: number; + rate_la4: number; +} +export interface CiecaPfl { + LAA?: DecodedPflLine; + LAB?: DecodedPflLine; + LAD?: DecodedPflLine; + LAS?: DecodedPflLine; + LAR?: DecodedPflLine; + LAE?: DecodedPflLine; + LAG?: DecodedPflLine; + LAF?: DecodedPflLine; + LAM?: DecodedPflLine; + LAU?: DecodedPflLine; + LA1?: DecodedPflLine; + LA2?: DecodedPflLine; + LA3?: DecodedPflLine; + LA4?: DecodedPflLine; +} + +export interface DecodedPfl extends JobLaborRateFields { + cieca_pfl: CiecaPfl; +} diff --git a/src/main/decoder/decode-pfl.ts b/src/main/decoder/decode-pfl.ts new file mode 100644 index 0000000..0cd6843 --- /dev/null +++ b/src/main/decoder/decode-pfl.ts @@ -0,0 +1,122 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { + DecodedPfl, + JobLaborRateFields, + DecodedPflLine, +} from "./decode-pfl.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePfl = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFL`); + } catch (error) { + //PFL File only has 1 location. + log.error("Error opening PFL File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any PFL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFL files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".pfl"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFL files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFL File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const jobLaborRates: JobLaborRateFields = { + rate_laa: 0, + rate_lab: 0, + rate_lad: 0, + rate_las: 0, + rate_lar: 0, + rate_lae: 0, + rate_lag: 0, + rate_laf: 0, + rate_lam: 0, + rate_lau: 0, + rate_la1: 0, + rate_la2: 0, + rate_la3: 0, + rate_la4: 0, + }; + + const rawPflData: DecodedPflLine[] = rawDBFRecord.map((record) => { + const singleLineData: DecodedPflLine = deepLowerCaseKeys( + _.pick(record, [ + //TODO: Add typings for EMS File Formats. + "LBR_TYPE", + "LBR_DESC", + "LBR_RATE", + "LBR_TAX_IN", + "LBR_TAXP", + "LBR_ADJP", + "LBR_TX_TY1", + "LBR_TX_IN1", + "LBR_TX_TY2", + "LBR_TX_IN2", + "LBR_TX_TY3", + "LBR_TX_IN3", + "LBR_TX_TY4", + "LBR_TX_IN4", + "LBR_TX_TY5", + "LBR_TX_IN5", + ]), + ); + //Apply line by line adjustments. + //Set the job.rate_ field based on the value. + jobLaborRates[`rate_${singleLineData.lbr_type.toLowerCase()}`] = + singleLineData.lbr_rate; + + //For Mitchell, Alum is stored under LA3 instead of LAA. Shift it back over. + //The old partner had a check for this, but it always was true. Matching that logic. + if (singleLineData.lbr_type === "LA3") { + jobLaborRates[`rate_laa`] = singleLineData.lbr_rate; + } + + //Also capture the whole object. + //This is segmented because the whole object was not previously captured for ImEX as it wasn't needed. + //Rome needs the whole object to accurately calculate the tax rates. + + return singleLineData; + }); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + + const pflObj = _.keyBy(rawPflData, "lbr_type"); + + return { ...jobLaborRates, cieca_pfl: pflObj }; +}; + +export default DecodePfl; diff --git a/src/main/decoder/decode-pfm.interface.ts b/src/main/decoder/decode-pfm.interface.ts new file mode 100644 index 0000000..fe293bf --- /dev/null +++ b/src/main/decoder/decode-pfm.interface.ts @@ -0,0 +1,50 @@ +export interface DecodedPfmLine { + matl_type?: string; + cal_code?: number; + cal_desc?: string; + cal_maxdlr?: number; + cal_prip?: number; + cal_secp?: number; + mat_calp?: number; + cal_prethr?: number; + cal_pstthr?: number; + cal_thramt?: number; + cal_lbrmin?: number; + cal_lbrrte?: number; + cal_opcode?: string; + tax_ind?: boolean; + mat_taxp?: number; + mat_adjp?: number; + mat_tx_ty1?: string; + mat_tx_in1?: boolean; + mat_tx_ty2?: string; + mat_tx_in2?: boolean; + mat_tx_ty3?: string; + mat_tx_in3?: boolean; + mat_tx_ty4?: string; + mat_tx_in4?: boolean; + mat_tx_ty5?: string; + mat_tx_in5?: boolean; +} + +export interface JobMaterialRateFields { + rate_mapa: number; + tax_paint_mat_rt: number; + rate_mash: number; + tax_shop_mat_rt: number; + rate_mahw: number; + tax_levies_rt: number; + rate_ma2s: number; + rate_ma2t: number; + rate_ma3s: number; + rate_macs: number; + rate_mabl: number; +} + +export interface DecodedPfm extends JobMaterialRateFields { + materials: { + MAPA?: DecodedPfmLine; + MASH?: DecodedPfmLine; + }; + cieca_pfm?: DecodedPfmLine[]; +} diff --git a/src/main/decoder/decode-pfm.ts b/src/main/decoder/decode-pfm.ts new file mode 100644 index 0000000..cc840db --- /dev/null +++ b/src/main/decoder/decode-pfm.ts @@ -0,0 +1,169 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import YNBoolConverter from "../../util/ynBoolConverter"; +import { + DecodedPfm, + DecodedPfmLine, + JobMaterialRateFields, +} from "./decode-pfm.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePfm = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFM`); + } catch (error) { + //PFM File only has 1 location. + log.error("Error opening PFM File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any PFM files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFM files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".pfm"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFM files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFM files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFM File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const jobMaterialRates: JobMaterialRateFields = { + rate_mapa: 0, + tax_paint_mat_rt: 0, + rate_mash: 0, + tax_shop_mat_rt: 0, + rate_mahw: 0, + tax_levies_rt: 0, + rate_ma2s: 0, + rate_ma2t: 0, + rate_ma3s: 0, + rate_macs: 0, + rate_mabl: 0, + }; + + const rawPfmData: DecodedPfmLine[] = rawDBFRecord.map((record) => { + const singleLineData: DecodedPfmLine = YNBoolConverter( + deepLowerCaseKeys( + _.pick(record, [ + //TODO: Add typings for EMS File Formats. + "MATL_TYPE", + "CAL_CODE", + "CAL_DESC", + "CAL_MAXDLR", + "CAL_PRIP", + + "CAL_SECP", + "MAT_CALP", + "CAL_PRETHR", //Mitchell here + "CAL_PSTTHR", + "CAL_THRAMT", + + "CAL_LBRMIN", + + "CAL_LBRRTE", //Audatex puts it here + "CAL_OPCODE", + + "TAX_IND", + "MAT_TAXP", + "MAT_ADJP", + "MAT_TX_TY1", + "MAT_TX_IN1", + "MAT_TX_TY2", + "MAT_TX_IN2", + "MAT_TX_TY3", + "MAT_TX_IN3", + "MAT_TX_TY4", + "MAT_TX_IN4", + "MAT_TX_TY5", + "MAT_TX_IN5", + ]), + ), + ); + + //Also capture the whole object. + //This is segmented because the whole object was not previously captured for ImEX as it wasn't needed. + //Rome needs the whole object to accurately calculate the tax rates. + + return singleLineData; + }); + + //Apply line by line adjustments. + const mapaLine: DecodedPfmLine | undefined = rawPfmData.find( + (line) => line.matl_type === "MAPA", + ); + if (mapaLine) { + jobMaterialRates.rate_mapa = + mapaLine.cal_lbrrte || mapaLine.cal_prethr || 0; + jobMaterialRates.tax_paint_mat_rt = (mapaLine.mat_taxp ?? 0) / 100; + } + + const mashLine: DecodedPfmLine | undefined = rawPfmData.find( + (line) => line.matl_type === "MASH", + ); + if (mashLine) { + jobMaterialRates.rate_mash = + mashLine.cal_lbrrte || mashLine.cal_prethr || 0; + jobMaterialRates.tax_shop_mat_rt = (mashLine.mat_taxp ?? 0) / 100; + } + + const mahwLine: DecodedPfmLine | undefined = rawPfmData.find( + (line) => line.matl_type === "MAHW", + ); + if (mahwLine) { + jobMaterialRates.rate_mahw = + mahwLine.cal_lbrrte || mahwLine.cal_prethr || 0; + jobMaterialRates.tax_levies_rt = (mahwLine.mat_taxp ?? 0) / 100; + } + + const additionalMaterials = ["MA2S", "MA2T", "MA3S", "MACS", "MABL"]; + additionalMaterials.forEach((type) => { + const line: DecodedPfmLine | undefined = rawPfmData.find( + (line) => line.matl_type === type, + ); + if (line) { + jobMaterialRates[`rate_${type.toLowerCase()}`] = + line.cal_lbrrte || line.cal_prethr || 0; + } + }); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + + return { + ...jobMaterialRates, + materials: { + MASH: mashLine, + MAPA: mapaLine, //TODO: Need to verify if more fields are to come in here. + }, + //cieca_pfm: rawPfmData, //TODO: Not currently captured. This may have valu in the future. + }; +}; + +export default DecodePfm; diff --git a/src/main/decoder/decode-pfo.interface.ts b/src/main/decoder/decode-pfo.interface.ts new file mode 100644 index 0000000..07c256e --- /dev/null +++ b/src/main/decoder/decode-pfo.interface.ts @@ -0,0 +1,32 @@ +export interface DecodedPfoLine { + tx_tow_ty?: string; + tow_t_ty1?: string; + tow_t_in1?: boolean; + tow_t_ty2?: string; + tow_t_in2?: boolean; + tow_t_ty3?: string; + tow_t_in3?: boolean; + tow_t_ty4?: string; + tow_t_in4?: boolean; + tow_t_ty5?: string; + tow_t_in5?: boolean; + tow_t_ty6?: string; + tow_t_in6?: boolean; + tx_stor_ty?: string; + stor_t_ty1?: string; + stor_t_in1?: boolean; + stor_t_ty2?: string; + stor_t_in2?: boolean; + stor_t_ty3?: string; + stor_t_in3?: boolean; + stor_t_ty4?: string; + stor_t_in4?: boolean; + stor_t_ty5?: string; + stor_t_in5?: boolean; + stor_t_ty6?: string; + stor_t_in6?: boolean; +} + +export interface DecodedPfo { + cieca_pfo: DecodedPfoLine; +} diff --git a/src/main/decoder/decode-pfo.ts b/src/main/decoder/decode-pfo.ts new file mode 100644 index 0000000..c63241d --- /dev/null +++ b/src/main/decoder/decode-pfo.ts @@ -0,0 +1,93 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import YNBoolConverter from "../../util/ynBoolConverter"; +import { DecodedPfo, DecodedPfoLine } from "./decode-pfo.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePfo = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFO`); + } catch (error) { + log.error("Error opening PFO File.", errorTypeCheck(error)); + dbf = await DBFFile.open(`${extensionlessFilePath}.PFO`); + log.log("Trying to find PFO file using regular CIECA Id."); + } + + if (!dbf) { + log.error(`Could not find any PFO files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFO files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".pfo"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFO files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFO files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFO File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(1); + + //PFO will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawPfoData: DecodedPfoLine = YNBoolConverter( + deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "TX_TOW_TY", + "TOW_T_TY1", + "TOW_T_IN1", + "TOW_T_TY2", + "TOW_T_IN2", + "TOW_T_TY3", + "TOW_T_IN3", + "TOW_T_TY4", + "TOW_T_IN4", + "TOW_T_TY5", + "TOW_T_IN5", + "TOW_T_TY6", + "TOW_T_IN6", + "TX_STOR_TY", + "STOR_T_TY1", + "STOR_T_IN1", + "STOR_T_TY2", + "STOR_T_IN2", + "STOR_T_TY3", + "STOR_T_IN3", + "STOR_T_TY4", + "STOR_T_IN4", + "STOR_T_TY5", + "STOR_T_IN5", + "STOR_T_TY6", + "STOR_T_IN6", + ]), + ), + ); + + //Apply business logic transfomrations. + + return { cieca_pfo: rawPfoData }; +}; +export default DecodePfo; diff --git a/src/main/decoder/decode-pfp.interface.ts b/src/main/decoder/decode-pfp.interface.ts new file mode 100644 index 0000000..d0f15a8 --- /dev/null +++ b/src/main/decoder/decode-pfp.interface.ts @@ -0,0 +1,37 @@ +export interface DecodedPfpLine { + prt_type: string; + prt_tax_in: boolean; + prt_tax_rt: number; + prt_mkupp: number; + prt_mktyp: string; + prt_discp: number; + prt_tx_ty1: string; + prt_tx_in1: boolean; + prt_tx_ty2: string; + prt_tx_in2: boolean; + prt_tx_ty3: string; + prt_tx_in3: boolean; + prt_tx_ty4: string; + prt_tx_in4: boolean; + prt_tx_ty5: string; + prt_tx_in5: boolean; +} + +export interface DecodedPfpLinesByType { + PAA: DecodedPfpLine; + PAC: DecodedPfpLine; + PAL: DecodedPfpLine; + PAG: DecodedPfpLine; + PAM: DecodedPfpLine; + PAP: DecodedPfpLine; + PAN: DecodedPfpLine; + PAO: DecodedPfpLine; + PAR: DecodedPfpLine; + PAS: DecodedPfpLine; + PASL: DecodedPfpLine; + PAT: DecodedPfpLine; +} + +export interface DecodedPfp { + parts_tax_rates: DecodedPfpLinesByType; +} diff --git a/src/main/decoder/decode-pfp.ts b/src/main/decoder/decode-pfp.ts new file mode 100644 index 0000000..c6d1f2a --- /dev/null +++ b/src/main/decoder/decode-pfp.ts @@ -0,0 +1,98 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import YNBoolConverter from "../../util/ynBoolConverter"; +import { + DecodedPfp, + DecodedPfpLine, + DecodedPfpLinesByType, +} from "./decode-pfp.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePfp = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFP`); + } catch (error) { + //PFP File only has 1 location. + log.error("Error opening PFP File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any PFP files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFP files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = [".pfp"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFP files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFP files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFP File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawPfpData: DecodedPfpLine[] = rawDBFRecord.map((record) => { + const singleLineData: DecodedPfpLine = deepLowerCaseKeys( + _.pick(record, [ + //TODO: Add typings for EMS File Formats. + "PRT_TYPE", + "PRT_TAX_IN", + "PRT_TAX_RT", + "PRT_MKUPP", + "PRT_MKTYP", + "PRT_DISCP", + "PRT_TX_TY1", + "PRT_TX_IN1", + "PRT_TX_TY2", + "PRT_TX_IN2", + "PRT_TX_TY3", + "PRT_TX_IN3", + "PRT_TX_TY4", + "PRT_TX_IN4", + "PRT_TX_TY5", + "PRT_TX_IN5", + ]), + ); + + singleLineData.prt_tax_rt = singleLineData.prt_tax_rt / 100; + return YNBoolConverter(singleLineData); + }); + + //Apply business logic transfomrations. + + //Convert array of lines to a hash object. + const parsedPfpFile: DecodedPfpLinesByType = rawPfpData.reduce( + (acc: DecodedPfpLinesByType, line: DecodedPfpLine) => { + acc[line.prt_type] = line; + return acc; + }, + {} as DecodedPfpLinesByType, + ); + + return { parts_tax_rates: parsedPfpFile }; +}; + +export default DecodePfp; diff --git a/src/main/decoder/decode-pft.interface.ts b/src/main/decoder/decode-pft.interface.ts new file mode 100644 index 0000000..664171d --- /dev/null +++ b/src/main/decoder/decode-pft.interface.ts @@ -0,0 +1,147 @@ +/** + * Interface representing decoded data from a PFT file + * Contains tax type information with up to 6 tax types and 5 tiers each + */ +export interface DecodedPftLine { + // Tax Type 1 + tax_type1?: string; + ty1_tier1?: number; + ty1_thres1?: number; + ty1_rate1?: number; + ty1_sur1?: number; + ty1_tier2?: number; + ty1_thres2?: number; + ty1_rate2?: number; + ty1_sur2?: number; + ty1_tier3?: number; + ty1_thres3?: number; + ty1_rate3?: number; + ty1_sur3?: number; + ty1_tier4?: number; + ty1_thres4?: number; + ty1_rate4?: number; + ty1_sur4?: number; + ty1_tier5?: number; + ty1_thres5?: number; + ty1_rate5?: number; + ty1_sur5?: number; + + // Tax Type 2 + tax_type2?: string; + ty2_tier1?: number; + ty2_thres1?: number; + ty2_rate1?: number; + ty2_sur1?: number; + ty2_tier2?: number; + ty2_thres2?: number; + ty2_rate2?: number; + ty2_sur2?: number; + ty2_tier3?: number; + ty2_thres3?: number; + ty2_rate3?: number; + ty2_sur3?: number; + ty2_tier4?: number; + ty2_thres4?: number; + ty2_rate4?: number; + ty2_sur4?: number; + ty2_tier5?: number; + ty2_thres5?: number; + ty2_rate5?: number; + ty2_sur5?: number; + + // Tax Type 3 + tax_type3?: string; + ty3_tier1?: number; + ty3_thres1?: number; + ty3_rate1?: number; + ty3_sur1?: number; + ty3_tier2?: number; + ty3_thres2?: number; + ty3_rate2?: number; + ty3_sur2?: number; + ty3_tier3?: number; + ty3_thres3?: number; + ty3_rate3?: number; + ty3_sur3?: number; + ty3_tier4?: number; + ty3_thres4?: number; + ty3_rate4?: number; + ty3_sur4?: number; + ty3_tier5?: number; + ty3_thres5?: number; + ty3_rate5?: number; + ty3_sur5?: number; + + // Tax Type 4 + tax_type4?: string; + ty4_tier1?: number; + ty4_thres1?: number; + ty4_rate1?: number; + ty4_sur1?: number; + ty4_tier2?: number; + ty4_thres2?: number; + ty4_rate2?: number; + ty4_sur2?: number; + ty4_tier3?: number; + ty4_thres3?: number; + ty4_rate3?: number; + ty4_sur3?: number; + ty4_tier4?: number; + ty4_thres4?: number; + ty4_rate4?: number; + ty4_sur4?: number; + ty4_tier5?: number; + ty4_thres5?: number; + ty4_rate5?: number; + ty4_sur5?: number; + + // Tax Type 5 + tax_type5?: string; + ty5_tier1?: number; + ty5_thres1?: number; + ty5_rate1?: number; + ty5_sur1?: number; + ty5_tier2?: number; + ty5_thres2?: number; + ty5_rate2?: number; + ty5_sur2?: number; + ty5_tier3?: number; + ty5_thres3?: number; + ty5_rate3?: number; + ty5_sur3?: number; + ty5_tier4?: number; + ty5_thres4?: number; + ty5_rate4?: number; + ty5_sur4?: number; + ty5_tier5?: number; + ty5_thres5?: number; + ty5_rate5?: number; + ty5_sur5?: number; + + // Tax Type 6 + tax_type6?: string; + ty6_tier1?: number; + ty6_thres1?: number; + ty6_rate1?: number; + ty6_sur1?: number; + ty6_tier2?: number; + ty6_thres2?: number; + ty6_rate2?: number; + ty6_sur2?: number; + ty6_tier3?: number; + ty6_thres3?: number; + ty6_rate3?: number; + ty6_sur3?: number; + ty6_tier4?: number; + ty6_thres4?: number; + ty6_rate4?: number; + ty6_sur4?: number; + ty6_tier5?: number; + ty6_thres5?: number; + ty6_rate5?: number; + ty6_sur5?: number; +} + +export interface DecodedPft { + cieca_pft: DecodedPftLine; +} diff --git a/src/main/decoder/decode-pft.ts b/src/main/decoder/decode-pft.ts new file mode 100644 index 0000000..3430660 --- /dev/null +++ b/src/main/decoder/decode-pft.ts @@ -0,0 +1,189 @@ +import { platform } from "@electron-toolkit/utils"; +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedPft, DecodedPftLine } from "./decode-pft.interface"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodePft = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.PFT`); + } catch (error) { + log.error("Error opening PFH File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any PFT files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFT files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["pft"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any PFT files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any PFT files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening PFT File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(1); + + //PFT will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawPftData: DecodedPftLine = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "TAX_TYPE1", //The below is is taken from a CCC estimate. Will require validation to ensure it is also accurate for Audatex/Mitchell + "TY1_TIER1", + "TY1_THRES1", + "TY1_RATE1", + "TY1_SUR1", + "TY1_TIER2", + "TY1_THRES2", + "TY1_RATE2", + "TY1_SUR2", + "TY1_TIER3", + "TY1_THRES3", + "TY1_RATE3", + "TY1_SUR3", + "TY1_TIER4", + "TY1_THRES4", + "TY1_RATE4", + "TY1_SUR4", + "TY1_TIER5", + "TY1_THRES5", + "TY1_RATE5", + "TY1_SUR5", + "TAX_TYPE2", + "TY2_TIER1", + "TY2_THRES1", + "TY2_RATE1", + "TY2_SUR1", + "TY2_TIER2", + "TY2_THRES2", + "TY2_RATE2", + "TY2_SUR2", + "TY2_TIER3", + "TY2_THRES3", + "TY2_RATE3", + "TY2_SUR3", + "TY2_TIER4", + "TY2_THRES4", + "TY2_RATE4", + "TY2_SUR4", + "TY2_TIER5", + "TY2_THRES5", + "TY2_RATE5", + "TY2_SUR5", + "TAX_TYPE3", + "TY3_TIER1", + "TY3_THRES1", + "TY3_RATE1", + "TY3_SUR1", + "TY3_TIER2", + "TY3_THRES2", + "TY3_RATE2", + "TY3_SUR2", + "TY3_TIER3", + "TY3_THRES3", + "TY3_RATE3", + "TY3_SUR3", + "TY3_TIER4", + "TY3_THRES4", + "TY3_RATE4", + "TY3_SUR4", + "TY3_TIER5", + "TY3_THRES5", + "TY3_RATE5", + "TY3_SUR5", + "TAX_TYPE4", + "TY4_TIER1", + "TY4_THRES1", + "TY4_RATE1", + "TY4_SUR1", + "TY4_TIER2", + "TY4_THRES2", + "TY4_RATE2", + "TY4_SUR2", + "TY4_TIER3", + "TY4_THRES3", + "TY4_RATE3", + "TY4_SUR3", + "TY4_TIER4", + "TY4_THRES4", + "TY4_RATE4", + "TY4_SUR4", + "TY4_TIER5", + "TY4_THRES5", + "TY4_RATE5", + "TY4_SUR5", + "TAX_TYPE5", + "TY5_TIER1", + "TY5_THRES1", + "TY5_RATE1", + "TY5_SUR1", + "TY5_TIER2", + "TY5_THRES2", + "TY5_RATE2", + "TY5_SUR2", + "TY5_TIER3", + "TY5_THRES3", + "TY5_RATE3", + "TY5_SUR3", + "TY5_TIER4", + "TY5_THRES4", + "TY5_RATE4", + "TY5_SUR4", + "TY5_TIER5", + "TY5_THRES5", + "TY5_RATE5", + "TY5_SUR5", + "TAX_TYPE6", + "TY6_TIER1", + "TY6_THRES1", + "TY6_RATE1", + "TY6_SUR1", + "TY6_TIER2", + "TY6_THRES2", + "TY6_RATE2", + "TY6_SUR2", + "TY6_TIER3", + "TY6_THRES3", + "TY6_RATE3", + "TY6_SUR3", + "TY6_TIER4", + "TY6_THRES4", + "TY6_RATE4", + "TY6_SUR4", + "TY6_TIER5", + "TY6_THRES5", + "TY6_RATE5", + "TY6_SUR5", + ]), + ); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + + return { cieca_pft: rawPftData }; +}; +export default DecodePft; diff --git a/src/main/decoder/decode-stl.interface.ts b/src/main/decoder/decode-stl.interface.ts new file mode 100644 index 0000000..b0953e0 --- /dev/null +++ b/src/main/decoder/decode-stl.interface.ts @@ -0,0 +1,23 @@ +export interface DecodedStlLine { + ttl_type?: string; + ttl_typecd?: string; + t_amt?: number; + t_hrs?: number; + t_addlbr?: number; + t_discamt?: number; + t_mkupamt?: number; + t_gdiscamt?: number; + tax_amt?: number; + nt_amt?: number; + nt_hrs?: number; + nt_addlbr?: number; + nt_disc?: number; + nt_mkup?: number; + nt_gdis?: number; + ttl_typamt?: number; + ttl_hrs?: number; + ttl_amt?: number; +} +export interface DecodedStl { + cieca_stl: { data: DecodedStlLine[] }; +} diff --git a/src/main/decoder/decode-stl.ts b/src/main/decoder/decode-stl.ts new file mode 100644 index 0000000..0706099 --- /dev/null +++ b/src/main/decoder/decode-stl.ts @@ -0,0 +1,85 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedStl, DecodedStlLine } from "./decode-stl.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeStl = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.STL`); + } catch (error) { + log.error("Error opening STL File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any STL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any STL files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["stl"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any STL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any STL files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening STL File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawStlData: DecodedStlLine[] = rawDBFRecord.map((record) => { + const singleLineData: DecodedStlLine = deepLowerCaseKeys( + _.pick(record, [ + //TODO: Add typings for EMS File Formats. + "TTL_TYPE", + "TTL_TYPECD", + "T_AMT", + "T_HRS", + "T_ADDLBR", + "T_DISCAMT", + "T_MKUPAMT", + "T_GDISCAMT", + "TAX_AMT", + "NT_AMT", + "NT_HRS", + "NT_ADDLBR", + "NT_DISC", + "NT_MKUP", + "NT_GDIS", + "TTL_TYPAMT", + "TTL_HRS", + "TTL_AMT", + ]), + ); + //Apply line by line adjustments. + + return singleLineData; + }); + + //Apply business logic transfomrations. + //We don't have an inspection date, we instead have `date_estimated` + + return { cieca_stl: { data: rawStlData } }; +}; +export default DecodeStl; diff --git a/src/main/decoder/decode-ttl.interface.ts b/src/main/decoder/decode-ttl.interface.ts new file mode 100644 index 0000000..52662d8 --- /dev/null +++ b/src/main/decoder/decode-ttl.interface.ts @@ -0,0 +1,22 @@ +export interface DecodedTtl { + clm_total: number; + depreciation_taxes: number; + cieca_ttl: { data: DecodedTtlLine }; +} + +export interface DecodedTtlLine { + g_ttl_amt?: number; + g_bett_amt?: number; + g_rpd_amt?: number; + g_ded_amt?: number; + g_cust_amt?: number; + g_aa_amt?: number; + n_ttl_amt?: number; + prev_net?: number; + supp_amt?: number; + n_supp_amt?: number; + g_upd_amt?: number; + g_ttl_disc?: number; + g_tax?: number; + gst_amt?: number; +} diff --git a/src/main/decoder/decode-ttl.ts b/src/main/decoder/decode-ttl.ts new file mode 100644 index 0000000..0fc1f36 --- /dev/null +++ b/src/main/decoder/decode-ttl.ts @@ -0,0 +1,80 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedTtl, DecodedTtlLine } from "./decode-ttl.interface"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeTtl = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}.TTL`); + } catch (error) { + log.error("Error opening TTL File.", errorTypeCheck(error)); + } + + if (!dbf) { + log.error(`Could not find any TTL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any TTL files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["ttl"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any TTL files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any TTL files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath); + } catch (error) { + log.error("Error opening TTL File.", errorTypeCheck(error)); + throw error; + } + } + + const rawDBFRecord = await dbf.readRecords(1); + + //PFT will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + const rawTtlData: DecodedTtlLine = deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "G_TTL_AMT", + "G_BETT_AMT", + "G_RPD_AMT", + "G_DED_AMT", + "G_CUST_AMT", + "G_AA_AMT", + "N_TTL_AMT", + "PREV_NET", + "SUPP_AMT", + "N_SUPP_AMT", //Previously commented. Possible issue. + "G_UPD_AMT", + "G_TTL_DISC", + "G_TAX", + "GST_AMT", + ]), + ); + + //Apply business logic transfomrations. + + return { + clm_total: rawTtlData.g_ttl_amt || 0, + depreciation_taxes: rawTtlData.g_bett_amt || 0, //TODO: Find where this needs to be filled from + cieca_ttl: { data: rawTtlData }, + }; +}; +export default DecodeTtl; diff --git a/src/main/decoder/decode-veh.interface.ts b/src/main/decoder/decode-veh.interface.ts new file mode 100644 index 0000000..75bcb9e --- /dev/null +++ b/src/main/decoder/decode-veh.interface.ts @@ -0,0 +1,64 @@ +import { UUID } from "crypto"; + +export interface DecodedVeh { + // Basic vehicle information + plate_no?: string; + plate_st?: string; + v_vin?: string; + v_model_yr?: string; + v_make_desc?: string; + v_model_desc?: string; + v_color?: string; + kmin?: number; + area_of_damage?: { + impact1?: string; + impact2?: string; + }; + // Complete vehicle data object + vehicle?: { data: VehicleRecordInterface }; +} + +export interface VehicleRecordInterface { + // Area of damage information + area_of_damage?: { + impact1?: string; + impact2?: string; + }; + // Paint code information + v_paint_codes: { + paint_cd1: string; + paint_cd2: string; + paint_cd3: string; + }; + // Vehicle information from DBF file + db_v_code?: string; + plate_no?: string; + plate_st?: string; + v_vin?: string; + v_cond: string; + v_prod_dt?: Date; + v_model_yr: string; + v_makecode: string; + v_make_desc?: string; + v_model?: string; + v_model_desc?: string; + v_type: string; + v_bstyle?: string; + v_trimcode?: string; + trim_color?: string; + v_mldgcode?: string; + v_engine?: string; + v_mileage?: number; //TODO: This can sometimes come in as UNK. + v_color?: string; + v_tone?: string; + v_stage?: string; + shopid: UUID; + + //These are removed during business logic processing. + v_makedesc?: string; + impact_1?: string; + impact_2?: string; + paint_cd1?: string; + paint_cd2?: string; + paint_cd3?: string; +} diff --git a/src/main/decoder/decode-veh.ts b/src/main/decoder/decode-veh.ts new file mode 100644 index 0000000..bdba630 --- /dev/null +++ b/src/main/decoder/decode-veh.ts @@ -0,0 +1,145 @@ +import { DBFFile } from "dbffile"; +import log from "electron-log/main"; +import _ from "lodash"; +import deepLowerCaseKeys from "../../util/deepLowercaseKeys"; +import { DecodedVeh, VehicleRecordInterface } from "./decode-veh.interface"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import store from "../store/store"; +import typeCaster from "../../util/typeCaster"; +import { platform } from "@electron-toolkit/utils"; +import { findFileCaseInsensitive } from "./decoder-utils"; + +const DecodeVeh = async ( + extensionlessFilePath: string, +): Promise => { + let dbf: DBFFile | null = null; + if (platform.isWindows) { + try { + dbf = await DBFFile.open(`${extensionlessFilePath}V.VEH`); + } catch (error) { + log.error("Error opening VEH File.", errorTypeCheck(error)); + dbf = await DBFFile.open(`${extensionlessFilePath}.VEH`); + log.log("Found VEH file using regular CIECA Id."); + } + + if (!dbf) { + log.error(`Could not find any VEH files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any VEH files at ${extensionlessFilePath}`, + ); + } + } else { + const possibleExtensions: string[] = ["v.veh", ".veh"]; + const filePath = await findFileCaseInsensitive( + extensionlessFilePath, + possibleExtensions, + ); + try { + if (!filePath) { + log.error(`Could not find any VEH files at ${extensionlessFilePath}`); + throw new Error( + `Could not find any VEH files at ${extensionlessFilePath}`, + ); + } + dbf = await DBFFile.open(filePath, { readMode: "loose" }); + } catch (error) { + log.error("Error opening VEH File.", errorTypeCheck(error)); + throw error; + } + } + const rawDBFRecord = await dbf.readRecords(1); + + //AD2 will always have only 1 row. + //Commented lines have been cross referenced with existing partner fields. + + //typeCaster is required as the previous partner sent some of these values toString, and the database was made accordingly rather than keeping their original type. + //Alternative is to change the database schema to match the original type. + const rawVehData: VehicleRecordInterface = typeCaster( + deepLowerCaseKeys( + _.pick(rawDBFRecord[0], [ + //TODO: Add typings for EMS File Formats. + "IMPACT_1", + "IMPACT_2", + "DB_V_CODE", + "PLATE_NO", + "PLATE_ST", + "V_VIN", + "V_COND", + "V_PROD_DT", + "V_MODEL_YR", + "V_MAKECODE", + "V_MAKEDESC", + "V_MODEL", + "V_TYPE", + "V_BSTYLE", + "V_TRIMCODE", + "TRIM_COLOR", + "V_MLDGCODE", + "V_ENGINE", + "V_MILEAGE", + "V_COLOR", + "V_TONE", + "V_STAGE", + "PAINT_CD1", + "PAINT_CD2", + "PAINT_CD3", + ]), + ), + { + v_tone: "string", + v_stage: "string", + }, + ); + + //Apply business logic transfomrations. + + //An old error where the column had an extra underscore. + rawVehData.v_make_desc = rawVehData.v_makedesc || rawVehData.v_makecode; //Fallback for US. + delete rawVehData.v_makedesc; + //An old error where the column had an extra underscore. + rawVehData.v_model_desc = rawVehData.v_model; + delete rawVehData.v_model; + + //Consolidate Area of Damage. + const area_of_damage = { + impact1: rawVehData.impact_1 ?? "", + impact2: rawVehData.impact_2 ?? "", + }; + delete rawVehData.impact_1; + delete rawVehData.impact_2; + + const kmin = rawVehData.v_mileage ?? 0; + delete rawVehData.v_mileage; + + //Consolidate Paint Code information. + rawVehData.v_paint_codes = { + paint_cd1: rawVehData.paint_cd1 ?? "", + paint_cd2: rawVehData.paint_cd2 ?? "", + paint_cd3: rawVehData.paint_cd3 ?? "", + }; + delete rawVehData.paint_cd1; + delete rawVehData.paint_cd2; + delete rawVehData.paint_cd3; + + rawVehData.shopid = store.get("app.bodyshop.id"); + + //Aggregate the vehicle data to be stamped onto the job record. + const jobVehicleData: DecodedVeh = { + plate_no: rawVehData.plate_no, + plate_st: rawVehData.plate_st, + v_vin: rawVehData.v_vin, + v_model_yr: rawVehData.v_model_yr, + v_make_desc: rawVehData.v_make_desc, + v_model_desc: rawVehData.v_model_desc, + v_color: rawVehData.v_color, + kmin: kmin, + area_of_damage: area_of_damage, + vehicle: { + data: rawVehData, + }, + }; + + return jobVehicleData; +}; + +export default DecodeVeh; diff --git a/src/main/decoder/decoder-utils.ts b/src/main/decoder/decoder-utils.ts new file mode 100644 index 0000000..73bf777 --- /dev/null +++ b/src/main/decoder/decoder-utils.ts @@ -0,0 +1,47 @@ +import log from "electron-log/main"; +import fs from "fs"; +import path from "path"; + +const findFileCaseInsensitive = async ( + extensionlessFilePath: string, + extensions: string[], +): Promise => { + const directory: string = path.dirname(extensionlessFilePath); + try { + const matchingFiles = fs.readdirSync(directory).filter((file: string) => { + return ( + extensions.some((ext) => + file.toLowerCase().endsWith(ext.toLowerCase()), + ) && + path + .basename(file, path.extname(file)) + .toLowerCase() + .startsWith(path.basename(extensionlessFilePath).toLowerCase()) + ); + }); + const files: string[] = []; + matchingFiles.forEach((file) => { + const fullPath = path.join(directory, file); + files.push(fullPath); + }); + + // Return the first matching file if needed + if (files.length > 0) { + return files[0]; + } + } catch (error) { + log.error(`Failed to read directory ${directory}:`, error); + throw error; + } + + return null; +}; + +const getFilePathWithoutExtension = (filePath: string): string => { + return path.join( + path.dirname(filePath), + path.basename(filePath, path.extname(filePath)), + ); +}; + +export { findFileCaseInsensitive }; diff --git a/src/main/decoder/decoder.ts b/src/main/decoder/decoder.ts new file mode 100644 index 0000000..6973c1a --- /dev/null +++ b/src/main/decoder/decoder.ts @@ -0,0 +1,431 @@ +import { platform } from "@electron-toolkit/utils"; +import { UUID } from "crypto"; +import { Notification, shell } from "electron"; +import log from "electron-log/main"; +import fs from "fs"; +import _ from "lodash"; +import path from "path"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import client from "../graphql/graphql-client"; +import { + INSERT_AVAILABLE_JOB_TYPED, + InsertAvailableJobResult, + QUERY_JOB_BY_CLM_NO_TYPED, + QUERY_VEHICLE_BY_VIN_TYPED, + QueryJobByClmNoResult, + VehicleQueryResult, +} from "../graphql/queries"; +import store from "../store/store"; +import DecodeAD1 from "./decode-ad1"; +import { DecodedAd1 } from "./decode-ad1.interface"; +import DecodeAD2 from "./decode-ad2"; +import { DecodedAD2 } from "./decode-ad2.interface"; +import DecodeEnv from "./decode-env"; +import { DecodedEnv } from "./decode-env.interface"; +import DecodeLin from "./decode-lin"; +import { DecodedLin } from "./decode-lin.interface"; +import DecodePfh from "./decode-pfh"; +import { DecodedPfh } from "./decode-pfh.interface"; +import DecodePfl from "./decode-pfl"; +import { DecodedPfl } from "./decode-pfl.interface"; +import DecodePfm from "./decode-pfm"; +import { DecodedPfm } from "./decode-pfm.interface"; +import DecodePfo from "./decode-pfo"; +import { DecodedPfo } from "./decode-pfo.interface"; +import DecodePfp from "./decode-pfp"; +import { DecodedPfp } from "./decode-pfp.interface"; +import DecodePft from "./decode-pft"; +import { DecodedPft } from "./decode-pft.interface"; +import DecodeStl from "./decode-stl"; +import { DecodedStl } from "./decode-stl.interface"; +import DecodeTtl from "./decode-ttl"; +import { DecodedTtl } from "./decode-ttl.interface"; +import DecodeVeh from "./decode-veh"; +import { DecodedVeh } from "./decode-veh.interface"; +import setAppProgressbar from "../util/setAppProgressBar"; +import UploadEmsToS3 from "./emsbackup"; + +async function ImportJob(filepath: string): Promise { + const parsedFilePath = path.parse(filepath); + const extensionlessFilePath = path.join( + parsedFilePath.dir, + parsedFilePath.name, + ); + log.debug("Importing Job", extensionlessFilePath); + + try { + await WaitForAllFiles(extensionlessFilePath, requiredExtensions); + + //The below all end up returning parts of the job object. + //Some of them return additional info - e.g. owner or vehicle record data at both the job and corresponding table level. + setAppProgressbar(0.1); + const env: DecodedEnv = await DecodeEnv(extensionlessFilePath); + setAppProgressbar(0.15); + const ad1: DecodedAd1 = await DecodeAD1(extensionlessFilePath); + setAppProgressbar(0.2); + const ad2: DecodedAD2 = await DecodeAD2(extensionlessFilePath); + setAppProgressbar(0.25); + const veh: DecodedVeh = await DecodeVeh(extensionlessFilePath); + setAppProgressbar(0.3); + const lin: DecodedLin = await DecodeLin(extensionlessFilePath); + setAppProgressbar(0.35); + const pfh: DecodedPfh = await DecodePfh(extensionlessFilePath); + setAppProgressbar(0.4); + const pfl: DecodedPfl = await DecodePfl(extensionlessFilePath); + setAppProgressbar(0.45); + const pft: DecodedPft = await DecodePft(extensionlessFilePath); + setAppProgressbar(0.5); + const pfm: DecodedPfm = await DecodePfm(extensionlessFilePath); + setAppProgressbar(0.55); + const pfo: DecodedPfo = await DecodePfo(extensionlessFilePath); // TODO: This will be the `cieca_pfo` object + setAppProgressbar(0.6); + const stl: DecodedStl = await DecodeStl(extensionlessFilePath); // TODO: This will be the `cieca_stl` object + setAppProgressbar(0.65); + const ttl: DecodedTtl = await DecodeTtl(extensionlessFilePath); + setAppProgressbar(0.7); + const pfp: DecodedPfp = await DecodePfp(extensionlessFilePath); + setAppProgressbar(0.75); + + const jobObjectUncleaned: RawJobDataObject = { + ...env, + ...ad1, + ...ad2, + ...veh, + ...lin, + ...pfh, + ...pfl, + ...pft, + ...pfm, + ...pfo, + ...stl, + ...ttl, + ...pfp, + shopid: store.get("app.bodyshop.id") as UUID, + }; + + // Replace owner information with claimant information if necessary + const jobObject = ReplaceOwnerInfoWithClaimant(jobObjectUncleaned); + setAppProgressbar(0.8); + + if (import.meta.env.DEV) { + // Save jobObject to a timestamped JSON file + const timestamp = new Date() + .toISOString() + .replace(/:/g, "-") + .replace(/\..+/, ""); + const fileName = `job_${timestamp}_${parsedFilePath.name}.json`; + const logsDir = path.join(process.cwd(), "logs"); + + // Create logs directory if it doesn't exist + if (!fs.existsSync(logsDir)) { + fs.mkdirSync(logsDir, { recursive: true }); + } + + const filePath = path.join(logsDir, fileName); + fs.writeFileSync(filePath, JSON.stringify(jobObject, null, 2), "utf8"); + log.info(`Job data saved to: ${filePath}`); + } + + const newAvailableJob: AvailableJobSchema = { + uploaded_by: store.get("user.email"), + bodyshopid: store.get("app.bodyshop.id"), + cieca_id: jobObject.ciecaid, + est_data: jobObject, + ownr_name: `${jobObject.ownr_fn} ${jobObject.ownr_ln} ${jobObject.ownr_co_nm}`, + ins_co_nm: jobObject.ins_co_nm, + vehicle_info: `${jobObject.v_model_yr} ${jobObject.v_make_desc} ${jobObject.v_model_desc}`, + clm_no: jobObject.clm_no, + clm_amt: jobObject.clm_total, + // source_system: jobObject.source_system, //TODO: Add back source system if needed. + issupplement: false, + jobid: null, + }; + setAppProgressbar(0.85); + + const existingVehicleRecord: VehicleQueryResult = await client.request( + QUERY_VEHICLE_BY_VIN_TYPED, + { + vin: jobObject.v_vin, + }, + ); + + if (existingVehicleRecord.vehicles.length > 0) { + delete newAvailableJob.est_data.vehicle; + newAvailableJob.est_data.vehicleid = existingVehicleRecord.vehicles[0].id; + } + + console.log("Available Job record to upload;", newAvailableJob); + + setAppProgressbar(0.95); + if (jobObject.clm_no) { + const existingJobRecord: QueryJobByClmNoResult = await client.request( + QUERY_JOB_BY_CLM_NO_TYPED, + { clm_no: jobObject.clm_no }, + ); + + if (existingJobRecord.jobs.length > 0) { + newAvailableJob.issupplement = true; + newAvailableJob.jobid = existingJobRecord.jobs[0].id; + } + } + + const insertRecordResult: InsertAvailableJobResult = await client.request( + INSERT_AVAILABLE_JOB_TYPED, + { + jobInput: [newAvailableJob], + }, + ); + setAppProgressbar(-1); + const uploadNotification = new Notification({ + title: "Job Imported", + //subtitle: `${newAvailableJob.ownr_name} - ${newAvailableJob.vehicle_info}`, + body: `${newAvailableJob.ownr_name} - ${newAvailableJob.vehicle_info}. Click to view.`, + actions: [{ text: "View Job", type: "button" }], + }); + uploadNotification.on("click", () => { + shell.openExternal( + `${ + store.get("app.isTest") + ? import.meta.env.VITE_FE_URL_TEST + : import.meta.env.VITE_FE_URL + }/manage/available`, + ); + }); + uploadNotification.show(); + + log.debug("Job inserted", insertRecordResult); + + UploadEmsToS3({ + extensionlessFilePath, + bodyshopid: newAvailableJob.bodyshopid, + ciecaid: jobObject.ciecaid ?? "", + clm_no: jobObject.clm_no ?? "", + ownr_ln: jobObject.ownr_ln ?? "", + }); + } catch (error) { + log.error("Error encountered while decoding job. ", errorTypeCheck(error)); + const uploadNotificationFailure = new Notification({ + title: "Job Upload Failure", + body: errorTypeCheck(error).message, //TODO: Remove after debug. + }); + + uploadNotificationFailure.show(); + } +} + +export default ImportJob; + +export interface RawJobDataObject + extends DecodedEnv, + DecodedAd1, + DecodedAD2, + DecodedVeh, + DecodedLin, + DecodedPfh, + DecodedPfl, + DecodedPft, + DecodedPfm, + DecodedPfo, + DecodedStl, + DecodedTtl, + DecodedPfp { + vehicleid?: UUID; + shopid: UUID; +} + +export interface AvailableJobSchema { + uploaded_by: string; + bodyshopid: UUID; + cieca_id?: string; + est_data: RawJobDataObject; + ownr_name: string; + ins_co_nm?: string; + vehicle_info: string; + clm_no?: string; + clm_amt: number; + source_system?: string | null; + issupplement: boolean; + jobid: UUID | null; +} + +async function WaitForAllFiles( + baseFilePath: string, + requiredExtensions: string[], + maxRetries: number = 5, + backoffMs: number = 1000, +): Promise { + for (let attempt = 1; attempt <= maxRetries; attempt++) { + //Get all files in directory if Mac. + let filesInDir: string[] = []; + if (platform.isMacOS) { + const dir: string = path.dirname(baseFilePath); + filesInDir = fs.readdirSync(dir).map((file) => file.toLowerCase()); + } + + const missingFiles = requiredExtensions.filter((ext) => { + const filePath: string = `${baseFilePath}.${ext}`; + const filePathA: string = `${baseFilePath}A.${ext}`; + const filePathB: string = `${baseFilePath}B.${ext}`; + const filePathV: string = `${baseFilePath}V.${ext}`; + + if (!platform.isWindows) { + // Case-insensitive check for macOS/Linux + const baseName: string = path.basename(baseFilePath); + + return !( + filesInDir.includes(`${baseName}.${ext}`.toLowerCase()) || + filesInDir.includes(`${baseName}A.${ext}`.toLowerCase()) || + filesInDir.includes(`${baseName}B.${ext}`.toLowerCase()) || + filesInDir.includes(`${baseName}V.${ext}`.toLowerCase()) + ); + } else { + // Case-sensitive check for other platforms + return !( + fs.existsSync(filePath) || + fs.existsSync(filePathA) || + fs.existsSync(filePathB) || + fs.existsSync(filePathV) + ); + } + }); + + if (missingFiles.length === 0) { + return; // All files are present + } + + log.debug( + `Attempt ${attempt}: Missing files: ${missingFiles.join(", ")}. Retrying in ${backoffMs}ms...`, + ); + + if (attempt < maxRetries) { + await new Promise((resolve) => setTimeout(resolve, backoffMs)); + backoffMs *= 2; // Exponential backoff + } else { + throw new Error( + `The set of files is not valid. Missing files for CIECA ID ${baseFilePath}: ${missingFiles.join(", ")}`, + ); + } + } +} + +const requiredExtensions = [ + "env", + "ad1", + "ad2", + "veh", + "lin", + "pfh", + "pfl", + "pft", + "pfm", + "pfo", + "stl", + "ttl", + "pfp", +]; + +export function ReplaceOwnerInfoWithClaimant< + T extends Partial< + Pick< + RawJobDataObject, + | "ownr_ln" + | "ownr_fn" + | "ownr_co_nm" + | "ownr_title" + | "ownr_co_nm" + | "ownr_addr1" + | "ownr_addr2" + | "ownr_city" + | "ownr_st" + | "ownr_zip" + | "ownr_ctry" + | "ownr_ph1" + | "ownr_ph2" + | "ownr_ea" + | "clmt_ln" + | "clmt_fn" + | "clmt_title" + | "clmt_co_nm" + | "clmt_addr1" + | "clmt_addr2" + | "clmt_city" + | "clmt_st" + | "clmt_zip" + | "clmt_ctry" + | "clmt_ph1" + | "clmt_ph2" + | "clmt_ea" + | "insd_ln" + | "insd_fn" + | "insd_title" + | "insd_co_nm" + | "insd_addr1" + | "insd_addr2" + | "insd_city" + | "insd_st" + | "insd_zip" + | "insd_ctry" + | "insd_ph1" + | "insd_ph2" + | "insd_ea" + | "owner" + > + >, +>(jobObject: T): T { + // Promote claimant data first if owner identity is entirely missing; otherwise fallback to insured data. + const identityKeys = ["ln", "fn", "co_nm"] as const; // keys used to determine presence + const copyKeys = [ + "ln", + "fn", + "title", + "co_nm", + "addr1", + "addr2", + "city", + "st", + "zip", + "ctry", + "ph1", + "ph2", + "ea", + ] as const; // full set of fields to copy/delete + + const ownerMissing = identityKeys.every((k) => + _.isEmpty((jobObject as any)[`ownr_${k}`]), + ); + const claimantHasSome = identityKeys.some( + (k) => !_.isEmpty((jobObject as any)[`clmt_${k}`]), + ); + const claimantMissing = identityKeys.every((k) => + _.isEmpty((jobObject as any)[`clmt_${k}`]), + ); + + const { owner } = jobObject as any; // destructure for optional nested updates + + // Copy helper inline (no extra function as requested) + const promote = (sourcePrefix: "clmt" | "insd"): void => { + copyKeys.forEach((suffix) => { + (jobObject as any)[`ownr_${suffix}`] = (jobObject as any)[ + `${sourcePrefix}_${suffix}` + ]; + if (owner?.data) { + owner.data[`ownr_${suffix}`] = (jobObject as any)[ + `${sourcePrefix}_${suffix}` + ]; + } + }); + }; + + if (ownerMissing && claimantHasSome) { + promote("clmt"); + } else if (ownerMissing && claimantMissing) { + promote("insd"); + } + + // Delete the claimant info as it's not needed. + copyKeys.forEach((suffix) => delete (jobObject as any)[`clmt_${suffix}`]); + // Delete the insured info as it's not needed. + copyKeys.forEach((suffix) => delete (jobObject as any)[`insd_${suffix}`]); + + return jobObject; +} diff --git a/src/main/decoder/emsbackup.ts b/src/main/decoder/emsbackup.ts new file mode 100644 index 0000000..69e8fdb --- /dev/null +++ b/src/main/decoder/emsbackup.ts @@ -0,0 +1,104 @@ +import axios from "axios"; +import archiver from "archiver"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { UUID } from "crypto"; +import fs from "fs"; +import path from "path"; +import stream from "stream"; +import { getTokenFromRenderer } from "../graphql/graphql-client"; +import store from "../store/store"; + +async function UploadEmsToS3({ + extensionlessFilePath, + bodyshopid, + clm_no, + ciecaid, + ownr_ln, +}: { + extensionlessFilePath: string; + bodyshopid: UUID; + clm_no: string; + ciecaid: string; + ownr_ln: string; +}): Promise { + // This function is a placeholder for the actual upload logic + try { + const directory = path.dirname(extensionlessFilePath); + const baseFilename = path.basename(extensionlessFilePath); + + // Find all files in the directory that start with the base filename + const filesToZip = fs + .readdirSync(directory) + .filter((file) => file.startsWith(baseFilename)) + .map((file) => path.join(directory, file)); + + if (filesToZip.length === 0) { + console.error("No files found to zip."); + return false; + } + + // Create a zip archive in memory + const archive = archiver("zip", { zlib: { level: 9 } }); + const zipBuffer = await new Promise((resolve, reject) => { + const buffers: Buffer[] = []; + const writableStream = new stream.Writable({ + write(chunk, _encoding, callback) { + buffers.push(chunk); + callback(); + }, + }); + + writableStream.on("finish", () => resolve(Buffer.concat(buffers))); + writableStream.on("error", reject); + + archive.pipe(writableStream); + + // Append files to the archive + filesToZip.forEach((file) => { + archive.file(file, { name: path.basename(file) }); + }); + + archive.finalize(); + }); + + // Get the presigned URL from the server + const presignedUrlResponse = await axios.post( + `${ + store.get("app.isTest") + ? import.meta.env.VITE_API_TEST_URL + : import.meta.env.VITE_API_URL + }/emsupload`, + { + bodyshopid, + ciecaid, + clm_no, + ownr_ln, + }, + { + headers: { + Authorization: `Bearer ${await getTokenFromRenderer()}`, + }, + }, + ); + + const presignedUrl = presignedUrlResponse.data?.presignedUrl; + if (!presignedUrl) { + console.error("Failed to retrieve presigned URL."); + return false; + } + + // Upload the zip file to S3 using the presigned URL + await axios.put(presignedUrl, zipBuffer, { + headers: { + "Content-Type": "application/zip", + }, + }); + } catch (error) { + console.error("Error uploading EMS to S3:", errorTypeCheck(error)); + return false; + } + + return true; // Return true if the upload is successful +} + +export default UploadEmsToS3; diff --git a/src/main/decoder/folder-scan.ts b/src/main/decoder/folder-scan.ts new file mode 100644 index 0000000..fc53ef8 --- /dev/null +++ b/src/main/decoder/folder-scan.ts @@ -0,0 +1,57 @@ +import path from "path"; +import { GetAllEnvFiles } from "../watcher/watcher"; +import DecodeAD1 from "./decode-ad1"; +import DecodeAD2 from "./decode-ad2"; +import DecodeEnv from "./decode-env"; +import DecodeVeh from "./decode-veh"; +import { ReplaceOwnerInfoWithClaimant } from "./decoder"; + +const folderScan = async (): Promise => { + //Get all ENV files for watched paths. + const allEnvFiles = GetAllEnvFiles(); + //Run a simplified decode on them + const returnedFiles: FolderScanResult[] = []; + + for (const filepath of allEnvFiles) { + const parsedFilePath = path.parse(filepath); + const extensionlessFilePath = path.join( + parsedFilePath.dir, + parsedFilePath.name, + ); + + const rawJob = { + ...(await DecodeEnv(extensionlessFilePath)), + ...(await DecodeAD1(extensionlessFilePath)), + ...(await DecodeAD2(extensionlessFilePath)), + ...(await DecodeVeh(extensionlessFilePath)), + }; + const job = ReplaceOwnerInfoWithClaimant(rawJob); + + const scanResult: FolderScanResult = { + id: job.ciecaid, + filepath: filepath, + cieca_id: job.ciecaid, + clm_no: job.clm_no, + owner: `${job.ownr_fn} ${job.ownr_ln} ${job.ownr_co_nm}`.trim(), + vehicle: + `${job.vehicle?.data.v_model_yr} ${job.vehicle?.data.v_make_desc} ${job.vehicle?.data.v_model_desc}`.trim(), + ins_co_nm: job.ins_co_nm, + }; + + returnedFiles.push(scanResult); + } + //Build up the object and return it + return returnedFiles; +}; + +export interface FolderScanResult { + id?: string; + filepath: string; + cieca_id?: string; + clm_no?: string; + owner: string; + ins_co_nm?: string; + vehicle: string; +} + +export default folderScan; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-ad1.ts b/src/main/ems-parts-order/ems-parts-order-generate-ad1.ts new file mode 100644 index 0000000..03905e7 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-ad1.ts @@ -0,0 +1,158 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { ad1FieldLineDescriptors } from "../util/ems-interface/fielddescriptors/ad1-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateAd1File = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = [ + { + INS_CO_ID: partsOrder.job.ins_co_nm, + INS_CO_NM: partsOrder.job.ins_co_nm, + INS_ADDR1: partsOrder.job.ins_addr1, + INS_ADDR2: partsOrder.job.ins_addr2, + INS_CITY: partsOrder.job.ins_city, + INS_ST: partsOrder.job.ins_st, + INS_ZIP: partsOrder.job.ins_zip, + INS_CTRY: partsOrder.job.ins_ctry, + INS_PH1: partsOrder.job.ins_ph1, + INS_PH1X: partsOrder.job.ins_ph1x, + INS_PH2: partsOrder.job.ins_ph2, + INS_PH2X: partsOrder.job.ins_ph2x, + INS_FAX: partsOrder.job.ins_fax, + INS_FAXX: partsOrder.job.ins_faxx, + INS_CT_LN: partsOrder.job.ins_ct_ln, + INS_CT_FN: partsOrder.job.ins_ct_fn, + INS_TITLE: partsOrder.job.ins_title, + INS_CT_PH: partsOrder.job.ins_ct_ph, + INS_CT_PHX: partsOrder.job.ins_ct_phx, + INS_EA: partsOrder.job.ins_ea, + INS_MEMO: partsOrder.job.ins_memo, + POLICY_NO: partsOrder.job.policy_no, + DED_AMT: partsOrder.job.ded_amt, + DED_STATUS: partsOrder.job.ded_status, + ASGN_NO: partsOrder.job.asgn_no, + ASGN_DATE: partsOrder.job.asgn_date + ? new Date(partsOrder.job.asgn_date) + : null, + ASGN_TYPE: partsOrder.job.asgn_type, + CLM_NO: partsOrder.job.clm_no, + CLM_OFC_ID: partsOrder.job.clm_ofc_id, + CLM_OFC_NM: partsOrder.job.clm_ofc_nm, + CLM_ADDR1: partsOrder.job.clm_addr1, + CLM_ADDR2: partsOrder.job.clm_addr2, + CLM_CITY: partsOrder.job.clm_city, + CLM_ST: partsOrder.job.clm_st, + CLM_ZIP: partsOrder.job.clm_zip, + CLM_CTRY: partsOrder.job.clm_ctry, + CLM_PH1: partsOrder.job.clm_ph1, + CLM_PH1X: partsOrder.job.clm_ph1x, + CLM_PH2: partsOrder.job.clm_ph2, + CLM_PH2X: partsOrder.job.clm_ph2x, + CLM_FAX: partsOrder.job.clm_fax, + CLM_FAXX: partsOrder.job.clm_faxx, + CLM_CT_LN: partsOrder.job.clm_ct_ln, + CLM_CT_FN: partsOrder.job.clm_ct_fn, + CLM_TITLE: partsOrder.job.clm_title, + CLM_CT_PH: partsOrder.job.clm_ct_ph, + CLM_CT_PHX: partsOrder.job.clm_ct_phx, + CLM_EA: partsOrder.job.clm_ea, + PAYEE_NMS: partsOrder.job.payee_nms, + PAY_TYPE: partsOrder.job.pay_type, + PAY_DATE: partsOrder.job.pay_date, + PAY_CHKNM: null, // Explicitly set to null as in original code + PAY_AMT: null, // Explicitly set to null as in original code + PAY_MEMO: partsOrder.job.pay_memo, + AGT_CO_ID: partsOrder.job.agt_co_id, + AGT_CO_NM: partsOrder.job.agt_co_nm, + AGT_ADDR1: partsOrder.job.agt_addr1, + AGT_ADDR2: partsOrder.job.agt_addr2, + AGT_CITY: partsOrder.job.agt_city, + AGT_ST: partsOrder.job.agt_st, + AGT_ZIP: partsOrder.job.agt_zip, + AGT_CTRY: partsOrder.job.agt_ctry, + AGT_PH1: partsOrder.job.agt_ph1, + AGT_PH1X: partsOrder.job.agt_ph1x, + AGT_PH2: partsOrder.job.agt_ph2, + AGT_PH2X: partsOrder.job.agt_ph2x, + AGT_FAX: partsOrder.job.agt_fax, + AGT_FAXX: partsOrder.job.agt_faxx, + AGT_CT_LN: partsOrder.job.agt_ct_ln, + AGT_CT_FN: partsOrder.job.agt_ct_fn, + AGT_CT_PH: partsOrder.job.agt_ct_ph, + AGT_CT_PHX: partsOrder.job.agt_ct_phx, + AGT_EA: partsOrder.job.agt_ea, + AGT_LIC_NO: partsOrder.job.agt_lic_no, + LOSS_DATE: partsOrder.job.loss_date + ? new Date(partsOrder.job.loss_date) + : null, + LOSS_CAT: null, // Explicitly set to null as in original code + LOSS_TYPE: null, // Explicitly set to null as in original code + LOSS_DESC: partsOrder.job.loss_desc, + THEFT_IND: null, // Explicitly set to null as in original code + CAT_NO: partsOrder.job.cat_no, + TLOS_IND: null, // Explicitly set to null as in original code + LOSS_MEMO: partsOrder.job.loss_memo, + CUST_PR: partsOrder.job.cust_pr, + INSD_LN: partsOrder.job.insd_ln, + INSD_FN: partsOrder.job.insd_fn, + INSD_TITLE: partsOrder.job.insd_title, + INSD_CO_NM: partsOrder.job.insd_co_nm, + INSD_ADDR1: partsOrder.job.insd_addr1, + INSD_ADDR2: partsOrder.job.insd_addr2, + INSD_CITY: partsOrder.job.insd_city, + INSD_ST: partsOrder.job.insd_st, + INSD_ZIP: partsOrder.job.insd_zip, + INSD_CTRY: partsOrder.job.insd_ctry, + INSD_PH1: partsOrder.job.insd_ph1, + INSD_PH1X: partsOrder.job.insd_ph1x, + INSD_PH2: partsOrder.job.insd_ph2, + INSD_PH2X: partsOrder.job.insd_ph2x, + INSD_FAX: partsOrder.job.insd_fax, + INSD_FAXX: partsOrder.job.insd_faxx, + INSD_EA: partsOrder.job.insd_ea, + OWNR_LN: partsOrder.job.ownr_ln, + OWNR_FN: partsOrder.job.ownr_fn, + OWNR_TITLE: partsOrder.job.ownr_title, + OWNR_CO_NM: partsOrder.job.ownr_co_nm, + OWNR_ADDR1: partsOrder.job.ownr_addr1, + OWNR_ADDR2: partsOrder.job.ownr_addr2, + OWNR_CITY: partsOrder.job.ownr_city, + OWNR_ST: partsOrder.job.ownr_st, + OWNR_ZIP: partsOrder.job.ownr_zip, + OWNR_CTRY: partsOrder.job.ownr_ctry, + OWNR_PH1: partsOrder.job.ownr_ph1, + OWNR_PH1X: partsOrder.job.ownr_ph1x, + OWNR_PH2: partsOrder.job.ownr_ph2, + OWNR_PH2X: partsOrder.job.ownr_ph2x, + OWNR_FAX: partsOrder.job.ownr_fax, + OWNR_FAXX: partsOrder.job.ownr_faxx, + OWNR_EA: partsOrder.job.ownr_ea, + }, + ]; + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.AD1`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.AD1`), + ad1FieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} AD1 file records added.`); + return true; + } catch (error) { + console.error("Error generating AD1 file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateAd1File; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-ad2.ts b/src/main/ems-parts-order/ems-parts-order-generate-ad2.ts new file mode 100644 index 0000000..c90234e --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-ad2.ts @@ -0,0 +1,67 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { ad2FieldLineDescriptors } from "../util/ems-interface/fielddescriptors/ad2-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateAd2File = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = [ + { + EST_CO_NM: partsOrder.job.est_co_nm, + EST_ADDR1: partsOrder.job.est_addr1, + EST_ADDR2: partsOrder.job.est_addr2, + EST_CITY: partsOrder.job.est_city, + EST_ST: partsOrder.job.est_st, + EST_ZIP: partsOrder.job.est_zip, + EST_CTRY: partsOrder.job.est_ctry, + EST_PH1: partsOrder.job.est_ph1, + EST_CT_LN: partsOrder.job.est_ct_ln, + EST_CT_FN: partsOrder.job.est_ct_fn, + EST_EA: partsOrder.job.est_ea, + CLMT_ADDR1: partsOrder.job.clm_addr1, + CLMT_ADDR2: partsOrder.job.clm_addr2, + CLMT_CITY: partsOrder.job.clm_city, + CLMT_ST: partsOrder.job.clm_st, + CLMT_ZIP: partsOrder.job.clm_zip, + CLMT_CTRY: partsOrder.job.clm_ctry, + CLMT_PH1: partsOrder.job.clm_ph1, + CLMT_PH1X: partsOrder.job.clm_ph1x, + CLMT_PH2: partsOrder.job.clm_ph2, + CLMT_PH2X: partsOrder.job.clm_ph2x, + CLMT_FAX: partsOrder.job.clm_fax, + CLMT_FAXX: partsOrder.job.clm_faxx, + CLMT_LN: partsOrder.job.clm_ct_ln, + CLMT_FN: partsOrder.job.clm_ct_fn, + CLMT_TITLE: partsOrder.job.clm_title, + CLMT_CT_PH: partsOrder.job.clm_ct_ph, + CLMT_CT_PHX: partsOrder.job.clm_ct_phx, + CLMT_EA: partsOrder.job.clm_ea, + RF_CO_NM: partsOrder.job.bodyshop.shopname, + }, + ]; + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.AD2`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.AD2`), + ad2FieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} AD2 file records added.`); + return true; + } catch (error) { + console.error("Error generating AD2 file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateAd2File; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-env.ts b/src/main/ems-parts-order/ems-parts-order-generate-env.ts new file mode 100644 index 0000000..34b9ec5 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-env.ts @@ -0,0 +1,80 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { envFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/env-field-descriptor"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateEnvFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const dateNow = new Date(); + const formatTime = (date: Date): string => + `${date.getHours().toString().padStart(2, "0")}${date.getMinutes().toString().padStart(2, "0")}${date.getSeconds().toString().padStart(2, "0")}`; + + const { + job: { ro_number, ciecaid }, + } = partsOrder; + + // Find the highest line_ind value + const lineInds = partsOrder.parts_order_lines.map( + (line) => line.jobline.line_ind, + ); + const getNumber = (str: string): number => { + const match = str.match(/(\d+)$/); + return match ? parseInt(match[1], 10) : 0; + }; + const highestLineInd = lineInds.reduce( + (max, current) => (getNumber(current) > getNumber(max) ? current : max), + lineInds[0] || "", + ); + + const records = [ + { + EST_SYSTEM: "M", + SW_VERSION: "25.3", + DB_VERSION: "OCT_25_V", + DB_DATE: dateNow, + RO_ID: ro_number, + ESTFILE_ID: ciecaid, + SUPP_NO: highestLineInd ? getNumber(highestLineInd).toString() : "1", + EST_CTRY: "CAN", + TOP_SECRET: "00000000-0000-0000-0000-000000000000", + TRANS_TYPE: highestLineInd ? highestLineInd.charAt(0) : "S", + STATUS: false, + CREATE_DT: dateNow, + CREATE_TM: formatTime(dateNow), + TRANSMT_DT: dateNow, + TRANSMT_TM: formatTime(dateNow), + INCL_ADMIN: true, + INCL_VEH: true, + INCL_EST: true, + INCL_PROFL: false, + INCL_TOTAL: false, + INCL_VENDR: false, + EMS_VER: "2.0", + }, + ]; + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.ENV`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.ENV`), + envFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} ENV file records added.`); + return true; + } catch (error) { + console.error("Error generating ENV file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateEnvFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-lin.ts b/src/main/ems-parts-order/ems-parts-order-generate-lin.ts new file mode 100644 index 0000000..791909f --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-lin.ts @@ -0,0 +1,85 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; +import { linFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/lin-field-descriptors"; + +const EmsPartsOrderGenerateLinFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = partsOrder.parts_order_lines.map((partsOrderLine) => ({ + LINE_NO: partsOrderLine.jobline?.line_no, + LINE_IND: partsOrderLine.jobline?.line_ind, + LINE_REF: partsOrderLine.jobline?.line_ref, + TRAN_CODE: partsOrderLine.jobline?.tran_code ?? "1", + DB_REF: partsOrderLine.jobline?.db_ref, + UNQ_SEQ: partsOrderLine.jobline?.unq_seq, + PART_DES_J: false, + LINE_DESC: partsOrderLine.jobline?.line_desc, + PART_TYPE: + partsOrderLine.priceChange === true + ? partsOrderLine.part_type + : partsOrderLine.jobline?.part_type, + GLASS_FLAG: partsOrderLine.jobline?.glass_flag, + OEM_PARTNO: partsOrderLine.jobline?.oem_partno, + PRICE_INC: partsOrderLine.jobline?.price_inc, + ALT_PART_I: partsOrderLine.jobline?.alt_part_i, + TAX_PART: partsOrderLine.jobline?.tax_part, + DB_PRICE: partsOrderLine.jobline?.db_price, + ACT_PRICE: + partsOrderLine.priceChange === true + ? partsOrderLine.act_price + : partsOrderLine.jobline?.act_price, + PRICE_J: partsOrderLine.jobline?.price_j, + CERT_PART: partsOrderLine.jobline?.cert_part, + PART_QTY: partsOrderLine.jobline?.part_qty, + ALT_CO_ID: partsOrderLine.jobline?.alt_co_id, + ALT_PARTNO: partsOrderLine.jobline?.alt_partno, + ALT_OVERRD: partsOrderLine.jobline?.alt_overrd, + ALT_PARTM: partsOrderLine.jobline?.alt_partm, + PRT_DSMK_P: partsOrderLine.jobline?.prt_dsmk_p, + PRT_DSMK_M: partsOrderLine.jobline?.prt_dsmk_m, + MOD_LBR_TY: partsOrderLine.jobline?.mod_lbr_ty, + DB_HRS: partsOrderLine.jobline?.db_hrs, + MOD_LB_HRS: partsOrderLine.jobline?.mod_lb_hrs, + LBR_INC: partsOrderLine.jobline?.lbr_inc, + LBR_OP: partsOrderLine.jobline?.lbr_op, + LBR_HRS_J: partsOrderLine.jobline?.lbr_hrs_j, + LBR_TYP_J: partsOrderLine.jobline?.lbr_typ_j, + LBR_OP_J: partsOrderLine.jobline?.lbr_op_j, + PAINT_STG: partsOrderLine.jobline?.paint_stg, + PAINT_TONE: partsOrderLine.jobline?.paint_tone, + LBR_TAX: partsOrderLine.jobline?.lbr_tax, + LBR_AMT: partsOrderLine.jobline?.lbr_amt, + MISC_AMT: partsOrderLine.jobline?.misc_amt, + MISC_SUBLT: partsOrderLine.jobline?.misc_sublt, + MISC_TAX: partsOrderLine.jobline?.misc_tax, + BETT_TYPE: partsOrderLine.jobline?.bett_type, + BETT_PCTG: partsOrderLine.jobline?.bett_pctg, + BETT_AMT: partsOrderLine.jobline?.bett_amt, + BETT_TAX: partsOrderLine.jobline?.bett_tax, + })); + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.LIN`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.LIN`), + linFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} LIN file records added.`); + return true; + } catch (error) { + console.error("Error generating LIN file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateLinFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pfh.ts b/src/main/ems-parts-order/ems-parts-order-generate-pfh.ts new file mode 100644 index 0000000..689507c --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pfh.ts @@ -0,0 +1,59 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; +import { pfhFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pfh-field-descriptors"; + +const EmsPartsOrderGeneratePfhFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = [ + { + ID_PRO_NAM: "REPAIR FACILITY", // Job.id_pro_nam?.Value + TAX_PRETHR: (partsOrder.job.tax_prethr || 0) * 100, + TAX_THRAMT: (partsOrder.job.tax_thramt || 0) * 100, + TAX_PSTTHR: (partsOrder.job.tax_pstthr || 0) * 100, + TAX_TOW_IN: true, // Job.tax_tow_in?.Value + TAX_TOW_RT: (partsOrder.job.tax_tow_rt || 0) * 100, + TAX_STR_IN: true, // Job.tax_str_in?.Value + TAX_STR_RT: (partsOrder.job.tax_str_rt || 0) * 100, + TAX_SUB_IN: true, // Job.tax_sub_in?.Value + TAX_SUB_RT: (partsOrder.job.tax_sub_rt || 0) * 100, + TAX_BTR_IN: true, // Job.tax_btr_in?.Value + TAX_LBR_RT: + (partsOrder.job.bodyshop?.bill_tax_rates?.state_tax_rate || 0) * 100, + TAX_GST_RT: + (partsOrder.job.bodyshop?.bill_tax_rates?.federal_tax_rate || 0) * + 100, + TAX_GST_IN: true, // Job.tax_gst_in?.Value + ADJ_G_DISC: (partsOrder.job.adj_g_disc || 0) * 100, + ADJ_TOWDIS: (partsOrder.job.adj_towdis || 0) * 100, + ADJ_STRDIS: (partsOrder.job.adj_strdis || 0) * 100, + ADJ_BTR_IN: null, // Job.adj_btr_in?.Value + TAX_PREDIS: (partsOrder.job.tax_predis || 0) * 100, + }, + ]; + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFH`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFH`), + pfhFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFH file records added.`); + return true; + } catch (error) { + console.error("Error generating PFH file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePfhFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pfl.ts b/src/main/ems-parts-order/ems-parts-order-generate-pfl.ts new file mode 100644 index 0000000..ab3b8d9 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pfl.ts @@ -0,0 +1,302 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedPflLine } from "../decoder/decode-pfl.interface"; +import { pflFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pfl-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import uppercaseObjectKeys from "../util/uppercaseObjectKeys"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; +import _ from "lodash"; + +const EmsPartsOrderGeneratePflFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + let records; + + if (partsOrder.job.cieca_pfl && !_.isEmpty(partsOrder.job.cieca_pfl)) { + records = Object.keys(partsOrder.job.cieca_pfl).map((key) => { + const record: DecodedPflLine = partsOrder.job.cieca_pfl[key]; + return uppercaseObjectKeys(record); + }); + } else { + //We don't have the PFL data for an old job, so make it manually. + + records = [ + { + LBR_TYPE: "LAA", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_laa, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAB", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lab, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + + { + LBR_TYPE: "LAD", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lad, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAE", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lae, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAF", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_laf, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAG", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lag, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAM", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lam, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAR", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lar, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAS", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_las, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LAU", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_lau, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LA1", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_la1, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LA2", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_la2, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LA3", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_la3, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + { + LBR_TYPE: "LA4", + LBR_DESC: "", + LBR_RATE: partsOrder.job.rate_la4, + LBR_TAX_IN: true, + LBR_TAXP: null, // Job.bodyshop.bill_tax_rates.state_tax_rate?.Value ?? 0, + LBR_ADJP: 0, + LBR_TX_TY1: null, //partsOrder.job.lbr_tx_ty1, + LBR_TX_IN1: null, //partsOrder.job.lbr_tx_in1, + LBR_TX_TY2: null, //partsOrder.job.lbr_tx_ty2, + LBR_TX_IN2: null, //partsOrder.job.lbr_tx_in2, + LBR_TX_TY3: null, //partsOrder.job.lbr_tx_ty3, + LBR_TX_IN3: null, //partsOrder.job.lbr_tx_in3, + LBR_TX_TY4: null, //partsOrder.job.lbr_tx_ty4, + LBR_TX_IN4: null, //partsOrder.job.lbr_tx_in4, + LBR_TX_TY5: null, //partsOrder.job.lbr_tx_ty5, + LBR_TX_IN5: null, //partsOrder.job.lbr_tx_in5, + }, + ]; + } + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFL`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFL`), + pflFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFL file records added.`); + return true; + } catch (error) { + console.error("Error generating PFL file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePflFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pfm.ts b/src/main/ems-parts-order/ems-parts-order-generate-pfm.ts new file mode 100644 index 0000000..2a3a501 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pfm.ts @@ -0,0 +1,105 @@ +import { DBFFile } from "dbffile"; +import _ from "lodash"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedPfmLine } from "../decoder/decode-pfm.interface"; +import { pfmFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pfm-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import uppercaseObjectKeys from "../util/uppercaseObjectKeys"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGeneratePfmFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + let records; + if (partsOrder.job.materials && !_.isEmpty(partsOrder.job.materials)) { + records = Object.keys(partsOrder.job.materials).map((key) => { + const record: DecodedPfmLine = partsOrder.job.materials[key]; + return uppercaseObjectKeys(record); + }); + } else { + //Older records may not have materials, especially for ImEX. + records = [ + { + MATL_TYPE: "MAPA", + CAL_CODE: null, + CAL_DESC: null, + CAL_MAXDLR: 0, + CAL_PRIP: 0, + CAL_SECP: 0, + MAT_CALP: 0, + CAL_PRETHR: 0, + CAL_PSTTHR: 0, + CAL_THRAMT: 0, + CAL_LBRMIN: 0, + CAL_LBRMAX: 0, + CAL_LBRRTE: partsOrder.job.rate_mapa, + CAL_OPCODE: null, + TAX_IND: true, + MAT_TAXP: null, + MAT_ADJP: null, + MAT_TX_TY1: null, + MAT_TX_IN1: null, + MAT_TX_TY2: null, + MAT_TX_IN2: null, + MAT_TX_TY3: null, + MAT_TX_IN3: null, + MAT_TX_TY4: null, + MAT_TX_IN4: null, + MAT_TX_TY5: null, + MAT_TX_IN5: null, + }, + { + MATL_TYPE: "MASH", + CAL_CODE: null, + CAL_DESC: null, + CAL_MAXDLR: 0, + CAL_PRIP: 0, + CAL_SECP: 0, + MAT_CALP: 0, + CAL_PRETHR: 0, + CAL_PSTTHR: 0, + CAL_THRAMT: 0, + CAL_LBRMIN: 0, + CAL_LBRMAX: 0, + CAL_LBRRTE: partsOrder.job.rate_mash, + CAL_OPCODE: null, + TAX_IND: true, + MAT_TAXP: null, + MAT_ADJP: null, + MAT_TX_TY1: null, + MAT_TX_IN1: null, + MAT_TX_TY2: null, + MAT_TX_IN2: null, + MAT_TX_TY3: null, + MAT_TX_IN3: null, + MAT_TX_TY4: null, + MAT_TX_IN4: null, + MAT_TX_TY5: null, + MAT_TX_IN5: null, + }, + ]; + } + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFM`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFM`), + pfmFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFM file records added.`); + return true; + } catch (error) { + console.error("Error generating PFM file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePfmFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pfo.ts b/src/main/ems-parts-order/ems-parts-order-generate-pfo.ts new file mode 100644 index 0000000..2ff6d9b --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pfo.ts @@ -0,0 +1,34 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { pfoFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pfo-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGeneratePfoFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = []; //This was kept blank previously as well. + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFO`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFO`), + pfoFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFO file records added.`); + return true; + } catch (error) { + console.error("Error generating PFO file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePfoFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pfp.ts b/src/main/ems-parts-order/ems-parts-order-generate-pfp.ts new file mode 100644 index 0000000..9e8ac97 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pfp.ts @@ -0,0 +1,39 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedPfpLine } from "../decoder/decode-pfp.interface"; +import { pfpFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pfp-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import uppercaseObjectKeys from "../util/uppercaseObjectKeys"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGeneratePfpFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = Object.keys(partsOrder.job.parts_tax_rates).map((key) => { + const record: DecodedPfpLine = partsOrder.job.parts_tax_rates[key]; + return uppercaseObjectKeys(record); + }); + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFP`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFP`), + pfpFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFP file records added.`); + return true; + } catch (error) { + console.error("Error generating PFP file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePfpFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-pft.ts b/src/main/ems-parts-order/ems-parts-order-generate-pft.ts new file mode 100644 index 0000000..893ddaf --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-pft.ts @@ -0,0 +1,34 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { pftFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/pft-field-descriptor"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGeneratePftFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = []; //Left blank intentionally as per previous code. + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFT`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.PFT`), + pftFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} PFT file records added.`); + return true; + } catch (error) { + console.error("Error generating PFT file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGeneratePftFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-stl.ts b/src/main/ems-parts-order/ems-parts-order-generate-stl.ts new file mode 100644 index 0000000..485c75e --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-stl.ts @@ -0,0 +1,40 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { DecodedStlLine } from "../decoder/decode-stl.interface"; +import { stlFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/stl-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import uppercaseObjectKeys from "../util/uppercaseObjectKeys"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateStlFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + //TODO: Add CIECA STL to parts order. + const records = Object.keys(partsOrder.job.cieca_stl?.data).map((key) => { + const record: DecodedStlLine = partsOrder.job.cieca_stl.data[key]; + return uppercaseObjectKeys(record); + }); + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.STL`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.STL`), + stlFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} STL file records added.`); + return true; + } catch (error) { + console.error("Error generating STL file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateStlFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-ttl.ts b/src/main/ems-parts-order/ems-parts-order-generate-ttl.ts new file mode 100644 index 0000000..9e56333 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-ttl.ts @@ -0,0 +1,36 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { ttlFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/ttl-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import uppercaseObjectKeys from "../util/uppercaseObjectKeys"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateTtlFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + //TODO: Add CIECA STL to parts order. + const records = uppercaseObjectKeys(partsOrder.job.cieca_ttl?.data); + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.TTL`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.TTL`), + ttlFieldLineDescriptors, + ); + + await dbf.appendRecords([records]); + console.log(`${records.length} TTL file records added.`); + return true; + } catch (error) { + console.error("Error generating TTL file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateTtlFile; diff --git a/src/main/ems-parts-order/ems-parts-order-generate-veh.ts b/src/main/ems-parts-order/ems-parts-order-generate-veh.ts new file mode 100644 index 0000000..791b365 --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-generate-veh.ts @@ -0,0 +1,65 @@ +import { DBFFile } from "dbffile"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import { vehFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/veh-field-descriptors"; +import { + deleteEmsFileIfExists, + generateEmsOutFilePath, +} from "../util/ems-util"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const EmsPartsOrderGenerateVehFile = async ( + partsOrder: EmsPartsOrder, +): Promise => { + try { + const records = [ + { + IMPACT_1: partsOrder.job.area_of_damage?.impact1 || null, + IMPACT_2: partsOrder.job.area_of_damage?.impact2 || null, + DMG_MEMO: null, + DB_V_CODE: "", + PLATE_NO: partsOrder.job.plate_no || null, + PLATE_ST: partsOrder.job.plate_st || null, + V_VIN: partsOrder.job.v_vin || null, + V_COND: "", + V_PROD_DT: "", + V_MODEL_YR: partsOrder.job.v_model_yr || null, + V_MAKECODE: "", + V_MAKEDESC: partsOrder.job.v_make_desc || null, + V_MODEL: partsOrder.job.v_model_desc || null, + V_TYPE: partsOrder.job.vehicle?.v_type || null, + V_BSTYLE: partsOrder.job.vehicle?.v_bstyle || null, + V_TRIMCODE: partsOrder.job.vehicle?.v_trimcode || null, + TRIM_COLOR: partsOrder.job.vehicle?.trim_color || null, + V_MLDGCODE: partsOrder.job.vehicle?.v_mldgcode || null, + V_ENGINE: partsOrder.job.vehicle?.v_engine || null, + V_MILEAGE: partsOrder.job.vehicle?.v_mileage || null, + V_OPTIONS: null, + V_COLOR: partsOrder.job.vehicle?.v_color || null, + V_TONE: Number(partsOrder.job.vehicle?.v_tone) || null, + V_STAGE: null, + PAINT_CD1: partsOrder.job.vehicle?.v_paint_codes?.paint_cd1 || "", + PAINT_CD2: partsOrder.job.vehicle?.v_paint_codes?.paint_cd2 || "", + PAINT_CD3: partsOrder.job.vehicle?.v_paint_codes?.paint_cd3 || "", + V_MEMO: null, + }, + ]; + + await deleteEmsFileIfExists( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.VEH`), + ); + + const dbf: DBFFile = await DBFFile.create( + generateEmsOutFilePath(`${partsOrder.job.ciecaid}.VEH`), + vehFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} VEH file records added.`); + return true; + } catch (error) { + console.error("Error generating VEH file:", errorTypeCheck(error)); + return false; + } +}; + +export default EmsPartsOrderGenerateVehFile; diff --git a/src/main/ems-parts-order/ems-parts-order-handler.ts b/src/main/ems-parts-order/ems-parts-order-handler.ts new file mode 100644 index 0000000..4471f2b --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-handler.ts @@ -0,0 +1,83 @@ +import log from "electron-log/main"; +import express from "express"; +import _ from "lodash"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import store from "../store/store"; +import createdDirectoryIfNotExist from "../util/createDirectoryIfNotExist"; +import EmsPartsOrderGenerateAd1File from "./ems-parts-order-generate-ad1"; +import EmsPartsOrderGenerateAd2File from "./ems-parts-order-generate-ad2"; +import EmsPartsOrderGenerateEnvFile from "./ems-parts-order-generate-env"; +import EmsPartsOrderGenerateLinFile from "./ems-parts-order-generate-lin"; +import EmsPartsOrderGeneratePfhFile from "./ems-parts-order-generate-pfh"; +import EmsPartsOrderGeneratePflFile from "./ems-parts-order-generate-pfl"; +import EmsPartsOrderGeneratePfmFile from "./ems-parts-order-generate-pfm"; +import EmsPartsOrderGeneratePfoFile from "./ems-parts-order-generate-pfo"; +import EmsPartsOrderGeneratePfpFile from "./ems-parts-order-generate-pfp"; +import EmsPartsOrderGeneratePftFile from "./ems-parts-order-generate-pft"; +import EmsPartsOrderGenerateStlFile from "./ems-parts-order-generate-stl"; +import EmsPartsOrderGenerateTtlFile from "./ems-parts-order-generate-ttl"; +import EmsPartsOrderGenerateVehFile from "./ems-parts-order-generate-veh"; +import { EmsPartsOrder } from "./ems-parts-order-interfaces"; + +const handleEMSPartsOrder = async ( + req: express.Request, + res: express.Response, +): Promise => { + //Route handler here only. + + const partsOrderBody = req.body as EmsPartsOrder; + try { + await generateEMSPartsOrder(partsOrderBody); + res.status(200).json({ success: true }); + } catch (error) { + log.error("Error generating parts price change", errorTypeCheck(error)); + res.status(500).json({ + success: false, + error: "Error generating parts price change.", + ...errorTypeCheck(error), + }); + } + return; +}; + +const generateEMSPartsOrder = async ( + partsOrder: EmsPartsOrder, +): Promise => { + log.debug(" Generating parts price change"); + //Check to make sure that the EMS Output file path exists. If it doesn't, create it. If it's not set, abandon ship. + + const emsOutFilePath: string | null = store.get("settings.emsOutFilePath"); + if (_.isEmpty(emsOutFilePath) || emsOutFilePath === null) { + log.error("EMS Out file path is not set"); + throw new Error("EMS Out file path is not set"); + } + try { + createdDirectoryIfNotExist(emsOutFilePath); + + //Generate all required files: ad1, ad2, veh, lin, pfh, pfl, pfm,pfo, pfp, pft, stl, ttl + await EmsPartsOrderGenerateAd1File(partsOrder); + await EmsPartsOrderGenerateAd2File(partsOrder); + await EmsPartsOrderGenerateVehFile(partsOrder); + await EmsPartsOrderGenerateLinFile(partsOrder); + await EmsPartsOrderGeneratePfhFile(partsOrder); + await EmsPartsOrderGeneratePflFile(partsOrder); + await EmsPartsOrderGeneratePfmFile(partsOrder); + await EmsPartsOrderGeneratePfoFile(partsOrder); + await EmsPartsOrderGeneratePfpFile(partsOrder); + await EmsPartsOrderGeneratePftFile(partsOrder); + await EmsPartsOrderGenerateStlFile(partsOrder); + await EmsPartsOrderGenerateTtlFile(partsOrder); + + await EmsPartsOrderGenerateEnvFile(partsOrder); + + log.info( + "EMS Parts Order files generated successfully for " + + partsOrder.job.ciecaid, + ); + } catch (error) { + log.error("Error generating parts price change", errorTypeCheck(error)); + throw error; + } +}; + +export { handleEMSPartsOrder }; diff --git a/src/main/ems-parts-order/ems-parts-order-interfaces.ts b/src/main/ems-parts-order/ems-parts-order-interfaces.ts new file mode 100644 index 0000000..264032e --- /dev/null +++ b/src/main/ems-parts-order/ems-parts-order-interfaces.ts @@ -0,0 +1,322 @@ +import { CiecaPfl } from "../decoder/decode-pfl.interface"; +import { DecodedPfmLine } from "../decoder/decode-pfm.interface"; +import { DecodedPfpLine } from "../decoder/decode-pfp.interface"; +import { DecodedStlLine } from "../decoder/decode-stl.interface"; +import { DecodedTtlLine } from "../decoder/decode-ttl.interface"; + +export interface TaxRate { + prt_type: string; + prt_discp: number; + prt_mktyp: boolean; + prt_mkupp: number; + prt_tax_in: boolean; + prt_tax_rt: number; +} + +export interface BillTaxRates { + local_tax_rate: number; + state_tax_rate: number; + federal_tax_rate: number; +} + +export interface PaintCodes { + paint_cd1: string | null; + paint_cd2: string | null; + paint_cd3: string | null; +} + +export interface AreaOfDamage { + impact1: string; + impact2: string | null; +} + +// Jobline export interface +export interface Jobline { + tran_code: string; + act_price: number; + db_ref: string; + db_price: number; + db_hrs: number; + glass_flag: boolean; + id: string; + lbr_amt: number; + lbr_hrs_j: boolean; + lbr_inc: boolean; + lbr_op: string; + lbr_op_j: boolean; + lbr_tax: boolean; + lbr_typ_j: boolean; + line_desc: string; + line_ind: string; + line_no: number; + line_ref: number; + location: string | null; + misc_amt: number; + misc_sublt: boolean; + misc_tax: boolean; + mod_lb_hrs: number; + mod_lbr_ty: string; + oem_partno: string; + op_code_desc: string; + paint_stg: number; + paint_tone: number; + part_qty: number; + part_type: string; + price_inc: boolean; + price_j: boolean; + prt_dsmk_m: number; + prt_dsmk_p: number; + tax_part: boolean; + unq_seq: number; + alt_co_id: string | null; + alt_overrd: boolean; + alt_part_i: boolean; + alt_partm: string | null; + alt_partno: string | null; + bett_amt: number; + bett_pctg: number; + bett_tax: boolean; + bett_type: string | null; + cert_part: boolean; + est_seq: string | null; + part_descj: boolean; +} + +// Parts Order Line export interface +export interface PartsOrderLine { + jobline: Jobline; + act_price: number; + id: string; + db_price: number; + line_desc: string; + quantity: number; + part_type: string; + priceChange: boolean; +} + +// Vehicle export interface +export interface Vehicle { + v_bstyle: string; + v_type: string; + v_trimcode: string | null; + v_tone: string; + v_stage: string; + v_prod_dt: string | null; + v_options: string | null; + v_paint_codes: PaintCodes; + v_model_yr: string; + v_model_desc: string; + v_mldgcode: string | null; + v_makecode: string; + v_make_desc: string; + v_engine: string; + v_cond: string; + v_color: string | null; + trim_color: string | null; + shopid: string; + plate_no: string; + plate_st: string; + db_v_code: string; + v_vin: string; +} + +// Bodyshop export interface +export interface Bodyshop { + shopname: string; + bill_tax_rates: BillTaxRates; +} + +// Job export interface +export interface Job { + bodyshop: Bodyshop; + ro_number: string; + clm_no: string; + asgn_no: string; + asgn_date: string; + state_tax_rate: number | null; + area_of_damage: AreaOfDamage; + asgn_type: string | null; + ciecaid: string; + cieca_pfl: CiecaPfl; + clm_addr1: string | null; + clm_city: string | null; + clm_addr2: string | null; + clm_ct_fn: string | null; + clm_ct_ln: string | null; + clm_ct_ph: string | null; + clm_ct_phx: string | null; + clm_ctry: string | null; + clm_ea: string | null; + clm_fax: string | null; + clm_faxx: string | null; + clm_ofc_id: string | null; + clm_ofc_nm: string | null; + clm_ph1: string | null; + clm_ph1x: string | null; + clm_ph2: string | null; + clm_ph2x: string | null; + clm_st: string | null; + clm_title: string | null; + clm_total: number; + clm_zip: string | null; + ded_amt: number; + est_addr1: string | null; + est_addr2: string | null; + est_city: string | null; + est_co_nm: string | null; + est_ct_fn: string; + est_ctry: string | null; + est_ct_ln: string; + est_ea: string; + est_ph1: string | null; + est_st: string | null; + est_zip: string | null; + g_bett_amt: number; + id: string; + ins_addr1: string | null; + ins_city: string | null; + ins_addr2: string | null; + ins_co_id: string | null; + ins_co_nm: string; + ins_ct_fn: string | null; + ins_ct_ln: string | null; + ins_ct_ph: string | null; + ins_ct_phx: string | null; + ins_ctry: string | null; + ins_ea: string | null; + ins_fax: string | null; + ins_faxx: string | null; + ins_memo: string | null; + ins_ph1: string | null; + ins_ph1x: string | null; + ins_ph2: string | null; + ins_ph2x: string | null; + ins_st: string | null; + ins_title: string | null; + ins_zip: string | null; + insd_addr1: string; + insd_addr2: string | null; + insd_city: string; + insd_co_nm: string | null; + insd_ctry: string | null; + insd_ea: string | null; + insd_fax: string | null; + insd_faxx: string | null; + insd_fn: string; + insd_ln: string; + insd_ph1: string; + insd_ph1x: string | null; + insd_ph2: string; + insd_ph2x: string | null; + insd_st: string; + insd_title: string | null; + insd_zip: string; + loss_cat: string; + loss_date: string; + loss_desc: string; + loss_of_use: string | null; + loss_type: string; + ownr_addr1: string; + ownr_addr2: string | null; + ownr_city: string; + ownr_co_nm: string | null; + ownr_ctry: string | null; + ownr_ea: string | null; + ownr_fax: string | null; + ownr_faxx: string | null; + ownr_ph1: string; + ownr_fn: string; + ownr_ln: string; + ownr_ph1x: string | null; + ownr_ph2: string; + ownr_ph2x: string | null; + ownr_st: string; + ownr_title: string | null; + ownr_zip: string; + parts_tax_rates: Record; + pay_amt: number; + pay_date: string | null; + pay_type: string | null; + pay_chknm: string; + payee_nms: string | null; + plate_no: string; + plate_st: string; + po_number: string | null; + policy_no: string; + tax_lbr_rt: number; + tax_levies_rt: number; + tax_paint_mat_rt: number; + tax_predis: number; + tax_prethr: number; + tax_pstthr: number; + tax_registration_number: string | null; + tax_str_rt: number; + tax_shop_mat_rt: number; + tax_sub_rt: number; + tax_thramt: number; + tax_tow_rt: number; + theft_ind: boolean; + tlos_ind: boolean; + towin: boolean; + v_color: string | null; + v_make_desc: string; + v_model_desc: string; + v_model_yr: string; + v_vin: string; + vehicle: Vehicle; + agt_zip: string | null; + agt_st: string | null; + agt_ph2x: string | null; + agt_ph2: string | null; + agt_ph1x: string | null; + agt_ph1: string | null; + agt_lic_no: string | null; + agt_faxx: string | null; + agt_fax: string | null; + agt_ea: string | null; + agt_ctry: string | null; + agt_ct_phx: string | null; + agt_ct_ph: string | null; + agt_ct_ln: string | null; + agt_ct_fn: string | null; + agt_co_nm: string | null; + agt_co_id: string | null; + agt_city: string | null; + agt_addr1: string | null; + agt_addr2: string | null; + adj_g_disc: number; + rate_matd: number | null; + rate_mash: number; + rate_mapa: number; + rate_mahw: number; + rate_macs: number; + rate_mabl: number | null; + rate_ma3s: number; + rate_ma2t: number; + rate_ma2s: number; + rate_lau: number; + rate_las: number; + rate_lar: number; + rate_lam: number; + rate_lag: number; + rate_laf: number; + rate_lae: number | null; + rate_lad: number | null; + rate_lab: number; + rate_laa: number; + rate_la4: number; + rate_la3: number; + rate_la2: number; + rate_la1: number; + materials: Record; + cieca_stl: { + data: Array; + }; + cieca_ttl: { data: DecodedTtlLine }; +} + +// Main Parts Order export interface +export interface EmsPartsOrder { + parts_order_lines: PartsOrderLine[]; + job: Job; +} diff --git a/src/main/graphql/graphql-client.ts b/src/main/graphql/graphql-client.ts new file mode 100644 index 0000000..0dba4b5 --- /dev/null +++ b/src/main/graphql/graphql-client.ts @@ -0,0 +1,53 @@ +import { BrowserWindow, ipcMain } from "electron"; +import log from "electron-log/main"; +import { GraphQLClient, RequestMiddleware } from "graphql-request"; +import errorTypeCheck from "../../util/errorTypeCheck.js"; +import ipcTypes from "../../util/ipcTypes.json"; +import store from "../store/store.js"; +import getMainWindow from "../../util/getMainWindow.js"; + +const requestMiddleware: RequestMiddleware = async (request) => { + const token = await getTokenFromRenderer(); + log.info( + `%c[Graphql Request]%c${request.operationName}`, + "color: red", + "color: green", + request, + ); + + return { + ...request, + headers: { ...request.headers, Authorization: `Bearer ${token}` }, + }; +}; + +const client: GraphQLClient = new GraphQLClient( + store.get("app.isTest") || false + ? import.meta.env.VITE_GRAPHQL_ENDPOINT_TEST + : import.meta.env.VITE_GRAPHQL_ENDPOINT, + { + requestMiddleware, + }, +); + +export async function getTokenFromRenderer(): Promise { + return new Promise((resolve) => { + try { + const mainWindow = getMainWindow(); + //TODO: Verify that this will work if the app is minimized/closed. + mainWindow?.webContents.send(ipcTypes.toRenderer.user.getToken); + } catch (error) { + log.error( + "Unable to send request to renderer process for token", + errorTypeCheck(error), + ); + } + + // Set up one-time listener for the response + ipcMain.once(ipcTypes.toMain.user.getTokenResponse, (_, token: string) => { + resolve(token); + }); + }); +} + +export default client; diff --git a/src/main/graphql/queries.ts b/src/main/graphql/queries.ts new file mode 100644 index 0000000..e020c53 --- /dev/null +++ b/src/main/graphql/queries.ts @@ -0,0 +1,272 @@ +import { UUID } from "crypto"; +import { parse, TypedQueryDocumentNode } from "graphql"; +import { gql } from "graphql-request"; +import { AvailableJobSchema } from "../decoder/decoder"; + +// Define types for the query result and variables +export interface ActiveBodyshopQueryResult { + bodyshops: Array<{ + id: string; + shopname: string; + region_config: string; + convenient_company: string; + }>; +} + +// No variables needed for this query +export const QUERY_ACTIVE_BODYSHOP_TYPED: TypedQueryDocumentNode< + ActiveBodyshopQueryResult, + Record +> = parse(gql` + query QUERY_ACTIVE_BODYSHOP { + bodyshops(where: { associations: { active: { _eq: true } } }) { + id + shopname + region_config + convenient_company + } + } +`) as TypedQueryDocumentNode>; + +export interface MasterdataQueryResult { + masterdata: Array<{ + value: string; + key: string; + }>; +} + +interface MasterdataQueryVariables { + key: string; +} + +export const QUERY_MASTERDATA_TYPED: TypedQueryDocumentNode< + MasterdataQueryResult, + MasterdataQueryVariables +> = parse(gql` + query QUERY_MASTERDATA($key: String!) { + masterdata(where: { key: { _eq: $key } }) { + value + key + } + } +`) as TypedQueryDocumentNode; + +export interface VehicleQueryResult { + vehicles: Array<{ + id: UUID; + }>; +} + +interface VehicleQueryVariables { + vin: string; +} + +export const QUERY_VEHICLE_BY_VIN_TYPED: TypedQueryDocumentNode< + VehicleQueryResult, + VehicleQueryVariables +> = parse(gql` + query QUERY_VEHICLE_BY_VIN($vin: String!) { + vehicles(where: { v_vin: { _eq: $vin } }) { + id + } + } +`) as TypedQueryDocumentNode; + +export interface QueryJobByClmNoResult { + jobs: Array<{ + id: UUID; + }>; +} + +export interface QueryJobByClmNoVariables { + clm_no: string; +} + +export const QUERY_JOB_BY_CLM_NO_TYPED: TypedQueryDocumentNode< + QueryJobByClmNoResult, + QueryJobByClmNoVariables +> = parse(gql` + query QUERY_JOB_BY_CLM_NO($clm_no: String!) { + jobs(where: { clm_no: { _eq: $clm_no } }) { + id + } + } +`) as TypedQueryDocumentNode; + +export interface InsertAvailableJobResult { + returning: Array<{ + id: UUID; + }>; +} + +export interface InsertAvailableJobVariables { + jobInput: Array; +} + +export const INSERT_AVAILABLE_JOB_TYPED: TypedQueryDocumentNode< + InsertAvailableJobResult, + InsertAvailableJobVariables +> = parse(gql` + mutation INSERT_AVAILABLE_JOB($jobInput: [available_jobs_insert_input!]!) { + insert_available_jobs( + objects: $jobInput + on_conflict: { + constraint: available_jobs_clm_no_bodyshopid_key + update_columns: [ + clm_amt + cieca_id + est_data + issupplement + ownr_name + source_system + supplement_number + vehicle_info + ] + } + ) { + returning { + id + } + } + } +`) as TypedQueryDocumentNode< + InsertAvailableJobResult, + InsertAvailableJobVariables +>; + +// Add PpgData Query +export interface PpgDataQueryResult { + bodyshops_by_pk: { + id: string; + shopname: string; + imexshopid: string; + } | null; + jobs: Array<{ + id: string; + ro_number: string; + status: string; + ownr_fn: string; + ownr_ln: string; + ownr_co_nm: string; + v_vin: string; + v_model_yr: string; + v_make_desc: string; + v_model_desc: string; + v_color: string; + plate_no: string; + ins_co_nm: string; + est_ct_fn: string; + est_ct_ln: string; + rate_mapa: number; + rate_lab: number; + job_totals: { + rates?: { + mapa?: { + total?: { + amount?: number; + }; + }; + }; + totals?: { + subtotal?: { + amount?: number; + }; + }; + }; + vehicle: { + v_paint_codes: { + paint_cd1?: string; + }; + }; + labhrs: { + aggregate: { + sum: { + mod_lb_hrs: number; + }; + }; + }; + larhrs: { + aggregate: { + sum: { + mod_lb_hrs: number; + }; + }; + }; + }>; +} + +export interface PpgDataQueryVariables { + today: string; + todayplus5: string; + shopid: string; +} + +export const PPG_DATA_QUERY_TYPED: TypedQueryDocumentNode< + PpgDataQueryResult, + PpgDataQueryVariables +> = parse(gql` + query PpgData( + $today: timestamptz! + $todayplus5: timestamptz! + $shopid: uuid! + ) { + bodyshops_by_pk(id: $shopid) { + id + shopname + imexshopid + } + jobs( + where: { + _or: [ + { + _and: [ + { scheduled_in: { _lte: $todayplus5 } } + { scheduled_in: { _gte: $today } } + ] + } + { inproduction: { _eq: true } } + ] + } + ) { + id + ro_number + status + ownr_fn + ownr_ln + ownr_co_nm + v_vin + v_model_yr + v_make_desc + v_model_desc + v_color + plate_no + ins_co_nm + est_ct_fn + est_ct_ln + rate_mapa + rate_lab + job_totals + vehicle { + v_paint_codes + } + labhrs: joblines_aggregate( + where: { mod_lbr_ty: { _neq: "LAR" }, removed: { _eq: false } } + ) { + aggregate { + sum { + mod_lb_hrs + } + } + } + larhrs: joblines_aggregate( + where: { mod_lbr_ty: { _eq: "LAR" }, removed: { _eq: false } } + ) { + aggregate { + sum { + mod_lb_hrs + } + } + } + } + } +`) as TypedQueryDocumentNode; diff --git a/src/main/http-server/http-server.ts b/src/main/http-server/http-server.ts new file mode 100644 index 0000000..ef407ea --- /dev/null +++ b/src/main/http-server/http-server.ts @@ -0,0 +1,210 @@ +import cors from "cors"; +import { app } from "electron"; +import log from "electron-log/main"; +import express from "express"; +import http from "http"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import ImportJob from "../decoder/decoder"; +import folderScan from "../decoder/folder-scan"; +import { handleEMSPartsOrder } from "../ems-parts-order/ems-parts-order-handler"; +import { handleShopMetaDataFetch } from "../ipc/ipcMainHandler.user"; +import { handlePartsPriceChangeRequest } from "../ppc/ppc-handler"; +import { handleQuickBookRequest } from "../quickbooks-desktop/quickbooks-desktop"; + +export default class LocalServer { + private readonly app: express.Application; + private server: http.Server | null; + private PORT = 1337; + + constructor() { + this.server = null; + this.app = express(); + this.configureMiddleware(); + this.configureRoutes(); + } + + private configureMiddleware(): void { + const allowedOrigins = [ + "http://localhost", + "https://localhost", + "http://localhost:3000", + "https://localhost:3000", + "https://test.imex.online", + "https://imex.online", + "https://test.romeonline.io", + "https://romeonline.io", + "https://www.test.imex.online", + "https://www.imex.online", + "https://www.test.romeonline.io", + "https://www.romeonline.io", + ]; + + this.app.use( + cors({ + origin: (origin, callback) => { + // Allow requests with no origin (like mobile apps, curl requests) + if (!origin) return callback(null, true); + + if (allowedOrigins.indexOf(origin) !== -1) { + return callback(null, true); + } else { + return callback(null, false); + } + }, + credentials: true, + }), + ); + + // Parse JSON bodies + this.app.use(express.json()); + this.app.use(express.urlencoded()); + + //Add logger Middleware + this.app.use((req, res, next) => { + const startTime = Date.now(); + const requestId = Math.random().toString(36).substring(2, 15); + + // Log request details + log.info( + `[HTTP Server] [${requestId}] Request: ${req.method} ${req.url}`, + ); + log.info( + `[HTTP Server] [${requestId}] Headers: ${JSON.stringify(req.headers)}`, + ); + + // Log request body if it exists + if (req.body && Object.keys(req.body).length > 0) { + log.info( + `[HTTP Server] [${requestId}] Body: ${JSON.stringify(req.body)}`, + ); + } + + // Capture the original methods + const originalSend = res.send; + const originalJson = res.json; + + // Override send method to log response + res.send = function (body): express.Response { + log.info(`[HTTP Server] [${requestId}] Response body: ${body}`); + log.info( + `[HTTP Server] [${requestId}] Response time: ${Date.now() - startTime}ms`, + ); + return originalSend.call(this, body); + }; + + // Override json method to log response + res.json = function (body): express.Response { + log.info( + `[HTTP Server] [${requestId}] Response body: ${JSON.stringify(body)}`, + ); + log.info( + `[HTTP Server] [${requestId}] Response time: ${Date.now() - startTime}ms`, + ); + return originalJson.call(this, body); + }; + + next(); + }); + } + + private configureRoutes(): void { + // Basic health check endpoint + this.app.get("/health", (_req: express.Request, res: express.Response) => { + res.status(200).json({ status: "ok" }); + }); + this.app.post("/ping", (_req, res) => { + res.status(200).json({ + appVer: app.getVersion(), + qbPath: app.getPath("userData"), //TODO: Resolve to actual QB file path. + }); + }); + + this.app.post("/qb", handleQuickBookRequest); + this.app.post("/scan", async (_req, res): Promise => { + log.debug("[HTTP Server] Scan request received"); + const files = await folderScan(); + res.status(200).json(files); + return; + }); + this.app.post("/ppc", handlePartsPriceChangeRequest); + this.app.post("/oec", handleEMSPartsOrder); + this.app.post( + "/import", + async (req: express.Request, res: express.Response) => { + log.debug("[HTTP Server] Import request received"); + const { filepath } = req.body; + if (!filepath) { + res.status(400).json({ error: "filepath is required" }); + return; + } + try { + await ImportJob(filepath); + res.status(200).json({ success: true }); + } catch (error) { + log.error( + "[HTTP Server] Error importing file", + errorTypeCheck(error), + ); + res.status(500).json({ + success: false, + error: "Error importing file", + ...errorTypeCheck(error), + }); + } + }, + ); + this.app.post( + "/refresh", + async (_req: express.Request, res: express.Response) => { + log.debug("[HTTP Server] Refresh request received"); + try { + await handleShopMetaDataFetch(true); + res.status(200).json({ success: true }); + } catch (error) { + log.error( + "[HTTP Server] Error refreshing shop metadata", + errorTypeCheck(error), + ); + res.status(500).json({ + success: false, + error: "Error importing file", + ...errorTypeCheck(error), + }); + } + }, + ); + + // Add more routes as needed + } + + public start(): void { + try { + this.server = http.createServer(this.app); + + this.server.on("error", (error: NodeJS.ErrnoException) => { + if (error.code === "EADDRINUSE") { + log.error( + `[HTTP Server] Port ${this.PORT} is already in use. Please use a different port.`, + ); + } else { + log.error(`[HTTP Server] Server error: ${error.message}`); + } + }); + + this.server.listen(this.PORT, () => { + log.info( + `[HTTP Server] Local HTTP server running on port ${this.PORT}`, + ); + }); + } catch (error: unknown) { + log.error("[HTTP Server] Error starting server", errorTypeCheck(error)); + } + } + + public stop(): void { + if (this.server) { + this.server.close(); + log.info("[HTTP Server] Local HTTP server stopped"); + } + } +} diff --git a/src/main/index.test.ts b/src/main/index.test.ts new file mode 100644 index 0000000..f80e836 --- /dev/null +++ b/src/main/index.test.ts @@ -0,0 +1,19 @@ +import { _electron as electron } from "playwright"; +import { test, expect } from "@playwright/test"; + +test("Basic Electron app compilation.", async () => { + const electronApp = await electron.launch({ args: ["."] }); + const isPackaged = await electronApp.evaluate(async ({ app }) => { + // This runs in Electron's main process, parameter here is always + // the result of the require('electron') in the main app script. + return app.isPackaged; + }); + + expect(isPackaged).toBe(false); + + // Wait for the first BrowserWindow to open + // and return its Page object + const window = await electronApp.firstWindow(); + // close app + await electronApp.close(); +}); diff --git a/src/main/index.ts b/src/main/index.ts new file mode 100644 index 0000000..32be798 --- /dev/null +++ b/src/main/index.ts @@ -0,0 +1,691 @@ +import { is, optimizer, platform } from "@electron-toolkit/utils"; +import Sentry from "@sentry/electron/main"; +import { + app, + BrowserWindow, + globalShortcut, + ipcMain, + Menu, + nativeImage, + shell, + Tray, +} from "electron"; +import log from "electron-log/main"; +import { autoUpdater } from "electron-updater"; +import path, { join } from "path"; +import imexAppIcon from "../../resources/icon.png?asset"; +import romeAppIcon from "../../resources/ro-icon.png?asset"; + +import { + default as ErrorTypeCheck, + default as errorTypeCheck, +} from "../util/errorTypeCheck"; +import ipcTypes from "../util/ipcTypes.json"; +import ImportJob from "./decoder/decoder"; +import LocalServer from "./http-server/http-server"; +import store from "./store/store"; +import { checkForAppUpdates } from "./util/checkForAppUpdates"; +import { getMainWindow } from "./util/toRenderer"; +import { GetAllEnvFiles } from "./watcher/watcher"; +import { + isKeepAliveAgentInstalled, + setupKeepAliveAgent, +} from "./setup-keep-alive-agent"; +import { + isKeepAliveTaskInstalled, + setupKeepAliveTask, +} from "./setup-keep-alive-task"; +import ensureWindowOnScreen from "./util/ensureWindowOnScreen"; +import ongoingMemoryDump, { dumpMemoryStatsToFile } from "../util/memUsage"; + +const appIconToUse = + import.meta.env.VITE_COMPANY === "IMEX" ? imexAppIcon : romeAppIcon; + +Sentry.init({ + dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296", +}); + +log.initialize(); + +// Configure log format to include process ID +log.transports.file.format = + "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] [PID:{processId}] {text}"; +log.transports.console.format = + "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] [PID:{processId}] {text}"; +log.transports.file.maxSize = 50 * 1024 * 1024; // 50 MB +const isMac: boolean = process.platform === "darwin"; +const protocol: string = "imexmedia"; +let isAppQuitting = false; //Needed on Mac as an override to allow us to fully quit the app. +let isKeepAliveLaunch = false; // Track if launched via keep-alive +// Initialize the server +const localServer = new LocalServer(); +const gotTheLock = app.requestSingleInstanceLock(); + +if (!gotTheLock) { + log.warn( + "Another instance is already running and could not obtain mutex lock. Exiting this instance.", + ); + isAppQuitting = true; + app.quit(); // Quit the app if another instance is already running +} + +function createWindow(): void { + // Create the browser window. + const { width, height, x, y } = store.get("app.windowBounds") as { + width: number; + height: number; + x: number | undefined; + y: number | undefined; + }; + + // Validate window position is on screen + const { validX, validY } = ensureWindowOnScreen(x, y, width, height); + + const mainWindow = new BrowserWindow({ + width, + height, + x: validX, + y: validY, + show: false, // Start hidden, show later if not keep-alive + minWidth: 600, + minHeight: 400, + //autoHideMenuBar: true, + ...(process.platform === "linux" + ? { + icon: appIconToUse, + } + : {}), + title: "Shop Partner", + webPreferences: { + preload: join(__dirname, "../preload/index.js"), + sandbox: false, + devTools: true, + }, + }); + + const template: Electron.MenuItemConstructorOptions[] = [ + // { role: 'appMenu' } + // @ts-ignore + ...(isMac + ? [ + { + label: app.name, + submenu: [ + { role: "about" }, + { type: "separator" }, + { role: "services" }, + { type: "separator" }, + { role: "hide" }, + { role: "hideOthers" }, + { role: "unhide" }, + { type: "separator" }, + { role: "quit" }, + ], + }, + ] + : []), + // { role: 'fileMenu' } + { + label: "File", + submenu: [ + // @ts-ignore + ...(!isMac ? [{ role: "about" }] : []), + // @ts-ignore + isMac ? { role: "close" } : { role: "quit" }, + ], + }, + // { role: 'editMenu' } + { + label: "Edit", + submenu: [ + { role: "undo" }, + { role: "redo" }, + { type: "separator" }, + { role: "cut" }, + { role: "copy" }, + { role: "paste" }, + // @ts-ignore + ...(isMac + ? [ + { role: "pasteAndMatchStyle" }, + { role: "delete" }, + { role: "selectAll" }, + { type: "separator" }, + { + label: "Speech", + submenu: [{ role: "startSpeaking" }, { role: "stopSpeaking" }], + }, + ] + : [{ role: "delete" }, { type: "separator" }, { role: "selectAll" }]), + ], + }, + // { role: 'viewMenu' } + { + label: "View", + // @ts-ignore + submenu: [ + { role: "reload" }, + { role: "forceReload" }, + { role: "toggleDevTools" }, + { type: "separator" }, + { role: "resetZoom" }, + { role: "zoomIn" }, + { role: "zoomOut" }, + { type: "separator" }, + { role: "togglefullscreen" }, + ], + }, + { + label: "Application", + // @ts-ignore + submenu: [ + { + label: "Open on Startup", + checked: store.get("app.openOnStartup") as boolean, + type: "checkbox", + click: (): void => { + const currentSetting = store.get("app.openOnStartup") as boolean; + store.set("app.openOnStartup", !currentSetting); + log.info("Open on startup set to", !currentSetting); + if (!import.meta.env.DEV) { + app.setLoginItemSettings({ + enabled: true, //This is a windows only command. Updates the task manager and registry. + openAtLogin: !currentSetting, + }); + } + }, + }, + { + label: `Check for Updates (${app.getVersion()})`, + click: (): void => { + checkForAppUpdates(); + }, + }, + { + label: "Development", + id: "development", + visible: import.meta.env.DEV, + submenu: [ + { + label: "Connect to Test", + checked: store.get("app.isTest") as boolean, + type: "checkbox", + id: "toggleTest", + click: (): void => { + const currentSetting = store.get("app.isTest") as boolean; + store.set("app.isTest", !currentSetting); + log.info("Setting isTest to: ", !currentSetting); + app.relaunch(); // Relaunch the app + preQuitMethods(); //Quitting handlers aren't called. Manually execute to clean up the app. + app.exit(0); // Exit the current instance + }, + }, + { + label: "Check for updates", + click: (): void => { + checkForAppUpdates(); + }, + }, + { + label: "Open Log File", + click: (): void => { + /* action for item 1 */ + shell + .openPath(log.transports.file.getFile().path) + .catch((error) => { + log.error( + "Failed to open log file:", + errorTypeCheck(error), + ); + }); + }, + }, + { + label: "Clear Log", + click: (): void => { + log.transports.file.getFile().clear(); + }, + }, + { + label: "Open Config Folder", + click: (): void => { + shell.openPath(path.dirname(store.path)).catch((error) => { + log.error( + "Failed to open config folder:", + errorTypeCheck(error), + ); + }); + }, + }, + { + label: "Log the Store", + click: (): void => { + log.debug( + "Store Contents" + JSON.stringify(store.store, null, 4), + ); + }, + }, + { + type: "separator", + }, + { + label: "Enable Memory Logging", + checked: store.get("settings.enableMemDebug") as boolean, + type: "checkbox", + click: (): void => { + const currentSetting = store.get( + "settings.enableMemDebug", + ) as boolean; + store.set("settings.enableMemDebug", !currentSetting); + log.info("Enable Memory Logging set to", !currentSetting); + }, + }, + { + label: "Dump Memory Stats Now", + click: (): void => { + dumpMemoryStatsToFile(); + }, + }, + { + type: "separator", + }, + // { + // label: "Decode Hardcoded Estimate", + // click: (): void => { + // ImportJob(`C:\\EMS\\CCC\\9ee762f4.ENV`); + // }, + // }, + { + label: "Install Keep Alive", + enabled: true, // Default to enabled, update dynamically + click: async (): Promise => { + try { + if (platform.isWindows) { + log.debug("Creating Windows keep-alive task"); + await setupKeepAliveTask(); + log.info("Successfully installed Windows keep-alive task"); + } else if (platform.isMacOS) { + log.debug("Creating macOS keep-alive agent"); + await setupKeepAliveAgent(); + log.info("Successfully installed macOS keep-alive agent"); + } + // Wait to ensure task/agent is registered + await new Promise((resolve) => setTimeout(resolve, 1500)); + // Rebuild menu and update enabled state + await updateKeepAliveMenuItem(); + } catch (error) { + log.error( + `Failed to install keep-alive: ${error instanceof Error ? error.message : String(error)}`, + ); + // Optionally notify user (e.g., via dialog or log) + } + }, + }, + { + label: "Add All Estimates in watched directories", + click: (): void => { + GetAllEnvFiles().forEach((file) => ImportJob(file)); + }, + }, + ], + }, + ], + }, + // { role: 'windowMenu' } + { + label: "Window", + submenu: [ + { role: "minimize" }, + { role: "zoom" }, + // @ts-ignore + ...(isMac + ? [ + { type: "separator" }, + { role: "front" }, + { type: "separator" }, + { role: "window" }, + ] + : [{ role: "close" }]), + ], + }, + ]; + + // Dynamically update Install Keep Alive enabled state + const updateKeepAliveMenuItem = async (): Promise => { + try { + const isInstalled = platform.isWindows + ? await isKeepAliveTaskInstalled() + : platform.isMacOS + ? await isKeepAliveAgentInstalled() + : false; + const developmentMenu = template + .find((item) => item.label === "Application") + // @ts-ignore + ?.submenu?.find((item: { id: string }) => item.id === "development") + ?.submenu as Electron.MenuItemConstructorOptions[]; + const keepAliveItem = developmentMenu?.find( + (item) => item.label === "Install Keep Alive", + ); + if (keepAliveItem) { + keepAliveItem.enabled = !isInstalled; // Enable if not installed, disable if installed + const menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + log.debug( + `Updated Install Keep Alive menu item: enabled=${keepAliveItem.enabled}`, + ); + } + } catch (error) { + log.error( + `Error updating Keep Alive menu item: ${error instanceof Error ? error.message : String(error)}`, + ); + } + }; + + const menu: Electron.Menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + // Update menu item enabled state on app start + updateKeepAliveMenuItem().catch((error) => { + log.error( + `Error updating Keep Alive menu item: ${error instanceof Error ? error.message : String(error)}`, + ); + }); + + // Register a global shortcut to show the hidden item + globalShortcut.register("CommandOrControl+Shift+T", () => { + console.log("Shortcut pressed! Revealing hidden item."); + + // Update the menu to make the hidden item visible + // Find the menu item dynamically by its id + const fileMenu = template.find((item) => item.label === "Application"); + // @ts-ignore + const hiddenItem = fileMenu?.submenu?.find( + (item: { id: string }) => item.id === "development", + ); + //Adjust the development menu as well. + + if (hiddenItem) { + hiddenItem.visible = true; // Update the visibility dynamically + const menu: Electron.Menu = Menu.buildFromTemplate(template); + Menu.setApplicationMenu(menu); + } + }); + + // Store window properties for later + const storeWindowState = (): void => { + const [width, height] = mainWindow.getSize(); + const [x, y] = mainWindow.getPosition(); + store.set("app.windowBounds", { width, height, x, y }); + }; + mainWindow.on("resized", storeWindowState); + mainWindow.on("maximize", storeWindowState); + mainWindow.on("unmaximize", storeWindowState); + mainWindow.on("moved", storeWindowState); + + mainWindow.on("ready-to-show", () => { + if (!isKeepAliveLaunch) { + mainWindow.show(); // Show only if not a keep-alive launch + } + //Start the HTTP server. + // Start the local HTTP server + try { + localServer.start(); + } catch (error) { + log.error("Failed to start HTTP server:", errorTypeCheck(error)); + } + }); + + mainWindow.on("close", (event: Electron.Event) => { + if (!isAppQuitting) { + event.preventDefault(); // Prevent the window from closing + mainWindow.hide(); + } + }); + + mainWindow.webContents.setWindowOpenHandler((details) => { + shell.openExternal(details.url).catch((error) => { + log.error("Failed to open external URL:", errorTypeCheck(error)); + }); + return { action: "deny" }; + }); + + // HMR for renderer base on electron-vite cli. + // Load the remote URL for development or the local html file for production. + if (is.dev && process.env["ELECTRON_RENDERER_URL"]) { + mainWindow.loadURL(process.env["ELECTRON_RENDERER_URL"]).catch((error) => { + log.error("Failed to load URL:", errorTypeCheck(error)); + }); + } else { + mainWindow + .loadFile(join(__dirname, "../renderer/index.html")) + .catch((error) => { + log.error("Failed to load file:", errorTypeCheck(error)); + }); + } + if (import.meta.env.DEV) { + mainWindow.webContents.openDevTools(); + } +} + +// This method will be called when Electron has finished +// initialization and is ready to create browser windows. +// Some APIs can only be used after this event occurs. +app.whenReady().then(async () => { + // Default open or close DevTools by F12 in development + // and ignore CommandOrControl + R in production. + // see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils + log.debug("App is ready, initializing shortcuts and protocol handlers."); + + if (platform.isWindows) { + app.setAppUserModelId("Shop Partner"); + } + + app.on("browser-window-created", (_, window) => { + optimizer.watchWindowShortcuts(window); + }); + + let isDefaultProtocolClient: boolean; + + // remove so we can register each time as we run the app. + app.removeAsDefaultProtocolClient(protocol); + + // If we are running a non-packaged version of the app && on windows + if (process.env.NODE_ENV === "development" && process.platform === "win32") { + // Set the path of electron.exe and your app. + // These two additional parameters are only available on windows. + isDefaultProtocolClient = app.setAsDefaultProtocolClient( + protocol, + process.execPath, + [path.resolve(process.argv[1])], + ); + } else { + isDefaultProtocolClient = app.setAsDefaultProtocolClient(protocol); + } + if (isDefaultProtocolClient) { + log.info("Protocol handler registered successfully."); + } else { + log.warn("Failed to register protocol handler."); + } + + //Dynamically load ipcMain handlers once ready. + try { + const { initializeCronTasks } = await import("./ipc/ipcMainConfig"); + log.debug("Successfully loaded ipcMainConfig"); + + try { + await initializeCronTasks(); + log.info("Cron tasks initialized successfully"); + } catch (error) { + log.warn("Non-fatal: Failed to initialize cron tasks", { + ...ErrorTypeCheck(error), + }); + } + } catch (error) { + log.error("Fatal: Failed to load ipcMainConfig", { + ...ErrorTypeCheck(error), + }); + throw error; // Adjust based on whether the app should continue + } + + //Create Tray + const trayicon = nativeImage.createFromPath(appIconToUse); + const tray = new Tray(trayicon.resize({ width: 16 })); + const contextMenu = Menu.buildFromTemplate([ + { + label: "Show App", + click: (): void => { + openMainWindow(); + }, + }, + { + label: "Quit", + click: (): void => { + app.quit(); // actually quit the app. + }, + }, + ]); + + tray.on("double-click", () => { + openMainWindow(); + }); + + tray.setContextMenu(contextMenu); + + //Check for app updates. + autoUpdater.logger = log; + autoUpdater.allowDowngrade = true; + // if (import.meta.env.DEV) { + // // Useful for some dev/debugging tasks, but download can + // // not be validated because dev app is not signed + // autoUpdater.channel = "alpha"; + // autoUpdater.updateConfigPath = path.join( + // __dirname, + // "../../dev-app-update.yml", + // ); + // autoUpdater.forceDevUpdateConfig = true; + // //autoUpdater.autoDownload = false; + // } + + autoUpdater.on("checking-for-update", () => { + log.info("Checking for update..."); + const mainWindow = getMainWindow(); + mainWindow?.webContents.send(ipcTypes.toRenderer.updates.checking); + }); + autoUpdater.on("update-available", (info) => { + log.info("Update available.", info); + const mainWindow = getMainWindow(); + mainWindow?.webContents.send(ipcTypes.toRenderer.updates.available, info); + }); + autoUpdater.on("download-progress", (progress) => { + log.info(`Download speed: ${progress.bytesPerSecond}`); + log.info(`Downloaded ${progress.percent}%`); + log.info(`Total downloaded ${progress.transferred}/${progress.total}`); + const mainWindow = getMainWindow(); + mainWindow?.webContents.send( + ipcTypes.toRenderer.updates.downloading, + progress, + ); + }); + autoUpdater.on("update-downloaded", (info) => { + log.info("Update downloaded", info); + const mainWindow = getMainWindow(); + mainWindow?.webContents.send(ipcTypes.toRenderer.updates.downloaded, info); + }); + + // Check if launched with keep-alive protocol (Windows) + const args = process.argv.slice(1); + if (args.some((arg) => arg.startsWith(`${protocol}://keep-alive`))) { + isKeepAliveLaunch = true; + } + + //The update itself will run when the bodyshop record is queried to know what release channel to use. + openMainWindow(); + ongoingMemoryDump(); + + app.on("activate", function () { + openMainWindow(); + }); +}); + +app.on("open-url", (event: Electron.Event, url: string) => { + event.preventDefault(); + if (url.startsWith(`${protocol}://keep-alive`)) { + log.info("Keep-alive protocol received."); + // Do nothing, whether app is running or not + return; + } else { + openInExplorer(url); + } +}); + +// Add this event handler for second instance +app.on("second-instance", (_event: Electron.Event, argv: string[]) => { + const url = argv.find((arg) => arg.startsWith(`${protocol}://`)); + if (url) { + if (url.startsWith(`${protocol}://keep-alive`)) { + log.info( + "Keep-alive protocol received, app is already running. Nothing to do.", + ); + // Do nothing if already running + return; + } else { + log.info("Received Media URL: ", url); + openInExplorer(url); + } + } + // No action taken if no URL is provided +}); + +// Quit when all windows are closed, except on macOS. There, it's common +// for applications and their menu bar to stay active until the user quits +// explicitly with Cmd + Q. +app.on("window-all-closed", () => { + if (process.platform !== "darwin") { + app.quit(); //Disable the quit. + } +}); + +app.on("before-quit", () => { + preQuitMethods(); +}); + +//We need to hit the prequit methods from here as well to ensure the app quits and restarts. +ipcMain.on(ipcTypes.toMain.updates.apply, () => { + log.info("Applying update from renderer."); + preQuitMethods(); + setImmediate(() => { + app.removeAllListeners("window-all-closed"); + const mainWindow = getMainWindow(); + if (mainWindow) mainWindow.close(); + autoUpdater.quitAndInstall(false); + }); +}); + +function preQuitMethods(): void { + localServer.stop(); + const currentSetting = store.get("app.openOnStartup") as boolean; + if (!import.meta.env.DEV) { + app.setLoginItemSettings({ + enabled: true, //This is a windows only command. Updates the task manager and registry. + openAtLogin: !currentSetting, + }); + } + globalShortcut.unregisterAll(); + isAppQuitting = true; +} + +function openMainWindow(): void { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.show(); + } else { + createWindow(); + } +} + +function openInExplorer(url: string): void { + const folderPath: string = decodeURIComponent(url.split(`${protocol}://`)[1]); + log.info("Opening folder in explorer", folderPath); + shell.openPath(folderPath).catch((error) => { + log.error("Failed to open folder in explorer:", errorTypeCheck(error)); + }); +} diff --git a/src/main/ipc/ipcMainConfig.ts b/src/main/ipc/ipcMainConfig.ts new file mode 100644 index 0000000..fba4f99 --- /dev/null +++ b/src/main/ipc/ipcMainConfig.ts @@ -0,0 +1,278 @@ +import { app, ipcMain } from "electron"; +import log from "electron-log/main"; +import { autoUpdater } from "electron-updater"; +import path from "path"; +import ipcTypes from "../../util/ipcTypes.json"; +import ImportJob from "../decoder/decoder"; +import store from "../store/store"; +import { StartWatcher, StopWatcher } from "../watcher/watcher"; +import { + SettingEmsOutFilePathGet, + SettingEmsOutFilePathSet, + SettingsPaintScaleInputConfigsGet, + SettingsPaintScaleInputConfigsSet, + SettingsPaintScaleInputPathSet, + SettingsPaintScaleOutputConfigsGet, + SettingsPaintScaleOutputConfigsSet, + SettingsPaintScaleOutputPathSet, + SettingsPpcFilePathGet, + SettingsPpcFilePathSet, + SettingsWatchedFilePathsAdd, + SettingsWatchedFilePathsGet, + SettingsWatchedFilePathsRemove, + SettingsWatcherPollingGet, + SettingsWatcherPollingSet, +} from "./ipcMainHandler.settings"; +import { + ipcMainHandleAuthStateChanged, + ipMainHandleResetPassword, +} from "./ipcMainHandler.user"; +import cron from "node-cron"; +import { PaintScaleConfig, PaintScaleType } from "../../util/types/paintScale"; +import { ppgInputHandler, ppgOutputHandler } from "./paintScaleHandlers/PPG"; + +const initializeCronTasks = async () => { + try { + // Fetch input and output configurations + const inputConfigs = await SettingsPaintScaleInputConfigsGet(); + const outputConfigs = await SettingsPaintScaleOutputConfigsGet(); + + // Start input cron tasks + await handlePaintScaleInputCron(inputConfigs); + log.info("Initialized input cron tasks on app startup"); + + // Start output cron tasks + await handlePaintScaleOutputCron(outputConfigs); + log.info("Initialized output cron tasks on app startup"); + } catch (error) { + log.error("Error initializing cron tasks on app startup:", error); + } +}; + +// Log all IPC messages and their payloads +const logIpcMessages = (): void => { + Object.keys(ipcTypes.toMain).forEach((key) => { + const messageType = ipcTypes.toMain[key]; + const originalHandler = ipcMain.listeners(messageType)?.[0]; + if (originalHandler) { + ipcMain.removeAllListeners(messageType); + } + ipcMain.on(messageType, (event, payload) => { + log.info( + `%c[IPC Main]%c${messageType}`, + "color: red", + "color: green", + payload, + ); + if (originalHandler) { + originalHandler(event, payload); + } + }); + }); +}; + +// Input handler map +const inputTypeHandlers: Partial< + Record Promise> +> = { + [PaintScaleType.PPG]: ppgInputHandler, + // Add other input type handlers as needed +}; + +// Output handler map +const outputTypeHandlers: Partial< + Record Promise> +> = { + [PaintScaleType.PPG]: ppgOutputHandler, + // Add other output type handlers as needed +}; + +// Default handler for unsupported types +const defaultHandler = async (config: PaintScaleConfig) => { + log.debug( + `No handler defined for type ${config.type} in config ${config.id}`, + ); +}; + +// Input cron job management +let inputCronTasks: { [id: string]: cron.ScheduledTask } = {}; + +const handlePaintScaleInputCron = async (configs: PaintScaleConfig[]) => { + Object.values(inputCronTasks).forEach((task) => task.stop()); + inputCronTasks = {}; + + const validConfigs = configs.filter( + (config) => config.path && config.path.trim() !== "", + ); + + validConfigs.forEach((config) => { + const cronExpression = `*/${config.pollingInterval} * * * *`; + inputCronTasks[config.id] = cron.schedule(cronExpression, async () => { + const handler = inputTypeHandlers[config.type] || defaultHandler; + await handler(config); + }); + log.info( + `Started input cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}m`, + ); + }); +}; + +// Output cron job management +let outputCronTasks: { [id: string]: cron.ScheduledTask } = {}; + +const handlePaintScaleOutputCron = async (configs: PaintScaleConfig[]) => { + Object.values(outputCronTasks).forEach((task) => task.stop()); + outputCronTasks = {}; + + const validConfigs = configs.filter( + (config) => config.path && config.path.trim() !== "", + ); + + validConfigs.forEach((config) => { + const cronExpression = `*/${config.pollingInterval} * * * *`; + outputCronTasks[config.id] = cron.schedule(cronExpression, async () => { + const handler = outputTypeHandlers[config.type] || defaultHandler; + await handler(config); + }); + log.info( + `Started output cron task for config ${config.id} (type: ${config.type}) with interval ${config.pollingInterval}m`, + ); + }); +}; + +// Existing IPC handlers... + +ipcMain.on(ipcTypes.toMain.test, () => + console.log("** Verify that ipcMain is loaded and working."), +); + +// Auth handler +ipcMain.on(ipcTypes.toMain.authStateChanged, ipcMainHandleAuthStateChanged); +ipcMain.on(ipcTypes.toMain.user.resetPassword, ipMainHandleResetPassword); + +// Add debug handlers if in development +if (import.meta.env.DEV) { + log.debug("[IPC Debug Functions] Adding Debug Handlers"); + + ipcMain.on(ipcTypes.toMain.debug.decodeEstimate, async (): Promise => { + const relativeEmsFilepath = `_reference/ems/MPI_1/3698420.ENV`; + const rootDir = app.getAppPath(); + const absoluteFilepath = path.join(rootDir, relativeEmsFilepath); + + log.debug("[IPC Debug Function] Decode test Estimate", absoluteFilepath); + await ImportJob(absoluteFilepath); + + const job2 = `/Users/pfic/Downloads/12285264/2285264.ENV`; + const job3 = `/Users/pfic/Downloads/14033376/4033376.ENV`; + await ImportJob(job2); + await ImportJob(job3); + }); +} + +// Settings Handlers +ipcMain.handle( + ipcTypes.toMain.settings.filepaths.get, + SettingsWatchedFilePathsGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.filepaths.add, + SettingsWatchedFilePathsAdd, +); +ipcMain.handle( + ipcTypes.toMain.settings.filepaths.remove, + SettingsWatchedFilePathsRemove, +); +ipcMain.handle( + ipcTypes.toMain.settings.watcher.getpolling, + SettingsWatcherPollingGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.watcher.setpolling, + SettingsWatcherPollingSet, +); + +ipcMain.handle(ipcTypes.toMain.settings.getPpcFilePath, SettingsPpcFilePathGet); +ipcMain.handle(ipcTypes.toMain.settings.setPpcFilePath, SettingsPpcFilePathSet); +ipcMain.handle( + ipcTypes.toMain.settings.getEmsOutFilePath, + SettingEmsOutFilePathGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.setEmsOutFilePath, + SettingEmsOutFilePathSet, +); + +// Paint Scale Input Settings Handlers +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.getInputConfigs, + SettingsPaintScaleInputConfigsGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setInputConfigs, + SettingsPaintScaleInputConfigsSet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setInputPath, + SettingsPaintScaleInputPathSet, +); + +// Paint Scale Output Settings Handlers +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.getOutputConfigs, + SettingsPaintScaleOutputConfigsGet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setOutputConfigs, + SettingsPaintScaleOutputConfigsSet, +); +ipcMain.handle( + ipcTypes.toMain.settings.paintScale.setOutputPath, + SettingsPaintScaleOutputPathSet, +); + +// IPC handlers for updating paint scale cron +ipcMain.on( + ipcTypes.toMain.settings.paintScale.updateInputCron, + (_event, configs: PaintScaleConfig[]) => { + handlePaintScaleInputCron(configs).catch((error) => { + log.error(`Error handling paint scale input cron for configs: ${error}`); + }); + }, +); + +ipcMain.on( + ipcTypes.toMain.settings.paintScale.updateOutputCron, + (_event, configs: PaintScaleConfig[]) => { + handlePaintScaleOutputCron(configs).catch((error) => { + log.error(`Error handling paint scale output cron for configs: ${error}`); + }); + }, +); + +ipcMain.handle(ipcTypes.toMain.user.getActiveShop, () => { + return store.get("app.bodyshop.shopname"); +}); + +// Watcher Handlers +ipcMain.on(ipcTypes.toMain.watcher.start, () => { + StartWatcher().catch((error) => { + log.error("Error starting watcher:", error); + }); +}); + +ipcMain.on(ipcTypes.toMain.watcher.stop, () => { + StopWatcher().catch((error) => { + log.error("Error stopping watcher:", error); + }); +}); + +ipcMain.on(ipcTypes.toMain.updates.download, () => { + log.info("Download update requested from renderer."); + autoUpdater.downloadUpdate().catch((error) => { + log.error("Error downloading update:", error); + }); +}); + +export { initializeCronTasks }; + +logIpcMessages(); diff --git a/src/main/ipc/ipcMainConfig.types.ts b/src/main/ipc/ipcMainConfig.types.ts new file mode 100644 index 0000000..c90c9b4 --- /dev/null +++ b/src/main/ipc/ipcMainConfig.types.ts @@ -0,0 +1,67 @@ +export interface User { + stsTokenManager?: { + accessToken: string; + }; +} + +export interface BodyShop { + shopname: string; + id: string; +} + +export interface GraphQLResponse { + bodyshops_by_pk?: { + imexshopid: string; + shopname: string; + }; + jobs?: Array<{ + labhrs: any; + larhrs: any; + ro_number: string; + ownr_ln: string; + ownr_fn: string; + plate_no: string; + v_vin: string; + v_model_yr: string; + v_make_desc: string; + v_model_desc: string; + vehicle?: { + v_paint_codes?: { + paint_cd1: string; + }; + }; + larhrs_aggregate?: { + aggregate?: { + sum?: { + mod_lb_hrs: number; + }; + }; + }; + ins_co_nm: string; + est_ct_ln: string; + est_ct_fn: string; + job_totals?: { + rates?: { + mapa?: { + total?: { + amount: number; + }; + }; + }; + totals?: { + subtotal?: { + amount: number; + }; + }; + }; + rate_mapa: number; + labhrs_aggregate?: { + aggregate?: { + sum?: { + mod_lb_hrs: number; + }; + }; + }; + rate_lab: number; + }>; +} \ No newline at end of file diff --git a/src/main/ipc/ipcMainHandler.settings.ts b/src/main/ipc/ipcMainHandler.settings.ts new file mode 100644 index 0000000..4936b91 --- /dev/null +++ b/src/main/ipc/ipcMainHandler.settings.ts @@ -0,0 +1,257 @@ +// main/ipcMainHandler.settings.ts +import { dialog, IpcMainInvokeEvent } from "electron"; +import log from "electron-log/main"; +import _ from "lodash"; +import Store from "../store/store"; +import { getMainWindow } from "../util/toRenderer"; +import { + addWatcherPath, + removeWatcherPath, + StartWatcher, + StopWatcher, +} from "../watcher/watcher"; +import { PaintScaleConfig } from "../../util/types/paintScale"; + +// Initialize paint scale input configs in store if not set +if (!Store.get("settings.paintScaleInputConfigs")) { + Store.set("settings.paintScaleInputConfigs", []); +} + +// Initialize paint scale output configs in store if not set +if (!Store.get("settings.paintScaleOutputConfigs")) { + Store.set("settings.paintScaleOutputConfigs", []); +} + +const SettingsWatchedFilePathsAdd = async (): Promise => { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return []; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + + if (!result.canceled) { + Store.set( + "settings.filepaths", + _.union(result.filePaths, Store.get("settings.filepaths")), + ); + addWatcherPath(result.filePaths); + } + + return Store.get("settings.filepaths"); +}; + +const SettingsWatchedFilePathsRemove = async ( + _event: IpcMainInvokeEvent, + path: string, +): Promise => { + Store.set( + "settings.filepaths", + _.without(Store.get("settings.filepaths"), path), + ); + removeWatcherPath(path); + return Store.get("settings.filepaths"); +}; + +const SettingsWatchedFilePathsGet = async (): Promise => { + return Store.get("settings.filepaths") || []; +}; + +const SettingsWatcherPollingGet = async (): Promise<{ + enabled: boolean; + interval: number; +}> => { + const pollingEnabled: { enabled: boolean; interval: number } = + Store.get("settings.polling"); + return { enabled: pollingEnabled.enabled, interval: pollingEnabled.interval }; +}; + +const SettingsWatcherPollingSet = async ( + _event: IpcMainInvokeEvent, + pollingSettings: { + enabled: boolean; + interval: number; + }, +): Promise<{ + enabled: boolean; + interval: number; +}> => { + log.info("Polling set", pollingSettings); + const { enabled, interval } = pollingSettings; + Store.set("settings.polling", { enabled, interval }); + + await StopWatcher(); + await StartWatcher(); + + return { enabled, interval }; +}; + +const SettingsPpcFilePathGet = async (): Promise => { + return Store.get("settings.ppcFilePath"); +}; + +const SettingsPpcFilePathSet = async (): Promise => { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return ""; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + + if (!result.canceled) { + Store.set("settings.ppcFilePath", result.filePaths[0]); + } + + return (Store.get("settings.ppcFilePath") as string) || ""; +}; + +const SettingEmsOutFilePathGet = async (): Promise => { + return Store.get("settings.emsOutFilePath"); +}; + +const SettingEmsOutFilePathSet = async (): Promise => { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return ""; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + + if (!result.canceled) { + Store.set("settings.emsOutFilePath", result.filePaths[0]); + } + + return (Store.get("settings.emsOutFilePath") as string) || ""; +}; + +const SettingsPaintScaleInputConfigsGet = ( + _event?: IpcMainInvokeEvent, +): PaintScaleConfig[] => { + try { + const configs = Store.get( + "settings.paintScaleInputConfigs", + ) as PaintScaleConfig[]; + log.debug("Retrieved paint scale input configs:", configs); + return configs || []; + } catch (error) { + log.error("Error getting paint scale input configs:", error); + throw error; + } +}; + +const SettingsPaintScaleInputConfigsSet = async ( + _event: IpcMainInvokeEvent, + configs: PaintScaleConfig[], +): Promise => { + try { + Store.set("settings.paintScaleInputConfigs", configs); + log.debug("Saved paint scale input configs:", configs); + return true; + } catch (error) { + log.error("Error setting paint scale input configs:", error); + throw error; + } +}; + +const SettingsPaintScaleInputPathSet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return null; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + if (result.canceled) { + log.debug("Paint scale input path selection canceled"); + return null; + } + const path = result.filePaths[0]; + log.debug("Selected paint scale input path:", path); + return path; + } catch (error) { + log.error("Error setting paint scale input path:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputConfigsGet = ( + _event?: IpcMainInvokeEvent, +): PaintScaleConfig[] => { + try { + const configs = Store.get( + "settings.paintScaleOutputConfigs", + ) as PaintScaleConfig[]; + log.debug("Retrieved paint scale output configs:", configs); + return configs || []; + } catch (error) { + log.error("Error getting paint scale output configs:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputConfigsSet = async ( + _event: IpcMainInvokeEvent, + configs: PaintScaleConfig[], +): Promise => { + try { + Store.set("settings.paintScaleOutputConfigs", configs); + log.debug("Saved paint scale output configs:", configs); + return true; + } catch (error) { + log.error("Error setting paint scale output configs:", error); + throw error; + } +}; + +const SettingsPaintScaleOutputPathSet = async ( + _event: IpcMainInvokeEvent, +): Promise => { + try { + const mainWindow = getMainWindow(); + if (!mainWindow) { + log.error("No main window found when trying to open dialog"); + return null; + } + const result = await dialog.showOpenDialog(mainWindow, { + properties: ["openDirectory"], + }); + if (result.canceled) { + log.debug("Paint scale output path selection canceled"); + return null; + } + const path = result.filePaths[0]; + log.debug("Selected paint scale output path:", path); + return path; + } catch (error) { + log.error("Error setting paint scale output path:", error); + throw error; + } +}; + +export { + SettingsPpcFilePathGet, + SettingsPpcFilePathSet, + SettingsWatchedFilePathsAdd, + SettingsWatchedFilePathsGet, + SettingsWatchedFilePathsRemove, + SettingsWatcherPollingGet, + SettingsWatcherPollingSet, + SettingEmsOutFilePathGet, + SettingEmsOutFilePathSet, + SettingsPaintScaleInputConfigsGet, + SettingsPaintScaleInputConfigsSet, + SettingsPaintScaleInputPathSet, + SettingsPaintScaleOutputConfigsGet, + SettingsPaintScaleOutputConfigsSet, + SettingsPaintScaleOutputPathSet, +}; diff --git a/src/main/ipc/ipcMainHandler.user.ts b/src/main/ipc/ipcMainHandler.user.ts new file mode 100644 index 0000000..eb367d8 --- /dev/null +++ b/src/main/ipc/ipcMainHandler.user.ts @@ -0,0 +1,102 @@ +import { IpcMainEvent, shell } from "electron"; +import log from "electron-log/main"; +import { autoUpdater } from "electron-updater"; +import { User } from "firebase/auth"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import ipcTypes from "../../util/ipcTypes.json"; +import client from "../graphql/graphql-client"; +import { + ActiveBodyshopQueryResult, + MasterdataQueryResult, + QUERY_ACTIVE_BODYSHOP_TYPED, + QUERY_MASTERDATA_TYPED, +} from "../graphql/queries"; +import { default as Store, default as store } from "../store/store"; +import { checkForAppUpdatesContinuously } from "../util/checkForAppUpdates"; +import { getMainWindow, sendIpcToRenderer } from "../util/toRenderer"; + +const ipcMainHandleAuthStateChanged = async ( + _event: IpcMainEvent, + user: User | null, +): Promise => { + Store.set("user", user); + log.debug("Received authentication state change from Renderer.", user); + await setReleaseChannel(); + checkForAppUpdatesContinuously(); +}; + +async function setReleaseChannel() { + try { + //Need to query the currently active shop, and store the metadata as well. + //Also need to query the OP Codes for decoding reference. + await handleShopMetaDataFetch(); + //Check for updates + const bodyshop = Store.get("app.bodyshop"); + if (bodyshop?.convenient_company?.toLowerCase() === "alpha") { + autoUpdater.channel = "alpha"; + log.debug("Setting update channel to ALPHA channel."); + } else if (bodyshop?.convenient_company?.toLowerCase() === "beta") { + autoUpdater.channel = "beta"; + log.debug("Setting update channel to BETA channel."); + } else { + log.debug("Setting update channel to LATEST channel."); + } + } catch (error) { + log.error( + "Error while querying active bodyshop or master data", + errorTypeCheck(error), + ); + sendIpcToRenderer( + ipcTypes.toRenderer.general.showErrorMessage, + "Error connecting to ImEX Online servers to get shop data. Please try again.", + ); + } +} + +const handleShopMetaDataFetch = async ( + reloadWindow?: boolean, +): Promise => { + try { + log.debug("Requery shop information & master data."); + const activeBodyshop: ActiveBodyshopQueryResult = await client.request( + QUERY_ACTIVE_BODYSHOP_TYPED, + ); + + Store.set("app.bodyshop", activeBodyshop.bodyshops[0]); + + const OpCodes: MasterdataQueryResult = await client.request( + QUERY_MASTERDATA_TYPED, + { + key: `${activeBodyshop.bodyshops[0].region_config}_ciecaopcodes`, + }, + ); + Store.set( + "app.masterdata.opcodes", + JSON.parse(OpCodes.masterdata[0]?.value), + ); + if (reloadWindow) { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.reload(); + } + } + } catch (error) { + log.error("Error while fetching shop metadata", errorTypeCheck(error)); + throw error; + } +}; + +const ipMainHandleResetPassword = async (): Promise => { + shell.openExternal( + store.get("app.isTest") + ? `${import.meta.env.VITE_FE_URL_TEST}/resetpassword` + : `${import.meta.env.VITE_FE_URL}/resetpassword`, + ); +}; + +export { + handleShopMetaDataFetch, + ipcMainHandleAuthStateChanged, + ipMainHandleResetPassword, + setReleaseChannel, +}; diff --git a/src/main/ipc/paintScaleHandlers/PPG.ts b/src/main/ipc/paintScaleHandlers/PPG.ts new file mode 100644 index 0000000..50cad7f --- /dev/null +++ b/src/main/ipc/paintScaleHandlers/PPG.ts @@ -0,0 +1,272 @@ +import log from "electron-log/main"; +import path from "path"; +import fs from "fs/promises"; +import axios from "axios"; +import { create } from "xmlbuilder2"; +import { parseStringPromise } from "xml2js"; +import store from "../../store/store"; +import client, { getTokenFromRenderer } from "../../graphql/graphql-client"; +import { PaintScaleConfig } from "../../../util/types/paintScale"; +import dayjs from "dayjs"; +import { + PPG_DATA_QUERY_TYPED, + PpgDataQueryResult, + PpgDataQueryVariables, +} from "../../graphql/queries"; + +export async function ppgInputHandler(config: PaintScaleConfig): Promise { + try { + log.info( + `Polling input directory for PPG config ${config.id}: ${config.path}`, + ); + + log.debug( + `Archive dir: ${path.join(config.path!, "archive")}, Error dir: ${path.join(config.path!, "error")}`, + ); + + // Ensure archive and error directories exist + const archiveDir = path.join(config.path!, "archive"); + const errorDir = path.join(config.path!, "error"); + try { + await fs.mkdir(archiveDir, { recursive: true }); + await fs.mkdir(errorDir, { recursive: true }); + log.debug( + `Archive and error directories ensured: ${archiveDir}, ${errorDir}`, + ); + } catch (dirError) { + log.error(`Failed to create directories for ${config.path}:`, dirError); + throw dirError; + } + + // Check for files + const files = await fs.readdir(config.path!); + log.debug(`Found ${files.length} files in ${config.path}:`, files); + + for (const file of files) { + // Only process XML files + if (!file.toLowerCase().endsWith(".xml")) { + continue; + } + + const filePath = path.join(config.path!, file); + try { + const stats = await fs.stat(filePath); + if (!stats.isFile()) { + continue; + } + } catch (statError) { + log.warn(`Failed to stat file ${filePath}:`, statError); + continue; + } + + log.debug(`Processing input file: ${filePath}`); + + // Check file accessibility (e.g., not locked) + try { + await fs.access(filePath, fs.constants.R_OK); + } catch (error) { + log.warn(`File ${filePath} is inaccessible, skipping:`, error); + continue; + } + + // Validate XML structure + let xmlContent: BlobPart; + try { + xmlContent = await fs.readFile(filePath, "utf8"); + await parseStringPromise(xmlContent); + log.debug(`Successfully validated XML for ${filePath}`); + } catch (error) { + log.error(`Invalid XML in ${filePath}:`, error); + const timestamp = dayjs().format("YYYYMMDD_HHmmss"); + const originalFilename = path.basename(file, path.extname(file)); + const errorPath = path.join( + errorDir, + `${originalFilename}-${timestamp}.xml`, + ); + try { + await fs.rename(filePath, errorPath); + log.debug(`Moved invalid file to error: ${errorPath}`); + } catch (moveError) { + log.error( + `Failed to move invalid file to error directory ${errorPath}:`, + moveError, + ); + } + continue; + } + + // Get authentication token + let token: string | null; + try { + token = await getTokenFromRenderer(); + if (!token) { + log.error(`No authentication token for file: ${filePath}`); + continue; + } + log.debug( + `Obtained authentication token for ${filePath}: ${token.slice(0, 10)}...`, + ); + } catch (tokenError) { + log.error( + `Failed to obtain authentication token for ${filePath}:`, + tokenError, + ); + continue; + } + + // Upload file to API + const formData = new FormData(); + formData.append("file", new Blob([xmlContent]), path.basename(filePath)); + const shopId = (store.get("app.bodyshop") as any)?.shopname || ""; + formData.append("shopId", shopId); + log.debug(`Shop ID: ${shopId}`); + + const baseURL = store.get("app.isTest") + ? import.meta.env.VITE_API_TEST_URL + : import.meta.env.VITE_API_URL; + const finalUrl = `${baseURL}/mixdata/upload`; + log.debug(`Uploading file to ${finalUrl}`); + + try { + const response = await axios.post(finalUrl, formData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "multipart/form-data", + }, + timeout: 10000, // 10-second timeout + }); + + log.info(`Upload response for ${filePath}:`, { + status: response.status, + statusText: response.statusText, + data: response.data, + }); + + if (response.status === 200) { + log.info(`Successful upload of ${filePath}`); + // Move file to archive + const timestamp = dayjs().format("YYYYMMDD_HHmmss"); + const originalFilename = path.basename(file, path.extname(file)); + const archivePath = path.join( + archiveDir, + `${originalFilename}-${timestamp}.xml`, + ); + try { + await fs.access(archiveDir, fs.constants.W_OK); // Verify archiveDir is writable + await fs.rename(filePath, archivePath); + log.info(`Moved file to archive: ${archivePath}`); + } catch (moveError) { + log.error( + `Failed to move file to archive directory ${archivePath}:`, + moveError, + ); + } + } else { + log.error( + `Failed to upload ${filePath}: ${response.status} ${response.statusText}`, + { responseData: response.data }, + ); + } + } catch (error: any) { + log.error(`Error uploading ${filePath}:`, { + message: error.message, + code: error.code, + response: error.response + ? { + status: error.response.status, + statusText: error.response.statusText, + data: error.response.data, + } + : null, + }); + } + } + } catch (error) { + log.error(`Error polling input directory ${config.path}:`, error); + } +} + +// PPG Output Handler +export async function ppgOutputHandler( + config: PaintScaleConfig, +): Promise { + try { + log.info(`Generating PPG output for config ${config.id}: ${config.path}`); + + await fs.mkdir(config.path!, { recursive: true }); + + const variables: PpgDataQueryVariables = { + today: dayjs().toISOString(), + todayplus5: dayjs().add(5, "day").toISOString(), + shopid: (store.get("app.bodyshop") as any)?.id, + }; + + const response = await client.request< + PpgDataQueryResult, + PpgDataQueryVariables + >(PPG_DATA_QUERY_TYPED, variables); + const jobs = response.jobs ?? []; + + const header = { + PPG: { + Header: { + Protocol: { + Message: "PaintShopInterface", + Name: "PPG", + Version: "1.5.0", + }, + Transaction: { + TransactionID: "", + TransactionDate: dayjs().format("YYYY-MM-DD:HH:mm"), + }, + Product: { + Name: import.meta.env.VITE_COMPANY === "IMEX", + Version: "", + }, + }, + DataInterface: { + ROData: { + ShopInfo: { + ShopID: response.bodyshops_by_pk?.imexshopid || "", + ShopName: response.bodyshops_by_pk?.shopname || "", + }, + RepairOrders: { + ROCount: jobs.length.toString(), + RO: jobs.map((job) => ({ + RONumber: job.ro_number || "", + ROStatus: "Open", + Customer: `${job.ownr_ln || ""}, ${job.ownr_fn || ""}`, + ROPainterNotes: "", + LicensePlateNum: job.plate_no || "", + VIN: job.v_vin || "", + ModelYear: job.v_model_yr || "", + MakeDesc: job.v_make_desc || "", + ModelName: job.v_model_desc || "", + OEMColorCode: job.vehicle?.v_paint_codes?.paint_cd1 || "", + RefinishLaborHours: job.larhrs?.aggregate?.sum?.mod_lb_hrs || 0, + InsuranceCompanyName: job.ins_co_nm || "", + EstimatorName: `${job.est_ct_ln || ""}, ${job.est_ct_fn || ""}`, + PaintMaterialsRevenue: ( + (job.job_totals?.rates?.mapa?.total?.amount || 0) / 100 + ).toFixed(2), + PaintMaterialsRate: job.rate_mapa || 0, + BodyHours: job.labhrs?.aggregate?.sum?.mod_lb_hrs || 0, + BodyLaborRate: job.rate_lab || 0, + TotalCostOfRepairs: ( + (job.job_totals?.totals?.subtotal?.amount || 0) / 100 + ).toFixed(2), + })), + }, + }, + }, + }, + }; + + const xml = create({ version: "1.0" }, header).end({ prettyPrint: true }); + const outputPath = path.join(config.path!, `PPGPaint.xml`); + await fs.writeFile(outputPath, xml); + log.info(`Saved PPG output XML to ${outputPath}`); + } catch (error) { + log.error(`Error generating PPG output for config ${config.id}:`, error); + } +} diff --git a/src/main/ppc/ppc-generate-env.ts b/src/main/ppc/ppc-generate-env.ts new file mode 100644 index 0000000..94f8c7a --- /dev/null +++ b/src/main/ppc/ppc-generate-env.ts @@ -0,0 +1,34 @@ +import { DBFFile } from "dbffile"; +import { envFieldLineDescriptors } from "../util/ems-interface/fielddescriptors/env-field-descriptor"; +import { deleteEmsFileIfExists, generatePpcFilePath } from "../util/ems-util"; +import { PpcJob } from "./ppc-handler"; + +const GenerateEnvFile = async (job: PpcJob): Promise => { + const records = [ + { + EST_SYSTEM: "C", + RO_ID: job.ro_number, + ESTFILE_ID: job.ciecaid, + STATUS: false, + INCL_ADMIN: true, + INCL_VEH: true, + INCL_EST: true, + INCL_PROFL: true, + INCL_TOTAL: true, + INCL_VENDR: false, + }, + ]; + + await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.ENV`)); + + const dbf = await DBFFile.create( + generatePpcFilePath(`${job.ciecaid}.ENV`), + envFieldLineDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} LIN file records added.`); + return true; +}; + +export default GenerateEnvFile; diff --git a/src/main/ppc/ppc-generate-lin.ts b/src/main/ppc/ppc-generate-lin.ts new file mode 100644 index 0000000..98c10f1 --- /dev/null +++ b/src/main/ppc/ppc-generate-lin.ts @@ -0,0 +1,34 @@ +import { DBFFile } from "dbffile"; +import { linFieldDescriptors } from "../util/ems-interface/fielddescriptors/lin-field-descriptor"; +import { deleteEmsFileIfExists, generatePpcFilePath } from "../util/ems-util"; +import { PpcJob } from "./ppc-handler"; +import errorTypeCheck from "../../util/errorTypeCheck"; + +const GenerateLinFile = async (job: PpcJob): Promise => { + try { + const records = job.joblines.map((line) => { + return { + //TODO: There are missing types here. May require server side updates, but we are missing things like LINE_NO, LINE_IND, etc. + TRAN_CODE: "2", + UNQ_SEQ: line.unq_seq, + ACT_PRICE: line.act_price, + }; + }); + + await deleteEmsFileIfExists(generatePpcFilePath(`${job.ciecaid}.LIN`)); + + const dbf = await DBFFile.create( + generatePpcFilePath(`${job.ciecaid}.LIN`), + linFieldDescriptors, + ); + + await dbf.appendRecords(records); + console.log(`${records.length} LIN file records added.`); + return true; + } catch (error) { + console.error("Error generating PPC LIN file", errorTypeCheck(error)); + throw error; + } +}; + +export default GenerateLinFile; diff --git a/src/main/ppc/ppc-handler.ts b/src/main/ppc/ppc-handler.ts new file mode 100644 index 0000000..78d8f9d --- /dev/null +++ b/src/main/ppc/ppc-handler.ts @@ -0,0 +1,67 @@ +import { UUID } from "crypto"; +import log from "electron-log/main"; +import express from "express"; +import _ from "lodash"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import store from "../store/store"; +import createdDirectoryIfNotExist from "../util/createDirectoryIfNotExist"; +import GenerateEnvFile from "./ppc-generate-env"; +import GenerateLinFile from "./ppc-generate-lin"; + +const handlePartsPriceChangeRequest = async ( + req: express.Request, + res: express.Response, +): Promise => { + //Route handler here only. + + const job = req.body as PpcJob; + try { + await generatePartsPriceChange(job); + res.status(200).json({ success: true }); + } catch (error) { + log.error("Error generating parts price change", errorTypeCheck(error)); + res.status(500).json({ + success: false, + error: "Error generating parts price change.", + ...errorTypeCheck(error), + }); + } + return; +}; + +const generatePartsPriceChange = async (job: PpcJob): Promise => { + log.debug(" Generating parts price change"); + //Check to make sure that the PPC Output file path exists. If it doesn't, create it. If it's not set, abandon ship. + + const ppcOutFilePath: string | null = store.get("settings.ppcFilePath"); + if (_.isEmpty(ppcOutFilePath) || ppcOutFilePath === null) { + log.error("PPC file path is not set"); + throw new Error("PPC file path is not set"); + } + try { + createdDirectoryIfNotExist(ppcOutFilePath); + + await GenerateLinFile(job); + await GenerateEnvFile(job); + } catch (error) { + log.error("Error generating parts price change", errorTypeCheck(error)); + throw error; + } +}; +export interface PpcJob { + id: UUID; + ciecaid: string; + ro_number: string; + joblines: { + removed: boolean; + act_price_before_ppc: number | null; + id: string; + act_price: number; + unq_seq: string; //TODO: Might be a number. + }[]; + bodyshop: { + timezone: string; + }; +} + +export { handlePartsPriceChangeRequest }; diff --git a/src/main/quickbooks-desktop/QuickbooksConnector.cs b/src/main/quickbooks-desktop/QuickbooksConnector.cs new file mode 100644 index 0000000..7d102bf --- /dev/null +++ b/src/main/quickbooks-desktop/QuickbooksConnector.cs @@ -0,0 +1,30 @@ +using System; +using Interop.QBFC16; // Ensure this matches your DLL version + +public class QuickBooksConnector +{ + public string ProcessQBXML(string qbxmlRequest) + { + try + { + QBSessionManager sessionManager = new QBSessionManager(); + sessionManager.OpenConnection("", "YourAppName"); + sessionManager.BeginSession("", ENOpenMode.omDontCare); + + IMsgSetRequest requestMsgSet = sessionManager.CreateMsgSetRequest("US", 13, 0); + requestMsgSet.AppendXML(qbxmlRequest); + + IMsgSetResponse responseMsgSet = sessionManager.DoRequests(requestMsgSet); + string qbxmlResponse = responseMsgSet.ToXMLString(); + + sessionManager.EndSession(); + sessionManager.CloseConnection(); + + return qbxmlResponse; + } + catch (Exception ex) + { + return $"Error: {ex.Message}"; + } + } +} \ No newline at end of file diff --git a/src/main/quickbooks-desktop/quickbooks-desktop.ts b/src/main/quickbooks-desktop/quickbooks-desktop.ts new file mode 100644 index 0000000..68a1c76 --- /dev/null +++ b/src/main/quickbooks-desktop/quickbooks-desktop.ts @@ -0,0 +1,130 @@ +import log from "electron-log/main"; + +import { UUID } from "crypto"; +import { Request, Response } from "express"; +import _ from "lodash"; +import errorTypeCheck from "../../util/errorTypeCheck"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +let Winax: any; // Declare Winax as any to avoid TypeScript errors on non-Windows platforms + +if (process.platform === "win32") { + // eslint-disable-next-line @typescript-eslint/no-require-imports + Winax = require("winax"); +} + +export async function handleQuickBookRequest( + req: Request, + res: Response, +): Promise { + if (process.platform !== "win32") { + res.status(500).json({ + error: "QuickBooks Desktop integration is only available on Windows", + }); + return; + } + + const QbFilePath: string = `C:\\Users\\PatrickFic\\Development\\FRODO COLLISION.QBW`; + // || + // (store.get("settings.qbFilePath") as string) F + + if (_.isEmpty(QbFilePath)) { + res.status(400).json({ error: "Quickbooks file path not set" }); + return; + } + + const qbxmlRequestList = req.body as Array<{ + id: UUID; + okStatusCodes: Array; + qbxml: string; + }>; + + const returnResponse: Array<{ + Id: UUID; + Success: boolean; + ErrorMessage: string; + }> = []; + + //Connect to the QuickBooks File + let requestProcessor; + try { + requestProcessor = new Winax.Object("QBXMLRP2.RequestProcessor.2"); + requestProcessor.OpenConnection(QbFilePath, "ShopPartnerActualRequest"); + } catch (error) { + log.error( + "Error instnatiating QuickBooks Request Processor", + QbFilePath, + errorTypeCheck(error), + ); + res.status(500).json({ error: "Error connecting to QuickBooks" }); + return; + } + + const ticket = requestProcessor.BeginSession(QbFilePath, 2); //2 indicated qbFileOpenModeDoNotCare + log.info("Quickbooks Ticket", ticket); + for (const qbxmlRequest of qbxmlRequestList) { + try { + //TODO: Refactor to not create a new connection every time. + const QuickBooksResponse = requestProcessor.ProcessRequest( + ticket, + qbxmlRequest.qbxml, + ); + log.info("QuickBooks Raw Response: ", QuickBooksResponse); + returnResponse.push({ + Id: qbxmlRequest.id, + Success: + QuickBooksResponse.StatusCode === "0" || + qbxmlRequest.okStatusCodes.includes(QuickBooksResponse.StatusCode), + ErrorMessage: QuickBooksResponse, + }); + } catch (error) { + log.error( + "Error running transaction", + ticket, + qbxmlRequest, + errorTypeCheck(error), + ); + } + } + requestProcessor.EndSession(ticket); + requestProcessor.CloseConnection(); + res.json(qbxmlRequestList); +} + +//This set of functions works. +export function TestQB(): void { + if (process.platform !== "win32") { + log.warn("TestQB is only available on Windows"); + return; + } + let requestProcessor, ticket; + try { + requestProcessor = new Winax.Object("QBXMLRP.RequestProcessor.1"); + requestProcessor.OpenConnection("", "ShopPartnerOneoFf"); + + ticket = requestProcessor.BeginSession("", 2); //2 indicated qbFileOOpenModeDoNotCare + + requestProcessor.ProcessRequest( + ticket, + ` + + + + +`, + ); + } catch (error) { + log.error( + "Error instnatiating QuickBooks Request Processor", + + errorTypeCheck(error), + ); + + return; + } + + log.log("Ticket", ticket); + requestProcessor.EndSession(ticket); + requestProcessor.CloseConnection(); + return; +} diff --git a/src/main/setup-keep-alive-agent.ts b/src/main/setup-keep-alive-agent.ts new file mode 100644 index 0000000..1f924c0 --- /dev/null +++ b/src/main/setup-keep-alive-agent.ts @@ -0,0 +1,77 @@ +import { promises as fs } from "fs"; +import { join } from "path"; +import { homedir } from "os"; +import { exec } from "child_process"; +import { promisify } from "util"; +import log from "electron-log/main"; + +const execPromise = promisify(exec); + +// Define the interval as a variable (in seconds) +const KEEP_ALIVE_INTERVAL_SECONDS = 15 * 60; // 15 minutes + +export async function setupKeepAliveAgent(): Promise { + const plistContent = ` + + + + Label + com.convenientbrands.bodyshop-desktop.keepalive + ProgramArguments + + Shop Partner Keep Alive + imexmedia://keep-alive + + RunAtLoad + + StartInterval + ${KEEP_ALIVE_INTERVAL_SECONDS} + +`; + + const plistPath = join( + homedir(), + "/Library/LaunchAgents/com.convenientbrands.bodyshop-desktop.keepalive.plist", + ); + + try { + await fs.writeFile(plistPath, plistContent); + const { stdout, stderr } = await execPromise(`launchctl load ${plistPath}`); + log.info(`Launch agent created and loaded: ${stdout}`); + if (stderr) log.warn(`Launch agent stderr: ${stderr}`); + } catch (error) { + log.error( + `Error setting up launch agent: ${error instanceof Error ? error.message : String(error)}`, + ); + throw error; // Rethrow to allow caller to handle + } +} + +export async function isKeepAliveAgentInstalled(): Promise { + const plistPath = join( + homedir(), + "/Library/LaunchAgents/com.convenientbrands.bodyshop-desktop.keepalive.plist", + ); + const maxRetries = 3; + const retryDelay = 500; // 500ms delay between retries + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + await fs.access(plistPath, fs.constants.F_OK); + const { stdout } = await execPromise( + `launchctl list | grep com.convenientbrands.bodyshop-desktop.keepalive`, + ); + return !!stdout; // Return true if plist exists and agent is loaded + } catch (error) { + log.debug( + `Launch agent not found (attempt ${attempt}/${maxRetries}): ${error instanceof Error ? error.message : String(error)}`, + ); + if (attempt === maxRetries) { + return false; // Return false after all retries fail + } + // Wait before retrying + await new Promise((resolve) => setTimeout(resolve, retryDelay)); + } + } + return false; // Fallback return +} diff --git a/src/main/setup-keep-alive-task.ts b/src/main/setup-keep-alive-task.ts new file mode 100644 index 0000000..6e16f74 --- /dev/null +++ b/src/main/setup-keep-alive-task.ts @@ -0,0 +1,52 @@ +import { exec } from "child_process"; +import { promisify } from "util"; +import log from "electron-log/main"; + +const execPromise = promisify(exec); + +// Define the interval as a variable (in minutes) +const KEEP_ALIVE_INTERVAL_MINUTES = 15; +const taskName = "ShopPartnerKeepAlive"; + +export async function setupKeepAliveTask(): Promise { + const protocolUrl = "imexmedia://keep-alive"; + // Use rundll32.exe to silently open the URL as a protocol + const command = `rundll32.exe url.dll,OpenURL "${protocolUrl}"`; + // Escape quotes for schtasks /tr parameter + const escapedCommand = command.replace(/"/g, '\\"'); + + const schtasksCommand = `schtasks /create /tn "${taskName}" /tr "${escapedCommand}" /sc minute /mo ${KEEP_ALIVE_INTERVAL_MINUTES} /f`; + + try { + const { stdout, stderr } = await execPromise(schtasksCommand); + log.info(`Scheduled task created: ${stdout}`); + if (stderr) log.warn(`Scheduled task stderr: ${stderr}`); + } catch (error) { + log.error( + `Error creating scheduled task: ${error instanceof Error ? error.message : String(error)}`, + ); + throw error; // Rethrow to allow caller to handle + } +} + +export async function isKeepAliveTaskInstalled(): Promise { + const maxRetries = 3; + const retryDelay = 500; // 500ms delay between retries + + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const { stdout } = await execPromise(`schtasks /query /tn "${taskName}"`); + return !!stdout; // Return true if task exists + } catch (error) { + log.debug( + `Scheduled task ${taskName} not found (attempt ${attempt}/${maxRetries}): ${error instanceof Error ? error.message : String(error)}`, + ); + if (attempt === maxRetries) { + return false; // Return false after all retries fail + } + // Wait before retrying + await new Promise((resolve) => setTimeout(resolve, retryDelay)); + } + } + return false; // Fallback return +} diff --git a/src/main/store/store.ts b/src/main/store/store.ts new file mode 100644 index 0000000..62968bd --- /dev/null +++ b/src/main/store/store.ts @@ -0,0 +1,40 @@ +import Store from "electron-store"; + +const store = new Store({ + defaults: { + settings: { + runOnStartup: true, + filepaths: [], + ppcFilePath: null, + emsOutFilePath: null, + qbFilePath: "", + runWatcherOnStartup: true, + enableMemDebug: false, + polling: { + enabled: false, + interval: 30000, + }, + }, + app: { + windowBounds: { + width: 800, + height: 600, + x: undefined, + y: undefined, + }, + user: null, + isTest: false, + bodyshop: {}, + masterdata: { + opcodes: null, + }, + }, + }, +}); + +// store.onDidAnyChange((newValue, oldValue) => { +// const mainWindow = BrowserWindow.getAllWindows()[0]; +// mainWindow?.webContents.send(ipcTypes.toRenderer.store.didChange, newValue); +// }); + +export default store; diff --git a/src/main/util/checkForAppUpdates.ts b/src/main/util/checkForAppUpdates.ts new file mode 100644 index 0000000..ea5e3c4 --- /dev/null +++ b/src/main/util/checkForAppUpdates.ts @@ -0,0 +1,23 @@ +import { autoUpdater } from "electron-updater"; +import { setReleaseChannel } from "../ipc/ipcMainHandler.user"; + +let continuousUpdatesTriggered = false; + +async function checkForAppUpdatesContinuously(): Promise { + if (!continuousUpdatesTriggered) { + continuousUpdatesTriggered = true; + checkForAppUpdates(); + setInterval( + () => { + checkForAppUpdates(); + }, + 1000 * 60 * 30, + ); + } +} +async function checkForAppUpdates(): Promise { + await setReleaseChannel(); + autoUpdater.checkForUpdates(); +} + +export { checkForAppUpdates, checkForAppUpdatesContinuously }; diff --git a/src/main/util/createDirectoryIfNotExist.ts b/src/main/util/createDirectoryIfNotExist.ts new file mode 100644 index 0000000..3b049a4 --- /dev/null +++ b/src/main/util/createDirectoryIfNotExist.ts @@ -0,0 +1,21 @@ +import log from "electron-log/main"; +import fs from "fs"; +import path from "path"; +import errorTypeCheck from "../../util/errorTypeCheck"; + +const createdDirectoryIfNotExist = async (dirPath: string) => { + try { + const directoryPath = path.dirname(dirPath); + if (!fs.existsSync(directoryPath)) { + log.info(`Directory does not exist. Creating: ${directoryPath}`); + fs.mkdirSync(directoryPath, { recursive: true }); + } + } catch (error) { + log.error("Error creating directory as needed", errorTypeCheck(error)); + throw new Error( + "Error creating directory: " + errorTypeCheck(error).message, + ); + } +}; + +export default createdDirectoryIfNotExist; diff --git a/src/main/util/ems-interface/fielddescriptors/ad1-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/ad1-field-descriptors.ts new file mode 100644 index 0000000..cdcd889 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/ad1-field-descriptors.ts @@ -0,0 +1,706 @@ +import { FieldDescriptor } from "dbffile"; + +export const ad1FieldLineDescriptors: FieldDescriptor[] = [ + { + name: "INS_CO_ID", + type: "C", + size: 5, + decimalPlaces: 0, + }, + { + name: "INS_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INS_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INS_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INS_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "INS_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "INS_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "INS_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "INS_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INS_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INS_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INS_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INS_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INS_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INS_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INS_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INS_TITLE", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INS_CT_PH", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INS_CT_PHX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INS_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "INS_MEMO", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "POLICY_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "DED_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "DED_STATUS", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "ASGN_NO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "ASGN_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "ASGN_TYPE", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "CLM_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "CLM_OFC_ID", + type: "C", + size: 5, + decimalPlaces: 0, + }, + { + name: "CLM_OFC_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLM_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "CLM_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "CLM_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "CLM_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "CLM_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "CLM_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "CLM_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLM_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLM_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLM_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLM_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLM_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLM_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLM_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLM_TITLE", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLM_CT_PH", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLM_CT_PHX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLM_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "PAYEE_NMS", + type: "C", + size: 85, + decimalPlaces: 0, + }, + { + name: "PAY_TYPE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PAY_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "PAY_CHKNM", + type: "C", + size: 16, + decimalPlaces: 0, + }, + { + name: "PAY_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "PAY_MEMO", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "AGT_CO_ID", + type: "C", + size: 5, + decimalPlaces: 0, + }, + { + name: "AGT_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "AGT_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "AGT_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "AGT_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "AGT_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "AGT_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "AGT_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "AGT_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "AGT_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "AGT_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "AGT_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "AGT_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "AGT_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "AGT_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "AGT_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "AGT_CT_PH", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "AGT_CT_PHX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "AGT_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "AGT_LIC_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "LOSS_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "LOSS_CAT", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "LOSS_TYPE", + type: "C", + size: 7, + decimalPlaces: 0, + }, + { + name: "LOSS_DESC", + type: "C", + size: 38, + decimalPlaces: 0, + }, + { + name: "THEFT_IND", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "CAT_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "TLOS_IND", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LOSS_MEMO", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CUST_PR", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "INSD_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INSD_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INSD_TITLE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "INSD_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INSD_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INSD_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INSD_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "INSD_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "INSD_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "INSD_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "INSD_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSD_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSD_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSD_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSD_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSD_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSD_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "OWNR_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "OWNR_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "OWNR_TITLE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "OWNR_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "OWNR_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "OWNR_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "OWNR_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "OWNR_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "OWNR_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "OWNR_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "OWNR_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "OWNR_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "OWNR_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "OWNR_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "OWNR_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "OWNR_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "OWNR_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/ad2-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/ad2-field-descriptors.ts new file mode 100644 index 0000000..65036b6 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/ad2-field-descriptors.ts @@ -0,0 +1,640 @@ +import { FieldDescriptor } from "dbffile"; + +export const ad2FieldLineDescriptors: FieldDescriptor[] = [ + { + name: "CLMT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLMT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLMT_TITLE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "CLMT_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "CLMT_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "CLMT_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "CLMT_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "CLMT_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "CLMT_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "CLMT_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "CLMT_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLMT_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLMT_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLMT_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLMT_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "CLMT_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "CLMT_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "EST_CO_ID", + type: "C", + size: 5, + decimalPlaces: 0, + }, + { + name: "EST_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "EST_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "EST_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "EST_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "EST_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "EST_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "EST_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "EST_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "EST_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "EST_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "EST_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "EST_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "EST_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "EST_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "EST_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "EST_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "EST_LIC_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "EST_FILENO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "INSP_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INSP_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "INSP_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INSP_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INSP_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "INSP_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "INSP_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "INSP_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "INSP_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSP_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSP_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSP_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSP_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "INSP_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSP_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "INSP_CODE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "INSP_DESC", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "INSP_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "INSP_TIME", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "RF_CO_ID", + type: "C", + size: 5, + decimalPlaces: 0, + }, + { + name: "RF_CO_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "RF_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "RF_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "RF_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "RF_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "RF_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "RF_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "RF_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "RF_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "RF_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "RF_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "RF_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "RF_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "RF_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "RF_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "RF_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "RF_TAX_ID", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "RF_LIC_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "RF_BAR_NO", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "RO_IN_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "RO_IN_TIME", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "RO_AUTH", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "TAR_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "TAR_TIME", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "RO_CMPDATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "RO_CMPTIME", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "DATE_OUT", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "TIME_OUT", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "RF_ESTIMTR", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "MKTG_TYPE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MKTG_SRC", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "LOC_NM", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "LOC_ADDR1", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "LOC_ADDR2", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "LOC_CITY", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "LOC_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LOC_ZIP", + type: "C", + size: 11, + decimalPlaces: 0, + }, + { + name: "LOC_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "LOC_PH1", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "LOC_PH1X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "LOC_PH2", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "LOC_PH2X", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "LOC_FAX", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "LOC_FAXX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "LOC_CT_LN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "LOC_CT_FN", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "LOC_TITLE", + type: "C", + size: 35, + decimalPlaces: 0, + }, + { + name: "LOC_PH", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "LOC_PHX", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "LOC_EA", + type: "C", + size: 80, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/env-field-descriptor.ts b/src/main/util/ems-interface/fielddescriptors/env-field-descriptor.ts new file mode 100644 index 0000000..ec84c52 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/env-field-descriptor.ts @@ -0,0 +1,154 @@ +import { FieldDescriptor } from "dbffile"; + +export const envFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "EST_SYSTEM", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "SW_VERSION", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "DB_VERSION", + type: "C", + size: 12, + decimalPlaces: 0, + }, + { + name: "DB_DATE", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "UNQFILE_ID", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "RO_ID", + type: "C", + size: 8, + decimalPlaces: 0, + }, + { + name: "ESTFILE_ID", + type: "C", + size: 38, + decimalPlaces: 0, + }, + { + name: "SUPP_NO", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "EST_CTRY", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "TOP_SECRET", + type: "C", + size: 80, + decimalPlaces: 0, + }, + { + name: "H_TRANS_ID", + type: "C", + size: 9, + decimalPlaces: 0, + }, + { + name: "H_CTRL_NO", + type: "C", + size: 9, + decimalPlaces: 0, + }, + { + name: "TRANS_TYPE", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STATUS", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "CREATE_DT", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "CREATE_TM", + type: "C", + size: 6, + decimalPlaces: 0, + }, + { + name: "TRANSMT_DT", + type: "D", + size: 8, + decimalPlaces: 0, + }, + { + name: "TRANSMT_TM", + type: "C", + size: 6, + decimalPlaces: 0, + }, + { + name: "INCL_ADMIN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "INCL_VEH", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "INCL_EST", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "INCL_PROFL", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "INCL_TOTAL", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "INCL_VENDR", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "EMS_VER", + type: "C", + size: 5, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/lin-field-descriptor.ts b/src/main/util/ems-interface/fielddescriptors/lin-field-descriptor.ts new file mode 100644 index 0000000..968d78b --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/lin-field-descriptor.ts @@ -0,0 +1,274 @@ +import { FieldDescriptor } from "dbffile"; + +export const linFieldDescriptors: FieldDescriptor[] = [ + { + name: "LINE_NO", + type: "N", + size: 3, + decimalPlaces: 0, + }, + { + name: "LINE_IND", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "LINE_REF", + type: "N", + size: 3, + decimalPlaces: 0, + }, + { + name: "TRAN_CODE", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "DB_REF", + type: "C", + size: 7, + decimalPlaces: 0, + }, + { + name: "UNQ_SEQ", + type: "N", + size: 4, + decimalPlaces: 0, + }, + { + name: "WHO_PAYS", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LINE_DESC", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "PART_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "PART_DES_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "GLASS_FLAG", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "OEM_PARTNO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "PRICE_INC", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "ALT_PART_I", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_PART", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "DB_PRICE", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "ACT_PRICE", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "PRICE_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "CERT_PART", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PART_QTY", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "ALT_CO_ID", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "ALT_PARTNO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "ALT_OVERRD", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "ALT_PARTM", + type: "C", + size: 45, + decimalPlaces: 0, + }, + { + name: "PRT_DSMK_P", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "PRT_DSMK_M", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MOD_LBR_TY", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "DB_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "MOD_LB_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "LBR_INC", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_OP", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "LBR_HRS_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TYP_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_OP_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PAINT_STG", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "PAINT_TONE", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MISC_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MISC_SUBLT", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "MISC_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "BETT_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "BETT_PCTG", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "BETT_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "BETT_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/lin-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/lin-field-descriptors.ts new file mode 100644 index 0000000..4d912b1 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/lin-field-descriptors.ts @@ -0,0 +1,274 @@ +import { FieldDescriptor } from "dbffile"; + +export const linFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "LINE_NO", + type: "N", + size: 3, + decimalPlaces: 0, + }, + { + name: "LINE_IND", + type: "C", + size: 3, + decimalPlaces: 0, + }, + { + name: "LINE_REF", + type: "N", + size: 3, + decimalPlaces: 0, + }, + { + name: "TRAN_CODE", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "DB_REF", + type: "C", + size: 7, + decimalPlaces: 0, + }, + { + name: "UNQ_SEQ", + type: "N", + size: 4, + decimalPlaces: 0, + }, + { + name: "WHO_PAYS", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LINE_DESC", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "PART_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "PART_DES_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "GLASS_FLAG", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "OEM_PARTNO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "PRICE_INC", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "ALT_PART_I", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_PART", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "DB_PRICE", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "ACT_PRICE", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "PRICE_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "CERT_PART", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PART_QTY", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "ALT_CO_ID", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "ALT_PARTNO", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "ALT_OVERRD", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "ALT_PARTM", + type: "C", + size: 45, + decimalPlaces: 0, + }, + { + name: "PRT_DSMK_P", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "PRT_DSMK_M", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MOD_LBR_TY", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "DB_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "MOD_LB_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "LBR_INC", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_OP", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "LBR_HRS_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TYP_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_OP_J", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PAINT_STG", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "PAINT_TONE", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MISC_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "MISC_SUBLT", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "MISC_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "BETT_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "BETT_PCTG", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "BETT_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "BETT_TAX", + type: "L", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pfh-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/pfh-field-descriptors.ts new file mode 100644 index 0000000..42d1187 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pfh-field-descriptors.ts @@ -0,0 +1,118 @@ +import { FieldDescriptor } from "dbffile"; + +export const pfhFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "ID_PRO_NAM", + type: "C", + size: 40, + decimalPlaces: 0, + }, + { + name: "TAX_PRETHR", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_THRAMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "TAX_PSTTHR", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_TOW_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_TOW_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_STR_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_STR_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_SUB_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_SUB_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_BTR_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_LBR_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_GST_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TAX_GST_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "ADJ_G_DISC", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "ADJ_TOWDIS", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "ADJ_STRDIS", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "ADJ_BTR_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "TAX_PREDIS", + type: "N", + size: 7, + decimalPlaces: 2, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pfl-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/pfl-field-descriptors.ts new file mode 100644 index 0000000..0d5df85 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pfl-field-descriptors.ts @@ -0,0 +1,100 @@ +import { FieldDescriptor } from "dbffile"; + +export const pflFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "LBR_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "LBR_DESC", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "LBR_RATE", + type: "N", + size: 6, + decimalPlaces: 2, + }, + { + name: "LBR_TAX_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TAXP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "LBR_ADJP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "LBR_TX_TY1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LBR_TX_IN1", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TX_TY2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LBR_TX_IN2", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TX_TY3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LBR_TX_IN3", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TX_TY4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LBR_TX_IN4", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "LBR_TX_TY5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "LBR_TX_IN5", + type: "C", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pfm-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/pfm-field-descriptors.ts new file mode 100644 index 0000000..215c63d --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pfm-field-descriptors.ts @@ -0,0 +1,166 @@ +import { FieldDescriptor } from "dbffile"; + +export const pfmFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "MATL_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "CAL_CODE", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "CAL_DESC", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "CAL_MAXDLR", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "CAL_PRIP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "CAL_SECP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "MAT_CALP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "CAL_PRETHR", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "CAL_PSTTHR", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "CAL_THRAMT", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "CAL_LBRMIN", + type: "N", + size: 4, + decimalPlaces: 1, + }, + { + name: "CAL_LBRMAX", + type: "N", + size: 4, + decimalPlaces: 1, + }, + { + name: "CAL_LBRRTE", + type: "N", + size: 6, + decimalPlaces: 2, + }, + { + name: "CAL_OPCODE", + type: "C", + size: 48, + decimalPlaces: 0, + }, + { + name: "TAX_IND", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "MAT_TAXP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "MAT_ADJP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "MAT_TX_TY1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MAT_TX_IN1", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "MAT_TX_TY2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MAT_TX_IN2", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "MAT_TX_TY3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MAT_TX_IN3", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "MAT_TX_TY4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MAT_TX_IN4", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "MAT_TX_TY5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "MAT_TX_IN5", + type: "C", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pfo-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/pfo-field-descriptors.ts new file mode 100644 index 0000000..e901baa --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pfo-field-descriptors.ts @@ -0,0 +1,160 @@ +import { FieldDescriptor } from "dbffile"; + +export const pfoFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "TX_TOW_TY", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN1", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN2", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN3", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN4", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN5", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TOW_T_TY6", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TOW_T_IN6", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "TX_STOR_TY", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN1", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN2", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN3", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN4", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN5", + type: "C", + size: 1, + decimalPlaces: 0, + }, + { + name: "STOR_T_TY6", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "STOR_T_IN6", + type: "C", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pfp-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/pfp-field-descriptors.ts new file mode 100644 index 0000000..121a576 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pfp-field-descriptors.ts @@ -0,0 +1,100 @@ +import { FieldDescriptor } from "dbffile"; + +export const pfpFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "PRT_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "PRT_TAX_IN", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_TAX_RT", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "PRT_MKUPP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "PRT_MKTYP", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_DISCP", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "PRT_TX_TY1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PRT_TX_IN1", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_TX_TY2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PRT_TX_IN2", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_TX_TY3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PRT_TX_IN3", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_TX_TY4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PRT_TX_IN4", + type: "L", + size: 1, + decimalPlaces: 0, + }, + { + name: "PRT_TX_TY5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "PRT_TX_IN5", + type: "L", + size: 1, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/pft-field-descriptor.ts b/src/main/util/ems-interface/fielddescriptors/pft-field-descriptor.ts new file mode 100644 index 0000000..5dc2fb5 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/pft-field-descriptor.ts @@ -0,0 +1,760 @@ +import { FieldDescriptor } from "dbffile"; + +export const pftFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "TAX_TYPE1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY1_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY1_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY1_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY1_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY1_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY1_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY1_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TAX_TYPE2", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY2_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY2_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY2_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY2_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY2_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY2_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY2_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TAX_TYPE3", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY3_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY3_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY3_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY3_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY3_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY3_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY3_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TAX_TYPE4", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY4_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY4_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY4_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY4_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY4_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY4_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY4_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TAX_TYPE5", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY5_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY5_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY5_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY5_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY5_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY5_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY5_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TAX_TYPE6", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_TIER1", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_THRES1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_RATE1", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY6_SUR1", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_TIER2", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_THRES2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_RATE2", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY6_SUR2", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_TIER3", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_THRES3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_RATE3", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY6_SUR3", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_TIER4", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_THRES4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_RATE4", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY6_SUR4", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_TIER5", + type: "N", + size: 2, + decimalPlaces: 0, + }, + { + name: "TY6_THRES5", + type: "N", + size: 7, + decimalPlaces: 2, + }, + { + name: "TY6_RATE5", + type: "N", + size: 8, + decimalPlaces: 4, + }, + { + name: "TY6_SUR5", + type: "N", + size: 7, + decimalPlaces: 2, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/stl-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/stl-field-descriptors.ts new file mode 100644 index 0000000..7cfe201 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/stl-field-descriptors.ts @@ -0,0 +1,112 @@ +import { FieldDescriptor } from "dbffile"; + +export const stlFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "TTL_TYPE", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "TTL_TYPECD", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "T_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "T_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "T_ADDLBR", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "T_DISCAMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "T_MKUPAMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "T_GDISCAMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "TAX_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "NT_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "NT_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "NT_ADDLBR", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "NT_DISC", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "NT_MKUP", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "NT_GDIS", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "TTL_TYPAMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, + { + name: "TTL_HRS", + type: "N", + size: 5, + decimalPlaces: 1, + }, + { + name: "TTL_AMT", + type: "N", + size: 9, + decimalPlaces: 2, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/ttl-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/ttl-field-descriptors.ts new file mode 100644 index 0000000..b395b8d --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/ttl-field-descriptors.ts @@ -0,0 +1,88 @@ +import { FieldDescriptor } from "dbffile"; + +export const ttlFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "G_TTL_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_BETT_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_RPD_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_DED_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_CUST_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_AA_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "N_TTL_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "PREV_NET", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "SUPP_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "N_SUPP_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_UPD_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_TTL_DISC", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "G_TAX", + type: "N", + size: 10, + decimalPlaces: 2, + }, + { + name: "GST_AMT", + type: "N", + size: 10, + decimalPlaces: 2, + }, +]; diff --git a/src/main/util/ems-interface/fielddescriptors/veh-field-descriptors.ts b/src/main/util/ems-interface/fielddescriptors/veh-field-descriptors.ts new file mode 100644 index 0000000..6ce4c00 --- /dev/null +++ b/src/main/util/ems-interface/fielddescriptors/veh-field-descriptors.ts @@ -0,0 +1,172 @@ +import { FieldDescriptor } from "dbffile"; + +export const vehFieldLineDescriptors: FieldDescriptor[] = [ + { + name: "IMPACT_1", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "IMPACT_2", + type: "C", + size: 30, + decimalPlaces: 0, + }, + { + name: "DMG_MEMO", + type: "C", // Changed from "M" to "C" to allow writing, need to verify if this still works. + size: 10, + decimalPlaces: 0, + }, + { + name: "DB_V_CODE", + type: "C", + size: 7, + decimalPlaces: 0, + }, + { + name: "PLATE_NO", + type: "C", + size: 10, + decimalPlaces: 0, + }, + { + name: "PLATE_ST", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "V_VIN", + type: "C", + size: 25, + decimalPlaces: 0, + }, + { + name: "V_COND", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "V_PROD_DT", + type: "C", + size: 4, + decimalPlaces: 0, + }, + { + name: "V_MODEL_YR", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "V_MAKECODE", + type: "C", + size: 12, + decimalPlaces: 0, + }, + { + name: "V_MAKEDESC", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_MODEL", + type: "C", + size: 50, + decimalPlaces: 0, + }, + { + name: "V_TYPE", + type: "C", + size: 2, + decimalPlaces: 0, + }, + { + name: "V_BSTYLE", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_TRIMCODE", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "TRIM_COLOR", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_MLDGCODE", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_ENGINE", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_MILEAGE", + type: "C", + size: 6, + decimalPlaces: 0, + }, + { + name: "V_OPTIONS", + type: "C", // Changed from "M" to "C" to allow writing, need to verify if this still works. + size: 10, + decimalPlaces: 0, + }, + { + name: "V_COLOR", + type: "C", + size: 20, + decimalPlaces: 0, + }, + { + name: "V_TONE", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "V_STAGE", + type: "N", + size: 1, + decimalPlaces: 0, + }, + { + name: "PAINT_CD1", + type: "C", + size: 15, + decimalPlaces: 0, + }, + { + name: "PAINT_CD2", + type: "C", + size: 15, + decimalPlaces: 0, + }, + { + name: "PAINT_CD3", + type: "C", + size: 15, + decimalPlaces: 0, + }, + { + name: "V_MEMO", //dbffile does not support writing to a memo field. + type: "C", // Changed from "M" to "C" to allow writing, need to verify if this still works. + size: 10, + decimalPlaces: 0, + }, +]; diff --git a/src/main/util/ems-util.ts b/src/main/util/ems-util.ts new file mode 100644 index 0000000..a1c449e --- /dev/null +++ b/src/main/util/ems-util.ts @@ -0,0 +1,36 @@ +import path from "path"; +import store from "../store/store"; +import fs from "fs"; + +const generatePpcFilePath = (filename: string): string => { + const ppcOutFilePath: string | null = store.get("settings.ppcFilePath"); + if (!ppcOutFilePath) { + throw new Error("PPC file path is not set"); + } + return path.resolve(ppcOutFilePath, filename); +}; + +const generateEmsOutFilePath = (filename: string): string => { + const emsOutFilePath: string | null = store.get("settings.emsOutFilePath"); + if (!emsOutFilePath) { + throw new Error("EMS Out file path is not set"); + } + return path.resolve(emsOutFilePath, filename); +}; + +const deleteEmsFileIfExists = async (filename: string): Promise => { + // Check if the file exists and delete it if it does + try { + await fs.promises.access(filename); // Check if the file exists + await fs.promises.unlink(filename); // Delete the file + console.log(`Existing file at ${filename} deleted.`); + } catch (err) { + if ((err as NodeJS.ErrnoException).code !== "ENOENT") { + // If the error is not "file not found", rethrow it + throw err; + } + console.log(`No existing file found at ${filename}.`); + } +}; + +export { generatePpcFilePath, generateEmsOutFilePath, deleteEmsFileIfExists }; diff --git a/src/main/util/ensureWindowOnScreen.ts b/src/main/util/ensureWindowOnScreen.ts new file mode 100644 index 0000000..2cd1f07 --- /dev/null +++ b/src/main/util/ensureWindowOnScreen.ts @@ -0,0 +1,109 @@ +import { screen } from "electron"; + +function ensureWindowOnScreen( + x: number | undefined, + y: number | undefined, + windowWidth: number, + windowHeight: number, +): { validX: number | undefined; validY: number | undefined } { + // If no coordinates stored, let Electron position window automatically + if (x === undefined || y === undefined) { + return { validX: undefined, validY: undefined }; + } + + const displays = screen.getAllDisplays(); + + // Minimum visible pixels required on each edge to be considered "visible enough" + const MIN_VISIBLE = 50; // Ensure at least 50px from each edge is visible + + // Try to find a display where the window would be almost fully visible + for (const display of displays) { + const { bounds } = display; + + // Check if window is mostly within this display + if ( + x + MIN_VISIBLE >= bounds.x && + x + windowWidth - MIN_VISIBLE <= bounds.x + bounds.width && + y + MIN_VISIBLE >= bounds.y && + y + windowHeight - MIN_VISIBLE <= bounds.y + bounds.height + ) { + // Window is adequately visible on this display + return { validX: x, validY: y }; + } + } + + // If window isn't adequately visible on any display, try to adjust it to fit the closest display + const closestDisplay = findClosestDisplay(displays, x, y); + const { bounds } = closestDisplay; + + // Adjust position to ensure window is fully on screen + let adjustedX = x; + let adjustedY = y; + + // Adjust horizontal position if needed + if (x < bounds.x) { + adjustedX = bounds.x; + } else if (x + windowWidth > bounds.x + bounds.width) { + adjustedX = bounds.x + bounds.width - windowWidth; + } + + // Adjust vertical position if needed + if (y < bounds.y) { + adjustedY = bounds.y; + } else if (y + windowHeight > bounds.y + bounds.height) { + adjustedY = bounds.y + bounds.height - windowHeight; + } + + // If adjustments keep window on screen, use adjusted position + if ( + adjustedX >= bounds.x && + adjustedX + windowWidth <= bounds.x + bounds.width && + adjustedY >= bounds.y && + adjustedY + windowHeight <= bounds.y + bounds.height + ) { + return { validX: adjustedX, validY: adjustedY }; + } + + // If all else fails, center on primary display + const primaryDisplay = screen.getPrimaryDisplay(); + const primaryBounds = primaryDisplay.bounds; + + return { + validX: Math.floor( + primaryBounds.x + (primaryBounds.width - windowWidth) / 2, + ), + validY: Math.floor( + primaryBounds.y + (primaryBounds.height - windowHeight) / 2, + ), + }; +} + +// Helper function to find the closest display to a point +function findClosestDisplay( + displays: Electron.Display[], + x: number, + y: number, +): Electron.Display { + let closestDisplay = displays[0]; + let shortestDistance = Number.MAX_VALUE; + + for (const display of displays) { + const { bounds } = display; + // Calculate distance to center of display + const displayCenterX = bounds.x + bounds.width / 2; + const displayCenterY = bounds.y + bounds.height / 2; + + const distance = Math.sqrt( + Math.pow(x - displayCenterX, 2) + Math.pow(y - displayCenterY, 2), + ); + + if (distance < shortestDistance) { + shortestDistance = distance; + closestDisplay = display; + } + } + + return closestDisplay; +} + +export default ensureWindowOnScreen; diff --git a/src/main/util/setAppProgressBar.ts b/src/main/util/setAppProgressBar.ts new file mode 100644 index 0000000..396bbf2 --- /dev/null +++ b/src/main/util/setAppProgressBar.ts @@ -0,0 +1,9 @@ +import { getMainWindow } from "./toRenderer"; + +const setAppProgressbar = (progress: number): void => { + const mainWindow = getMainWindow(); + if (mainWindow) { + mainWindow.setProgressBar(progress); + } +}; +export default setAppProgressbar; diff --git a/src/main/util/toRenderer.ts b/src/main/util/toRenderer.ts new file mode 100644 index 0000000..39b23f2 --- /dev/null +++ b/src/main/util/toRenderer.ts @@ -0,0 +1,20 @@ +import {BrowserWindow} from "electron"; +import log from "electron-log/main"; + +const getMainWindow = (): Electron.BrowserWindow => { + return BrowserWindow.getAllWindows()[0]; +}; + +const sendIpcToRenderer = (ipcMessage: string, ...args: any[]): void => { + const window = getMainWindow(); + if (window) { + window.webContents.send(ipcMessage, ...args); + } else { + log.error( + "Unable to find main window. Cannot send IPC message.", + ipcMessage, + args, + ); + } +}; +export { getMainWindow, sendIpcToRenderer }; diff --git a/src/main/util/uppercaseObjectKeys.ts b/src/main/util/uppercaseObjectKeys.ts new file mode 100644 index 0000000..44b9ec3 --- /dev/null +++ b/src/main/util/uppercaseObjectKeys.ts @@ -0,0 +1,24 @@ +/** + * Converts all keys of an object to uppercase + * @param obj The object whose keys need to be converted to uppercase + * @returns A new object with all keys converted to uppercase + */ +function uppercaseObjectKeys>( + obj: T, +): Record { + if (typeof obj !== "object" || obj === null) { + return obj; + } + + return Object.entries(obj).reduce( + (result, [key, value]) => { + const uppercaseKey = key.toUpperCase(); + result[uppercaseKey] = typeof value === "object" && value !== null + ? uppercaseObjectKeys(value) + : value; + return result; + }, + {} as Record, + ); +} +export default uppercaseObjectKeys; diff --git a/src/main/watcher/watcher.ts b/src/main/watcher/watcher.ts new file mode 100644 index 0000000..cd3bf11 --- /dev/null +++ b/src/main/watcher/watcher.ts @@ -0,0 +1,170 @@ +import chokidar, { FSWatcher } from "chokidar"; +import { BrowserWindow, Notification } from "electron"; +import log from "electron-log/main"; +import fs from "fs"; +import path from "path"; +import errorTypeCheck from "../../util/errorTypeCheck"; +import ipcTypes from "../../util/ipcTypes.json"; +import ImportJob from "../decoder/decoder"; +import store from "../store/store"; +import getMainWindow from "../../util/getMainWindow"; +let watcher: FSWatcher | null; + +async function StartWatcher(): Promise { + const filePaths: string[] = store.get("settings.filepaths") || []; + + if (filePaths.length === 0) { + new Notification({ + //TODO: Add Translations + title: "Watcher cannot start", + body: "Please set the appropriate file paths and try again.", + }).show(); + log.warn("Cannot start watcher. No file paths set."); + return false; + } + + if (watcher) { + try { + log.info("Trying to close watcher - it already existed."); + await watcher.close(); + + log.info("Watcher closed successfully!"); + } catch (error) { + log.error("Error trying to close Watcher.", error); + } + } + + const pollingSettings = + (store.get("settings.polling") as { + enabled?: boolean; + interval?: number; + }) || {}; + + watcher = chokidar.watch(filePaths, { + ignored: (filepath, stats) => { + const p = path.parse(filepath); + return ( + (!stats?.isFile() && p.ext !== "" && p.ext.toUpperCase() !== ".ENV") || + p.name?.toUpperCase() === ".DS_STORE" + ); //Only watch for .ENV files. + }, + usePolling: pollingSettings.enabled || false, + interval: pollingSettings.interval || 30000, + persistent: true, + ignoreInitial: true, + awaitWriteFinish: { + pollInterval: 500, + stabilityThreshold: 2000, + }, + }); + + watcher + .on("add", async function (path) { + console.log("File", path, "has been added"); + HandleNewFile(path); + }) + // .on("addDir", function (path) { + // console.log("Directory", path, "has been added"); + // }) + .on("change", async function (path) { + console.log("File", path, "has been changed"); + HandleNewFile(path); + }) + // .on("unlink", function (path) { + // console.log("File", path, "has been removed"); + // }) + // .on("unlinkDir", function (path) { + // console.log("Directory", path, "has been removed"); + // }) + .on("error", function (error) { + log.error("Error in Watcher", errorTypeCheck(error)); + // mainWindow.webContents.send( + // ipcTypes.toRenderer.watcher.error, + // errorTypeCheck(error) + // ); + }) + .on("ready", onWatcherReady); + // .on("raw", function (event, path, details) { + // // This event should be triggered everytime something happens. + // // console.log("Raw event info:", event, path, details); + // }); + + return true; +} + +function removeWatcherPath(path: string): void { + if (watcher) { + watcher.unwatch(path); + log.debug(`Stopped watching path: ${path}`); + } +} + +function addWatcherPath(path: string | string[]): void { + if (watcher) { + watcher.add(path); + log.debug(`Started watching path: ${path}`); + } +} + +function onWatcherReady(): void { + if (watcher) { + const mainWindow = getMainWindow(); + new Notification({ + title: "Watcher Started", + body: "Newly exported estimates will be automatically uploaded.", + }).show(); + log.info("Confirmed watched paths:", watcher.getWatched()); + mainWindow?.webContents.send(ipcTypes.toRenderer.watcher.started); + } +} + +async function StopWatcher(): Promise { + const mainWindow = getMainWindow(); + + if (watcher) { + await watcher.close(); + log.info("Watcher stopped."); + mainWindow?.webContents.send(ipcTypes.toRenderer.watcher.stopped); + + new Notification({ + title: "Watcher Stopped", + body: "Estimates will not be automatically uploaded.", + }).show(); + return true; + } + return false; +} + +async function HandleNewFile(path): Promise { + log.log("Received a new file", path); + await ImportJob(path); +} + +function GetAllEnvFiles(): string[] { + const directories = store.get("settings.filepaths") as string[]; + const files: string[] = []; + directories.forEach((directory) => { + try { + const envFiles = fs + .readdirSync(directory) + .filter((file: string) => file.toLowerCase().endsWith(".env")); + envFiles.forEach((file) => { + const fullPath = path.join(directory, file); + files.push(fullPath); + }); + } catch (error) { + log.error(`Failed to read directory ${directory}:`, error); + throw error; + } + }); + return files; +} + +export { + addWatcherPath, + GetAllEnvFiles, + removeWatcherPath, + StartWatcher, + StopWatcher, + watcher, +}; diff --git a/src/preload/index.d.ts b/src/preload/index.d.ts new file mode 100644 index 0000000..ab1657a --- /dev/null +++ b/src/preload/index.d.ts @@ -0,0 +1,8 @@ +import { ElectronAPI } from "@electron-toolkit/preload"; + +declare global { + interface Window { + electron: ElectronAPI; + api: unknown; + } +} diff --git a/src/preload/index.ts b/src/preload/index.ts new file mode 100644 index 0000000..4485593 --- /dev/null +++ b/src/preload/index.ts @@ -0,0 +1,30 @@ +import { contextBridge } from "electron"; +import { electronAPI } from "@electron-toolkit/preload"; +import "electron-log/preload"; +import store from "../main/store/store"; + +// Custom APIs for renderer +interface Api { + isTest: () => boolean; +} + +const api: Api = { + isTest: (): boolean => store.get("app.isTest") || false, +}; + +// Use `contextBridge` APIs to expose Electron APIs to +// renderer only if context isolation is enabled, otherwise +// just add to the DOM global. +if (process.contextIsolated) { + try { + contextBridge.exposeInMainWorld("electron", electronAPI); + contextBridge.exposeInMainWorld("api", api); + } catch (error) { + console.error(error); + } +} else { + // @ts-ignore (define in dts) + window.electron = electronAPI; + // @ts-ignore (define in dts) + window.api = api; +} diff --git a/src/renderer/index.html b/src/renderer/index.html new file mode 100644 index 0000000..05d34b0 --- /dev/null +++ b/src/renderer/index.html @@ -0,0 +1,17 @@ + + + + + Shop Partner + + + + + +
+ + + diff --git a/src/renderer/src/App.test.tsx b/src/renderer/src/App.test.tsx new file mode 100644 index 0000000..3b3d936 --- /dev/null +++ b/src/renderer/src/App.test.tsx @@ -0,0 +1,97 @@ +import { test, expect } from "@playwright/test"; +import { Page } from "@playwright/test"; + +// src/renderer/src/App.test.tsx + +// Mock data +const mockUser = { + uid: "test123", + email: "test@example.com", + displayName: "Test User", + toJSON: () => ({ + uid: "test123", + email: "test@example.com", + displayName: "Test User", + }), +}; + +test.describe("App Component", () => { + let page: Page; + + test.beforeEach(async ({ browser }) => { + page = await browser.newPage(); + + // Mock Firebase Auth + await page.addInitScript(() => { + window.mockAuthState = null; + + // Mock the firebase auth module + jest.mock("./util/firebase", () => ({ + auth: { + onAuthStateChanged: (callback) => { + callback(window.mockAuthState); + // Return mock unsubscribe function + return () => {}; + }, + }, + })); + + // Mock electron IPC + window.electron = { + ipcRenderer: { + send: jest.fn(), + }, + }; + }); + + await page.goto("/"); + }); + + test("should show SignInForm when user is not authenticated", async () => { + await page.evaluate(() => { + window.mockAuthState = null; + }); + + await page.reload(); + + // Check if SignInForm is visible + const signInForm = await page + .locator("form") + .filter({ hasText: "Sign In" }); + await expect(signInForm).toBeVisible(); + }); + + test("should show routes when user is authenticated", async () => { + await page.evaluate((user) => { + window.mockAuthState = user; + }, mockUser); + + await page.reload(); + + // Check if AuthHome is visible + const authHome = await page.locator('div:text("AuthHome")'); + await expect(authHome).toBeVisible(); + + // Check that electron IPC was called with auth state + await expect( + page.evaluate(() => { + return window.electron.ipcRenderer.send.mock.calls.length > 0; + }), + ).resolves.toBe(true); + }); + + test("should navigate to settings page when authenticated", async () => { + await page.evaluate((user) => { + window.mockAuthState = user; + }, mockUser); + + await page.reload(); + + // Navigate to settings + await page.click('a[href="/settings"]'); + + // Check if Settings page is visible + const settingsPage = await page.locator('div:text("Settings")'); + await expect(settingsPage).toBeVisible(); + }); +}); diff --git a/src/renderer/src/App.tsx b/src/renderer/src/App.tsx new file mode 100644 index 0000000..f1a6fe2 --- /dev/null +++ b/src/renderer/src/App.tsx @@ -0,0 +1,88 @@ +import "@ant-design/v5-patch-for-react-19"; +import { Layout, Skeleton, ConfigProvider, Badge } from "antd"; +import { User } from "firebase/auth"; +import { useEffect, useState, FC } from "react"; +import { ErrorBoundary } from "react-error-boundary"; +import { Provider } from "react-redux"; +import { HashRouter, Route, Routes } from "react-router"; +import ipcTypes from "../../util/ipcTypes.json"; +import ErrorBoundaryFallback from "./components/ErrorBoundaryFallback/ErrorBoundaryFallback"; +import Settings from "./components/Settings/Settings"; +import SignInForm from "./components/SignInForm/SignInForm"; +import UpdateAvailable from "./components/UpdateAvailable/UpdateAvailable"; +import reduxStore from "./redux/redux-store"; +import { auth } from "./util/firebase"; +import { NotificationProvider } from "./util/notificationContext"; + +const App: FC = () => { + const [user, setUser] = useState(false); + useEffect(() => { + // Only set up the listener once when component mounts + if (auth.currentUser) { + setUser(auth.currentUser); + } else { + setUser(false); + } + const unsubscribe = auth.onAuthStateChanged((user: User | null) => { + setUser(user); + //Send back to the main process so that it knows we are authenticated. + if (user) { + window.electron.ipcRenderer.send( + ipcTypes.toMain.authStateChanged, + user.toJSON(), + ); + window.electron.ipcRenderer.send(ipcTypes.toMain.watcher.start); + } + }); + + // Clean up the listener when component unmounts + return (): void => unsubscribe(); + }, []); + + const isTest = window.api.isTest(); + + return ( + + + + + + + + {!user ? ( + + ) : ( + + + + + } /> + + + + )} + + + + + + + + ); +}; + +export default App; diff --git a/src/renderer/src/components/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx b/src/renderer/src/components/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx new file mode 100644 index 0000000..010e452 --- /dev/null +++ b/src/renderer/src/components/ErrorBoundaryFallback/ErrorBoundaryFallback.tsx @@ -0,0 +1,25 @@ +import { FC } from "react"; +import { Button, Result } from "antd"; +import { FallbackProps } from "react-error-boundary"; +import { useTranslation } from "react-i18next"; + +const ErrorBoundaryFallback: FC = ({ + error, + resetErrorBoundary, +}) => { + const { t } = useTranslation(); + return ( + + Try again + , + ]} + /> + ); +}; + +export default ErrorBoundaryFallback; diff --git a/src/renderer/src/components/Home/Home.tsx b/src/renderer/src/components/Home/Home.tsx new file mode 100644 index 0000000..cb159a2 --- /dev/null +++ b/src/renderer/src/components/Home/Home.tsx @@ -0,0 +1,11 @@ +import { FC } from "react"; + +const Home: FC = () => { + return ( +
+

Home

+
+ ); +}; + +export default Home; diff --git a/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts b/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts new file mode 100644 index 0000000..1289514 --- /dev/null +++ b/src/renderer/src/components/Settings/PaintScale/usePaintScaleConfig.ts @@ -0,0 +1,164 @@ +import { useState, useEffect } from "react"; +import ipcTypes from "../../../../../util/ipcTypes.json"; +import { + PaintScaleConfig, + PaintScaleType, +} from "../../../../../util/types/paintScale"; +import { message } from "antd"; +import { useTranslation } from "react-i18next"; + +type ConfigType = "input" | "output"; + +export const usePaintScaleConfig = (configType: ConfigType) => { + const [paintScaleConfigs, setPaintScaleConfigs] = useState< + PaintScaleConfig[] + >([]); + const { t } = useTranslation(); + + // Get the appropriate IPC methods based on config type + const getConfigsMethod = + configType === "input" + ? ipcTypes.toMain.settings.paintScale.getInputConfigs + : ipcTypes.toMain.settings.paintScale.getOutputConfigs; + + const setConfigsMethod = + configType === "input" + ? ipcTypes.toMain.settings.paintScale.setInputConfigs + : ipcTypes.toMain.settings.paintScale.setOutputConfigs; + + const setPathMethod = + configType === "input" + ? ipcTypes.toMain.settings.paintScale.setInputPath + : ipcTypes.toMain.settings.paintScale.setOutputPath; + + // Load paint scale configs on mount + useEffect(() => { + window.electron.ipcRenderer + .invoke(getConfigsMethod) + .then((configs: PaintScaleConfig[]) => { + // Ensure all configs have a pollingInterval and type (for backward compatibility) + const defaultPolling = configType === "input" ? 1440 : 60; + const updatedConfigs = configs.map((config) => ({ + ...config, + pollingInterval: config.pollingInterval || defaultPolling, // Default to 1440 for input, 60 for output + type: config.type || PaintScaleType.PPG, // Default type if missing + })); + setPaintScaleConfigs(updatedConfigs || []); + }) + .catch((error) => { + console.error( + `Failed to load paint scale ${configType} configs:`, + error, + ); + }); + }, [getConfigsMethod]); + + // Save configs to store and notify main process of config changes + const saveConfigs = (configs: PaintScaleConfig[]) => { + window.electron.ipcRenderer + .invoke(setConfigsMethod, configs) + .then(() => { + // Notify main process to update cron job + if (configType === "input") { + window.electron.ipcRenderer.send( + ipcTypes.toMain.settings.paintScale.updateInputCron, + configs, + ); + } else if (configType === "output") { + window.electron.ipcRenderer.send( + ipcTypes.toMain.settings.paintScale.updateOutputCron, + configs, + ); + } + }) + .catch((error) => { + console.error( + `Failed to save paint scale ${configType} configs:`, + error, + ); + }); + }; + + // New helper to check if a path is unique across input and output configs + const checkPathUnique = async (newPath: string): Promise => { + try { + const inputConfigs: PaintScaleConfig[] = + await window.electron.ipcRenderer.invoke( + ipcTypes.toMain.settings.paintScale.getInputConfigs, + ); + const outputConfigs: PaintScaleConfig[] = + await window.electron.ipcRenderer.invoke( + ipcTypes.toMain.settings.paintScale.getOutputConfigs, + ); + const allConfigs = [...inputConfigs, ...outputConfigs]; + // Allow updating the current config even if its current value equals newPath. + return !allConfigs.some((config) => config.path === newPath); + } catch (error) { + console.error("Failed to check unique path:", error); + return false; + } + }; + + // Handle adding a new paint scale config + const handleAddConfig = (type: PaintScaleType) => { + const defaultPolling = configType === "input" ? 1440 : 60; + const newConfig: PaintScaleConfig = { + id: Date.now().toString(), + type, + pollingInterval: defaultPolling, // Default to 1440 for input, 60 for output + }; + const updatedConfigs = [...paintScaleConfigs, newConfig]; + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + // Handle removing a config + const handleRemoveConfig = (id: string) => { + const updatedConfigs = paintScaleConfigs.filter( + (config) => config.id !== id, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + // Handle path selection (modified to check directory uniqueness) + const handlePathChange = async (id: string) => { + try { + const path: string | null = await window.electron.ipcRenderer.invoke( + setPathMethod, + id, + ); + if (path) { + const isUnique = await checkPathUnique(path); + if (!isUnique) { + message.error(t("settings.errors.duplicatePath")); + return; + } + const updatedConfigs = paintScaleConfigs.map((config) => + config.id === id ? { ...config, path } : config, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + } + } catch (error) { + console.error(`Failed to set paint scale ${configType} path:`, error); + } + }; + + // Handle polling interval change + const handlePollingIntervalChange = (id: string, pollingInterval: number) => { + const updatedConfigs = paintScaleConfigs.map((config) => + config.id === id ? { ...config, pollingInterval } : config, + ); + setPaintScaleConfigs(updatedConfigs); + saveConfigs(updatedConfigs); + }; + + return { + paintScaleConfigs, + handleAddConfig, + handleRemoveConfig, + handlePathChange, + handlePollingIntervalChange, + }; +}; diff --git a/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx b/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx new file mode 100644 index 0000000..a84e0a5 --- /dev/null +++ b/src/renderer/src/components/Settings/Settings.EmsOutFilePath.tsx @@ -0,0 +1,46 @@ +import { FolderOpenFilled } from "@ant-design/icons"; +import { Button, Card, Input, Space } from "antd"; +import { useEffect, useState, FC } from "react"; +import { useTranslation } from "react-i18next"; +import ipcTypes from "../../../../util/ipcTypes.json"; + +const SettingsEmsOutFilePath: FC = () => { + const { t } = useTranslation(); + + const [emsFilePath, setEmsFilePath] = useState(null); + + const getPollingStateFromStore = (): void => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.settings.getEmsOutFilePath) + .then((filePath: string | null) => { + setEmsFilePath(filePath); + }); + }; + + //Get state first time it renders. + useEffect(() => { + getPollingStateFromStore(); + }, []); + + const handlePathChange = (): void => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.settings.setEmsOutFilePath) + .then((filePath: string | null) => { + setEmsFilePath(filePath); + }); + }; + + return ( + + + + + ), + }, + ]; + + return ( + <> + }> + {t("settings.actions.addpath")} + + } + > + + + + + + ) : ( + + ) + } + /> + + ), + }, + ]; + + return ( + <> + }> + {t("settings.actions.addpath")} + + } + > +
+ + + + + + } + > + ({ + key: index, + children: ( + + {path} + + {isWatcherStarted ? ( + + ) : ( + + )} + + + + + {pollingState.enabled && ( + + {t("settings.labels.pollinginterval")} + + + )} + {watcherError && } + + + + + + ); +}; +export default SettingsWatcher; diff --git a/src/renderer/src/components/Settings/Settings.tsx b/src/renderer/src/components/Settings/Settings.tsx new file mode 100644 index 0000000..5cdb13b --- /dev/null +++ b/src/renderer/src/components/Settings/Settings.tsx @@ -0,0 +1,45 @@ +// renderer/Settings.tsx +import { Col, Row } from "antd"; +import { FC } from "react"; +import SettingsWatchedPaths from "./Settings.WatchedPaths"; +import SettingsWatcher from "./Settings.Watcher"; +import Welcome from "../Welcome/Welcome"; +import SettingsPpcFilepath from "./Settings.PpcFilePath"; +import SettingsEmsOutFilePath from "./Settings.EmsOutFilePath"; +import SettingsPaintScaleInputPaths from "./Settings.PaintScaleInputPaths"; +import SettingsPaintScaleOutputPaths from "./Settings.PaintScaleOutputPaths"; + +const colSpans = { + md: 12, // Two columns on medium screens and above + sm: 24, // One column on small screens +}; + +const Settings: FC = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default Settings; \ No newline at end of file diff --git a/src/renderer/src/components/SignInForm/SignInForm.tsx b/src/renderer/src/components/SignInForm/SignInForm.tsx new file mode 100644 index 0000000..360cc23 --- /dev/null +++ b/src/renderer/src/components/SignInForm/SignInForm.tsx @@ -0,0 +1,142 @@ +import { auth } from "@renderer/util/firebase"; +import type { FormProps } from "antd"; +import { Alert, Button, Card, Form, Input, Typography } from "antd"; +import log from "electron-log/renderer"; +import { signInWithEmailAndPassword } from "firebase/auth"; +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import errorTypeCheck from "../../../../util/errorTypeCheck"; +import ipcTypes from "../../../../util/ipcTypes.json"; + +const { Title } = Typography; + +type FieldType = { + username: string; + password: string; + remember?: string; +}; + +const SignInForm: React.FC = () => { + const [error, setError] = useState(null); + const [loading, setLoading] = useState(false); + const { t } = useTranslation(); + const onFinish: FormProps["onFinish"] = async (values) => { + const { username, password } = values; + setLoading(true); + try { + const result = await signInWithEmailAndPassword(auth, username, password); + log.debug("Login result", result); + } catch (error) { + log.error("Login error", errorTypeCheck(error)); + setError(t("auth.login.error")); + } finally { + setLoading(false); + } + }; + + const onFinishFailed: FormProps["onFinishFailed"] = ( + errorInfo, + ) => { + log.log("Failed:", errorInfo); + }; + + return ( + +
+ + {import.meta.env.VITE_COMPANY === "IMEX" + ? t("title.imex") + : t("title.rome")} + +
+ +
+ {error && ( + + + + )} + + + label="Username" + name="username" + rules={[ + { + required: true, + message: t( + "auth.login.usernameRequired", + "Please enter your username", + ), + }, + ]} + > + + + + + label="Password" + name="password" + rules={[ + { + required: true, + message: t( + "auth.login.passwordRequired", + "Please enter your password", + ), + }, + ]} + > + + + + + + + + + + + +
+ ); +}; + +export default SignInForm; diff --git a/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx new file mode 100644 index 0000000..a43c61b --- /dev/null +++ b/src/renderer/src/components/UpdateAvailable/UpdateAvailable.tsx @@ -0,0 +1,95 @@ +import { + selectAppUpdateCompleted, + selectAppUpdateProgress, + selectAppUpdateSpeed, + selectUpdateAvailable, +} from "@renderer/redux/app.slice"; +import { useAppSelector } from "@renderer/redux/reduxHooks"; +import { Affix, Button, Card, Progress, Space, Statistic } from "antd"; +import { useTranslation } from "react-i18next"; +import ipcTypes from "../../../../util/ipcTypes.json"; +import { useState, FC } from "react"; + +const UpdateAvailable: FC = () => { + const { t } = useTranslation(); + + const isUpdateAvailable = useAppSelector(selectUpdateAvailable); + const updateSpeed = useAppSelector(selectAppUpdateSpeed); + const updateProgress = useAppSelector(selectAppUpdateProgress); + const isUpdateComplete = useAppSelector(selectAppUpdateCompleted); + const [applyingUpdate, setApplyingUpdate] = useState(false); + + const handleDownload = (): void => { + window.electron.ipcRenderer.send(ipcTypes.toMain.updates.download); + }; + + const handleApply = (): void => { + setApplyingUpdate(true); + window.electron.ipcRenderer.send(ipcTypes.toMain.updates.apply); + }; + + if (!isUpdateAvailable) { + return null; + } + return ( + + + + {updateProgress === 0 && ( + + )} + + {!isUpdateComplete && formatSpeed(updateSpeed)} + {isUpdateComplete && ( + <> + + handleApply()} + /> + + )} + + + + ); +}; + +export default UpdateAvailable; + +/** + * Formats bytes into a human-readable string with appropriate units + * @param bytes Number of bytes + * @returns Formatted string with appropriate unit (B/KB/MB/GB) + */ +const formatSpeed = (bytes: number): string => { + if (bytes === 0) return "0 B/s"; + + const units = ["B/s", "KB/s", "MB/s", "GB/s"]; + const i = Math.floor(Math.log(bytes) / Math.log(1024)); + + // Limit to available units and format with 2 decimal places (rounded) + return `${(bytes / Math.pow(1024, i)).toFixed(2)} ${units[i] || units[units.length - 1]}`; +}; diff --git a/src/renderer/src/components/Versions.tsx b/src/renderer/src/components/Versions.tsx new file mode 100644 index 0000000..ddd7349 --- /dev/null +++ b/src/renderer/src/components/Versions.tsx @@ -0,0 +1,15 @@ +import { JSX, useState } from "react"; + +function Versions(): JSX.Element { + const [versions] = useState(window.electron.process.versions); + + return ( +
    +
  • Electron v{versions.electron}
  • +
  • Chromium v{versions.chrome}
  • +
  • Node v{versions.node}
  • +
+ ); +} + +export default Versions; diff --git a/src/renderer/src/components/Welcome/Welcome.tsx b/src/renderer/src/components/Welcome/Welcome.tsx new file mode 100644 index 0000000..d3d3c87 --- /dev/null +++ b/src/renderer/src/components/Welcome/Welcome.tsx @@ -0,0 +1,49 @@ +import { LogoutOutlined } from "@ant-design/icons"; +import { auth } from "@renderer/util/firebase"; +import { Button, Space, Typography } from "antd"; +import { isEmpty } from "lodash"; +import { JSX, useEffect, useState } from "react"; +import { useTranslation } from "react-i18next"; +import ipcTypes from "../../../../util/ipcTypes.json"; + +const Welcome = (): JSX.Element => { + const { t } = useTranslation(); + const [shopName, setShopName] = useState(null); + useEffect(() => { + window.electron.ipcRenderer + .invoke(ipcTypes.toMain.user.getActiveShop) + .then((shopName: string) => { + console.log("Active shop name:", shopName); + setShopName(shopName); + }); + }, []); + + return ( + <> + + {t("auth.labels.welcome", { + name: isEmpty(auth.currentUser?.displayName) + ? auth.currentUser?.email + : `${auth.currentUser?.displayName} (${auth.currentUser?.email})`.trim(), + })} + + + {shopName || ""} + + + + ); +}; + +export default Welcome; diff --git a/src/renderer/src/env.d.ts b/src/renderer/src/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/src/renderer/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/src/renderer/src/main.tsx b/src/renderer/src/main.tsx new file mode 100644 index 0000000..ef1b4a0 --- /dev/null +++ b/src/renderer/src/main.tsx @@ -0,0 +1,26 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import App from "./App"; +import "./util/i18n"; +import "./util/ipcRendererHandler"; +import * as Sentry from "@sentry/electron/renderer"; + +// Extend the Window interface to include the api property +declare global { + interface Window { + api: { + isTest: () => boolean; + }; + } +} + + +Sentry.init({ + dsn: "https://ba41d22656999a8c1fd63bcb7df98650@o492140.ingest.us.sentry.io/4509074139447296", +}); + +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( + + + , +); diff --git a/src/renderer/src/redux/app.slice.ts b/src/renderer/src/redux/app.slice.ts new file mode 100644 index 0000000..806c8e8 --- /dev/null +++ b/src/renderer/src/redux/app.slice.ts @@ -0,0 +1,136 @@ +import { createSlice, PayloadAction } from "@reduxjs/toolkit"; +import log from "electron-log/renderer"; +import type { RootState } from "./redux-store"; + +interface AppState { + value: number; + watcher: { + started: boolean; + error: string | null; + polling: { + enabled: boolean; + interval: number; + }; + }; + updates: { + available: boolean; + checking: boolean; + progress: number; + speed: number; + completed: boolean; + }; +} + +// Define the initial state using that type +const initialState: AppState = { + value: 0, + watcher: { + started: false, + error: null, + polling: { + enabled: false, + interval: 30000, + }, + }, + updates: { + available: false, + checking: false, + progress: 0, + speed: 0, + completed: false, + }, +}; + +export const appSlice = createSlice({ + name: "app", + // `createSlice` will infer the state type from the `initialState` argument + initialState, + reducers: { + watcherStarted: (state) => { + state.watcher.started = true; + }, + watcherStopped: (state) => { + state.watcher.started = false; + }, + watcherError: (state, action: PayloadAction) => { + state.watcher.error = action.payload; + state.watcher.started = false; + log.error("[Redux] AppSlice: Watcher Error", action.payload); + }, + + updateChecking: (state) => { + state.updates.checking = true; + }, + updateAvailable: (state) => { + state.updates.available = true; + state.updates.checking = false; + }, + updateProgress: ( + state, + action: PayloadAction<{ progress: number; speed: number }>, + ) => { + state.updates.available = true; + state.updates.progress = action.payload.progress; + state.updates.speed = action.payload.speed; + }, + updateDownloaded: (state) => { + state.updates.completed = true; + state.updates.progress = 100; + state.updates.speed = 0; + }, + setWatcherPolling: ( + state, + action: PayloadAction<{ enabled: boolean; interval: number }>, + ) => { + state.watcher.polling.enabled = action.payload.enabled; + state.watcher.polling.interval = action.payload.interval; + }, + }, +}); + +export const { + watcherError, + watcherStarted, + watcherStopped, + updateAvailable, + updateChecking, + updateDownloaded, + updateProgress, + setWatcherPolling, +} = appSlice.actions; + +// Other code such as selectors can use the imported `RootState` type +export const selectWatcherStatus = (state: RootState): boolean => + state.app.watcher.started; + +export const selectWatcherError = (state: RootState): string | null => + state.app.watcher.error; + +export const selectUpdateAvailable = (state: RootState): boolean => + state.app.updates.available; + +export const selectAppUpdateProgress = (state: RootState): number => + state.app.updates.progress; + +export const selectAppUpdateSpeed = (state: RootState): number => + state.app.updates.speed; + +export const selectAppUpdateCompleted = (state: RootState): boolean => + state.app.updates.completed; + +export const selectWatcherPolling = ( + state: RootState, +): { + enabled: boolean; + interval: number; +} => state.app.watcher.polling; + +//Async Functions - Thunks +// Define a thunk that dispatches those action creators +// const fetchUsers = () => async (dispatch) => { +// //dispatch(watcherStarted()); +// //Some sort of async action. +// // dispatch(incrementByAmount(100)); +// }; + +export default appSlice.reducer; diff --git a/src/renderer/src/redux/redux-store.ts b/src/renderer/src/redux/redux-store.ts new file mode 100644 index 0000000..a798de3 --- /dev/null +++ b/src/renderer/src/redux/redux-store.ts @@ -0,0 +1,16 @@ +import { configureStore } from "@reduxjs/toolkit"; +import logger from "redux-logger"; +import appReducer from "./app.slice"; + +const store = configureStore({ + reducer: { app: appReducer }, + middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger), +}); + +// Infer the `RootState` and `AppDispatch` types from the store itself +export type RootState = ReturnType; + +// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState} +export type AppDispatch = typeof store.dispatch; +export type AppStore = typeof store; +export default store; diff --git a/src/renderer/src/redux/reduxHooks.ts b/src/renderer/src/redux/reduxHooks.ts new file mode 100644 index 0000000..6834500 --- /dev/null +++ b/src/renderer/src/redux/reduxHooks.ts @@ -0,0 +1,10 @@ +import type { TypedUseSelectorHook } from "react-redux"; +import { useDispatch, useSelector, useStore } from "react-redux"; +import type { AppDispatch, AppStore, RootState } from "./redux-store"; +import store from "./redux-store"; + +//Use these custom hooks to access the Redux store from your component with type safety. +export type AppDispatch = typeof store.dispatch; +export const useAppDispatch = useDispatch.withTypes(); // Ex +export const useAppSelector: TypedUseSelectorHook = useSelector; +export const useAppStore: () => AppStore = useStore; diff --git a/src/renderer/src/util/countdownHook.ts b/src/renderer/src/util/countdownHook.ts new file mode 100644 index 0000000..61b2d28 --- /dev/null +++ b/src/renderer/src/util/countdownHook.ts @@ -0,0 +1,124 @@ +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; + +type Timer = { + started: number | null; + lastInterval: number | null; + timeLeft: number; + timeToCount: number; + requestId: number; +}; + +const useCountDown = ( + timeToCount = 60 * 1000, + interval = 1000, +): [ + number, + { + start: (ttc?: number) => void; + pause: () => void; + resume: () => void; + reset: () => void; + }, +] => { + const [timeLeft, setTimeLeft] = useState(0); + const timer = useRef({ + started: null, + lastInterval: null, + timeLeft: 0, + timeToCount: 0, + requestId: 0, + }); + + const run = (ts: number) => { + if (!timer.current.started) { + timer.current.started = ts; + timer.current.lastInterval = ts; + } + + const localInterval = Math.min( + interval, + timer.current.timeLeft || Infinity, + ); + if (timer.current.lastInterval && ts - timer.current.lastInterval >= localInterval) { + timer.current.lastInterval += localInterval; + setTimeLeft((timeLeft) => { + timer.current.timeLeft = timeLeft - localInterval; + return timer.current.timeLeft; + }); + } + + if (ts - timer.current.started < timer.current.timeToCount) { + timer.current.requestId = window.requestAnimationFrame(run); + } else { + timer.current = { + started: null, + lastInterval: null, + timeLeft: 0, + timeToCount: 0, + requestId: 0, + }; + setTimeLeft(0); + } + }; + + const start = useCallback( + (ttc) => { + window.cancelAnimationFrame(timer.current.requestId); + + const newTimeToCount = ttc !== undefined ? ttc : timeToCount; + timer.current.started = null; + timer.current.lastInterval = null; + timer.current.timeToCount = newTimeToCount; + timer.current.requestId = window.requestAnimationFrame(run); + + setTimeLeft(newTimeToCount); + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + + const pause = useCallback(() => { + window.cancelAnimationFrame(timer.current.requestId); + timer.current.started = null; + timer.current.lastInterval = null; + timer.current.timeToCount = timer.current.timeLeft; + }, []); + + const resume = useCallback( + () => { + if (!timer.current.started && timer.current.timeLeft > 0) { + window.cancelAnimationFrame(timer.current.requestId); + timer.current.requestId = window.requestAnimationFrame(run); + } + }, + // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + + const reset = useCallback(() => { + if (timer.current.timeLeft) { + window.cancelAnimationFrame(timer.current.requestId); + timer.current = { + started: null, + lastInterval: null, + timeLeft: 0, + timeToCount: 0, + requestId: 0, + }; + setTimeLeft(0); + } + }, []); + + const actions = useMemo( + () => ({ start, pause, resume, reset }), // eslint-disable-next-line react-hooks/exhaustive-deps + [], + ); + + useEffect(() => { + return () => window.cancelAnimationFrame(timer.current.requestId); + }, []); + + return [timeLeft, actions]; +}; + +export default useCountDown; diff --git a/src/renderer/src/util/firebase.ts b/src/renderer/src/util/firebase.ts new file mode 100644 index 0000000..6d85c3b --- /dev/null +++ b/src/renderer/src/util/firebase.ts @@ -0,0 +1,14 @@ +import { initializeApp } from "firebase/app"; +import { getAuth } from "firebase/auth"; + +// TODO: Replace the following with your app's Firebase project configuration +const firebaseConfig = JSON.parse( + window.api.isTest() + ? import.meta.env.VITE_FIREBASE_CONFIG_TEST + : import.meta.env.VITE_FIREBASE_CONFIG, +); + +const app = initializeApp(firebaseConfig); +export const auth = getAuth(); + +export default app; diff --git a/src/renderer/src/util/graphql.client.ts b/src/renderer/src/util/graphql.client.ts new file mode 100644 index 0000000..939baa0 --- /dev/null +++ b/src/renderer/src/util/graphql.client.ts @@ -0,0 +1,30 @@ +import { + ApolloClient, + ApolloLink, + // HttpLink, + InMemoryCache, +} from "@apollo/client"; + +// const httpLink: HttpLink = new HttpLink({ +// uri: import.meta.env.VITE_GRAPHQL_URL, +// }); + +const middlewares = []; + +const client: ApolloClient = new ApolloClient({ + link: ApolloLink.from(middlewares), + cache: new InMemoryCache(), + defaultOptions: { + watchQuery: { + fetchPolicy: "network-only", + }, + query: { + fetchPolicy: "network-only", + }, + mutate: { + errorPolicy: "none", + }, + }, +}); + +export default client; diff --git a/src/renderer/src/util/i18n.ts b/src/renderer/src/util/i18n.ts new file mode 100644 index 0000000..0df882e --- /dev/null +++ b/src/renderer/src/util/i18n.ts @@ -0,0 +1,24 @@ +import i18n from "i18next"; +import { initReactI18next } from "react-i18next"; +import enTranslations from "../../../util/translations/en-US/renderer.json"; + +const resources = { + en: enTranslations, +}; + +i18n + .use(initReactI18next) + .init({ + resources, + debug: import.meta.env.DEV, + lng: "en", + interpolation: { + escapeValue: false, + }, + }) + .catch((err) => { + console.error("i18n initialization error:", err); + throw err; + }); + +export default i18n; diff --git a/src/renderer/src/util/ipcRendererHandler.ts b/src/renderer/src/util/ipcRendererHandler.ts new file mode 100644 index 0000000..8182169 --- /dev/null +++ b/src/renderer/src/util/ipcRendererHandler.ts @@ -0,0 +1,97 @@ +//Set up all the IPC handlers. +import { + setWatcherPolling, + updateAvailable, + updateChecking, + updateDownloaded, + updateProgress, + watcherError, + watcherStarted, + watcherStopped, +} from "@renderer/redux/app.slice"; +import store from "@renderer/redux/redux-store"; +import ipcTypes from "../../../util/ipcTypes.json"; +import { auth } from "./firebase"; +import { notification } from "antd"; +import i18n from "./i18n"; + +const ipcRenderer = window.electron.ipcRenderer; +const dispatch = store.dispatch; + +ipcRenderer.on( + ipcTypes.toRenderer.test, + (_event: Electron.IpcRendererEvent, arg) => { + console.log("Received test message from main process"); + console.log(arg); + }, +); + +ipcRenderer.on(ipcTypes.toRenderer.user.getToken, async () => { + const token = await auth.currentUser?.getIdToken(); + ipcRenderer.send(ipcTypes.toMain.user.getTokenResponse, token); +}); + +ipcRenderer.on(ipcTypes.toRenderer.watcher.started, () => { + console.log("Watcher has started"); + dispatch(watcherStarted()); +}); + +ipcRenderer.on(ipcTypes.toRenderer.watcher.stopped, () => { + console.log("Watcher has stopped"); + dispatch(watcherStopped()); +}); + +ipcRenderer.on( + ipcTypes.toRenderer.watcher.error, + (_event: Electron.IpcRendererEvent, error: string) => { + console.log("Watcher has encountered an error"); + console.log(error); + dispatch(watcherError(error)); + }, +); + +//Update Handlers +ipcRenderer.on(ipcTypes.toRenderer.updates.checking, () => { + console.log("Checking for updates..."); + dispatch(updateChecking()); +}); + +ipcRenderer.on(ipcTypes.toRenderer.updates.available, () => { + dispatch(updateAvailable()); +}); + +ipcRenderer.on( + ipcTypes.toRenderer.updates.downloading, + (_event: Electron.IpcRendererEvent, arg) => { + console.log("*** ARg", arg); + dispatch( + updateProgress({ + progress: Math.round(arg.percent), + speed: arg.bytesPerSecond, + }), + ); + }, +); + +ipcRenderer.on(ipcTypes.toRenderer.updates.downloaded, () => { + dispatch(updateDownloaded()); +}); + +ipcRenderer.on( + ipcTypes.toRenderer.watcher.polling, + (_event: Electron.IpcRendererEvent, arg) => { + dispatch( + setWatcherPolling({ enabled: arg.enabled, interval: arg.interval }), + ); + }, +); + +ipcRenderer.on( + ipcTypes.toRenderer.general.showErrorMessage, + (_event: Electron.IpcRendererEvent, error) => { + notification.error({ + message: i18n.t("errors.notificationtitle"), + description: error, + }); + }, +); diff --git a/src/renderer/src/util/notificationContext.tsx b/src/renderer/src/util/notificationContext.tsx new file mode 100644 index 0000000..efec48a --- /dev/null +++ b/src/renderer/src/util/notificationContext.tsx @@ -0,0 +1,46 @@ +import {createContext, FC, ReactNode, useContext} from "react"; +import { notification } from "antd"; + +/** + * Create our NotificationContext to store the `api` object + * returned by notification.useNotification(). + */ +const NotificationContext = createContext(null); + +/** + * A custom hook to make usage easier in child components. + */ +// eslint-disable-next-line react-refresh/only-export-components, @typescript-eslint/explicit-function-return-type +export const useNotification = () => { + return useContext(NotificationContext); +}; + +/** + * The Provider itself: + * - Call notification.useNotification() to get [api, contextHolder]. + * - Render contextHolder somewhere high-level in your app (so the notifications mount properly). + * - Provide `api` via the NotificationContext. + */ +interface NotificationProviderProps { + children?: ReactNode | ReactNode[]; +} + +export const NotificationProvider: FC = ({ + // eslint-disable-next-line react/prop-types + children, //TODO: Unable to resolve this. Adding an eslint disable. +}) => { + const [api, contextHolder] = notification.useNotification({ + placement: "bottomRight", + bottom: 70, + showProgress: true, + }); + + return ( + // @ts-ignore + + {/* contextHolder must be rendered in the DOM so notifications can appear */} + {contextHolder} + {children} + + ); +}; diff --git a/src/util/deepLowercaseKeys.ts b/src/util/deepLowercaseKeys.ts new file mode 100644 index 0000000..052ee8c --- /dev/null +++ b/src/util/deepLowercaseKeys.ts @@ -0,0 +1,37 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +/** + * Deep renames all keys in an object to lowercase + * @param obj - The object to transform + * @returns A new object with all keys converted to lowercase + */ +function deepLowerCaseKeys(obj: any): T { + if (!obj || typeof obj !== "object") { + return obj; + } + + // Handle arrays + if (Array.isArray(obj)) { + return obj.map((item) => deepLowerCaseKeys(item)) as unknown as T; + } + + // Handle objects + return Object.keys(obj).reduce( + (result, key) => { + const value = obj[key]; + const lowercaseKey = key.toLowerCase(); + + result[lowercaseKey] = + typeof value === "object" && + value !== null && + Object.keys(value).length > 0 + ? deepLowerCaseKeys(value) + : value; + + return result; + }, + {} as Record, + ) as T; +} + +export default deepLowerCaseKeys; diff --git a/src/util/errorTypeCheck.ts b/src/util/errorTypeCheck.ts new file mode 100644 index 0000000..149b348 --- /dev/null +++ b/src/util/errorTypeCheck.ts @@ -0,0 +1,21 @@ +//Type checking here allows us to skip the boilerplate in every catch block. +function errorTypeCheck(passedError: Error | unknown): ParsedError { + const errorMessage = + passedError instanceof Error ? passedError.message : String(passedError); + const errorStack = + passedError instanceof Error + ? (passedError.stack ?? "") + : String(passedError); + + return { + message: errorMessage, + stack: errorStack, + }; +} + +export default errorTypeCheck; + +export interface ParsedError { + message: string; + stack: string; +} diff --git a/src/util/getMainWindow.ts b/src/util/getMainWindow.ts new file mode 100644 index 0000000..2046a39 --- /dev/null +++ b/src/util/getMainWindow.ts @@ -0,0 +1,5 @@ +import { BrowserWindow } from "electron"; + +export default function getMainWindow(): BrowserWindow | null { + return BrowserWindow.getAllWindows()[0] || null; +} diff --git a/src/util/ipcTypes.json b/src/util/ipcTypes.json new file mode 100644 index 0000000..a53cd32 --- /dev/null +++ b/src/util/ipcTypes.json @@ -0,0 +1,71 @@ +{ + "toMain": { + "test": "toMain_test", + "authStateChanged": "toMain_authStateChanged", + "debug": { + "decodeEstimate": "toMain_debug_decodeEstimate" + }, + "updates": { + "checkForUpdates": "toMain_updates_checkForUpdates", + "download": "toMain_updates_download", + "apply": "toMain_updates_apply" + }, + "watcher": { + "start": "toMain_watcher_start", + "stop": "toMain_watcher_stop" + }, + "settings": { + "filepaths": { + "get": "toMain_settings_filepaths_get", + "add": "toMain_settings_filepaths_add", + "remove": "toMain_settings_filepaths_remove" + }, + "getEmsOutFilePath": "toMain_settings_filepaths_getEmsOutFilePath", + "setEmsOutFilePath": "toMain_settings_filepaths_setEmsOutFilePath", + "getPpcFilePath": "toMain_settings_filepaths_getPpcFilePath", + "setPpcFilePath": "toMain_settings_filepaths_setPpcFilePath", + "watcher": { + "getpolling": "toMain_settings_watcher_getpolling", + "setpolling": "toMain_settings_watcher_setpolling" + }, + "paintScale": { + "getInputConfigs": "toMain_settings_paintScale_getInputConfigs", + "setInputConfigs": "toMain_settings_paintScale_setInputConfigs", + "setInputPath": "toMain_settings_paintScale_setInputPath", + "getOutputConfigs": "toMain_settings_paintScale_getOutputConfigs", + "setOutputConfigs": "toMain_settings_paintScale_setOutputConfigs", + "setOutputPath": "toMain_settings_paintScale_setOutputPath", + "updateInputCron": "toMain_settings_paintScale_updateInputCron", + "updateOutputCron": "toMain_settings_paintScale_updateOutputCron" + } + }, + "user": { + "getTokenResponse": "toMain_user_getTokenResponse", + "getActiveShop": "toMain_user_getActiveShopify", + "resetPassword": "toMain_user_resetPassword" + } + }, + "toRenderer": { + "test": "toRenderer_test", + "watcher": { + "started": "toRenderer_watcher_started", + "stopped": "toRenderer_watcher_stopped", + "error": "toRenderer_watcher_error", + "polling": "toRenderer_watcher_polling" + }, + "updates": { + "checking": "toRenderer_updates_checking", + "available": "toRenderer_updates_available", + "notAvailable": "toRenderer_updates_notAvailable", + "error": "toRenderer_updates_error", + "downloading": "toRenderer_updates_downloading", + "downloaded": "toRenderer_updates_downloaded" + }, + "user": { + "getToken": "toRenderer_user_getToken" + }, + "general": { + "showErrorMessage": "toRenderer_general_showErrorMessage" + } + } +} \ No newline at end of file diff --git a/src/util/memUsage.ts b/src/util/memUsage.ts new file mode 100644 index 0000000..946a72a --- /dev/null +++ b/src/util/memUsage.ts @@ -0,0 +1,309 @@ +import { BrowserWindow } from "electron"; +import log from "electron-log/main"; +import fs from "fs"; +import os from "os"; +import path from "path"; +import Store from "../main/store/store"; +/** + * Human-readable memory/cpu/resource snapshot. + */ +export type MemoryUsageStats = { + timestamp: string; + label?: string; + uptimeSeconds: number; + pid: number; + memory: { + rss: number; + heapTotal: number; + heapUsed: number; + external: number; + arrayBuffers?: number; + }; + memoryPretty: { + rss: string; + heapTotal: string; + heapUsed: string; + external: string; + arrayBuffers?: string; + }; + os: { + totalMem: number; + freeMem: number; + freeMemPercent: number; + }; + cpuUsage?: NodeJS.CpuUsage; + resourceUsage?: NodeJS.ResourceUsage; + heapSpaces?: Array; + heapSnapshotFile?: string; + custom?: Record; +}; +// (merged into top import) + +/** + * Options for dumpMemoryStats. + */ +export type DumpOptions = { + /** + * Call global.gc() before sampling if available (requires node run with --expose-gc). + */ + runGc?: boolean; + /** + * Optional label to include in the returned snapshot. + */ + label?: string; + includeHeapSpaces?: boolean; + writeHeapSnapshot?: boolean; + heapSnapshotDir?: string; +}; + +/** + * Convert bytes to a compact human readable string. + */ +function formatBytes(bytes: number): string { + if (!isFinite(bytes)) return String(bytes); + const units = ["B", "KB", "MB", "GB", "TB"]; + let i = 0; + let val = bytes; + while (val >= 1024 && i < units.length - 1) { + val /= 1024; + i++; + } + return `${val.toFixed(2)} ${units[i]}`; +} + +/** + * Asynchronously produce a memory / cpu / os snapshot. + * + * Example: + * const stats = await dumpMemoryStats({ runGc: true, label: 'before-heavy-task' }); + */ +export async function dumpMemoryStats( + options: DumpOptions = {}, +): Promise { + const { + runGc = false, + label, + includeHeapSpaces = true, + writeHeapSnapshot = true, + heapSnapshotDir, + } = options; + + // Allow GC if requested and available to get a cleaner snapshot + if (runGc && typeof (global as any).gc === "function") { + try { + (global as any).gc(); + } catch { + // ignore GC errors + } + } + + // Let the event loop settle a tick so GC can complete if run + await new Promise((resolve) => setImmediate(resolve)); + + const mem = process.memoryUsage(); + const totalMem = os.totalmem(); + const freeMem = os.freemem(); + + const stats: MemoryUsageStats = { + timestamp: new Date().toISOString(), + label, + uptimeSeconds: Math.floor(process.uptime()), + pid: process.pid, + memory: { + rss: mem.rss, + heapTotal: mem.heapTotal, + heapUsed: mem.heapUsed, + external: mem.external, + arrayBuffers: mem.arrayBuffers, + }, + memoryPretty: { + rss: formatBytes(mem.rss), + heapTotal: formatBytes(mem.heapTotal), + heapUsed: formatBytes(mem.heapUsed), + external: formatBytes(mem.external), + arrayBuffers: + mem.arrayBuffers !== undefined + ? formatBytes(mem.arrayBuffers) + : undefined, + }, + os: { + totalMem, + freeMem, + freeMemPercent: Math.round((freeMem / totalMem) * 10000) / 100, + }, + cpuUsage: process.cpuUsage ? process.cpuUsage() : undefined, + resourceUsage: + typeof process.resourceUsage === "function" + ? process.resourceUsage() + : undefined, + custom: { + numBrowserWindows: BrowserWindow.getAllWindows().length, + }, + }; + + if (includeHeapSpaces) { + try { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const v8: typeof import("v8") = require("v8"); + if (typeof v8.getHeapSpaceStatistics === "function") { + stats.heapSpaces = v8.getHeapSpaceStatistics(); + } + } catch (err) { + log.warn("Failed to get heap space stats", err); + } + } + + if (writeHeapSnapshot) { + try { + if (!runGc && typeof (global as any).gc === "function") { + try { + (global as any).gc(); + } catch { + /* ignore */ + } + } + // eslint-disable-next-line @typescript-eslint/no-var-requires + const v8: typeof import("v8") = require("v8"); + if (typeof v8.writeHeapSnapshot === "function") { + const baseDir = + heapSnapshotDir || path.dirname(log.transports.file.getFile().path); + + const dir = path.join(baseDir, "heap-snapshots"); + fs.mkdirSync(dir, { recursive: true }); + const fileName = `heap-${Date.now()}-${process.pid}.heapsnapshot`; + const filePath = path.join(dir, fileName); + const snapshotPath = v8.writeHeapSnapshot(filePath); + stats.heapSnapshotFile = snapshotPath; + } else { + log.warn("v8.writeHeapSnapshot not available"); + } + } catch (err) { + log.warn("Failed to write heap snapshot", err); + } + } + + return stats; +} + +const memLogger = log.create({ logId: "mem-stat" }); +memLogger.transports.file.resolvePathFn = () => { + const filePath = path.join( + path.dirname(log.transports.file.getFile().path), + "memory-stats.log", + ); + return filePath; +}; +// Configure memory logger format to include process ID +memLogger.transports.file.format = + "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] [PID:{processId}] {text}"; +memLogger.transports.console.format = + "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}] [PID:{processId}] {text}"; + +export async function dumpMemoryStatsToFile() { + try { + const stats = await dumpMemoryStats({ includeHeapSpaces: false }); + memLogger.debug("[MemStat]:", stats); + } catch (error) { + log.warn("Unexpected error while writing memory stats log", error); + } +} + +function ongoingMemoryDump() { + console.log( + `Memory logging set to ${Store.get("settings.enableMemDebug")}. Log file at ${memLogger.transports.file.getFile().path}`, + ); + + setInterval( + async () => { + // Also write each snapshot to a dedicated memory stats log file as JSON lines. + try { + const loggingEnabled = Store.get("settings.enableMemDebug"); + log.debug( + "Checking if memory stats logging is enabled.", + loggingEnabled, + ); + if (loggingEnabled) { + // Enforce heap snapshot folder size limit (< 1GB) before writing a new snapshot. + const MAX_DIR_BYTES = 5 * 1024 * 1024 * 1024; // 5GB + const TARGET_REDUCED_BYTES = Math.floor(MAX_DIR_BYTES * 0.9); // prune down to 90% + const baseDir = path.dirname(log.transports.file.getFile().path); + const heapDir = path.join(baseDir, "heap-snapshots"); + try { + fs.mkdirSync(heapDir, { recursive: true }); + const files = fs + .readdirSync(heapDir) + .filter((f) => f.endsWith(".heapsnapshot")); + let totalSize = 0; + const fileStats: Array<{ + file: string; + size: number; + mtimeMs: number; + }> = []; + for (const file of files) { + try { + const stat = fs.statSync(path.join(heapDir, file)); + if (stat.isFile()) { + totalSize += stat.size; + fileStats.push({ + file, + size: stat.size, + mtimeMs: stat.mtimeMs, + }); + } + } catch (e) { + log.warn("Failed to stat heap snapshot file", file, e); + } + } + if (totalSize > MAX_DIR_BYTES) { + // Sort oldest first and delete until below TARGET_REDUCED_BYTES. + fileStats.sort((a, b) => a.mtimeMs - b.mtimeMs); + let bytesAfter = totalSize; + for (const info of fileStats) { + if (bytesAfter <= TARGET_REDUCED_BYTES) break; + try { + fs.unlinkSync(path.join(heapDir, info.file)); + bytesAfter -= info.size; + log.warn( + `Pruned heap snapshot '${info.file}' (${formatBytes(info.size)}) to reduce directory size. New size: ${formatBytes(bytesAfter)}.`, + ); + } catch (errDel) { + log.warn( + "Failed to delete heap snapshot file", + info.file, + errDel, + ); + } + } + if (bytesAfter > MAX_DIR_BYTES) { + // Still above hard cap; skip writing a new snapshot this cycle. + log.warn( + `Heap snapshot directory still above hard cap (${formatBytes(bytesAfter)} > ${formatBytes(MAX_DIR_BYTES)}). Skipping new heap snapshot this cycle.`, + ); + const stats = await dumpMemoryStats({ + includeHeapSpaces: false, + writeHeapSnapshot: false, + }); + memLogger.debug("[MemStat]:", stats); + return; // skip remainder; we already logged stats without snapshot. + } + } + } catch (dirErr) { + log.warn( + "Unexpected error while enforcing heap snapshot directory size limit", + dirErr, + ); + // Continue; failure to enforce limit should not stop memory stats. + } + // Directory is within allowed bounds (or pruning succeeded); proceed normally. + const stats = await dumpMemoryStats({ includeHeapSpaces: false }); + memLogger.debug("[MemStat]:", stats); + } + } catch (err) { + log.warn("Unexpected error while writing memory stats log", err); + } + }, + 15 * 60 * 1000, + ); // every 15 minutes +} + +export default ongoingMemoryDump; diff --git a/src/util/translations/en-US/main.json b/src/util/translations/en-US/main.json new file mode 100644 index 0000000..8dba742 --- /dev/null +++ b/src/util/translations/en-US/main.json @@ -0,0 +1,5 @@ +{ + "toolbar": { + "help": "Help" + } +} diff --git a/src/util/translations/en-US/renderer.json b/src/util/translations/en-US/renderer.json new file mode 100644 index 0000000..94ef64b --- /dev/null +++ b/src/util/translations/en-US/renderer.json @@ -0,0 +1,66 @@ +{ + "translation": { + "auth": { + "labels": { + "welcome": "Hi {{name}}" + }, + "login": { + "error": "The username and password combination provided is not valid.", + "login": "Log In", + "resetpassword": "Reset Password" + } + }, + "errors": { + "errorboundary": "Uh oh - we've hit an error.", + "notificationtitle": "Error Encountered" + }, + "navigation": { + "home": "Home", + "settings": "Settings", + "signout": "Sign Out" + }, + "settings": { + "actions": { + "addpath": "Add path", + "startwatcher": "Start Watcher", + "stopwatcher": "Stop Watcher\n" + }, + "errors": { + "duplicatePath": "The selected directory is already used in another configuration." + }, + "labels": { + "actions": "Actions", + "addPaintScalePath": "Add Paint Scale Path", + "emsOutFilePath": "EMS Out File Path (Parts Order, etc.)", + "invalidPath": "Path not set or invalid", + "paintScalePath": "Paint Scale Path", + "paintScaleSettingsInput": "BSMS To Paint Scale", + "paintScaleSettingsOutput": "Paint Scale To BSMS", + "paintScaleType": "Paint Scale Type", + "pollingInterval": "Polling Interval (m)", + "pollinginterval": "Polling Interval (ms)", + "ppcfilepath": "Parts Price Change File Path", + "remove": "Remove", + "selectPaintScaleType": "Select Paint Scale Type", + "started": "Started", + "stopped": "Stopped", + "validPath": "Valid path", + "watchedpaths": "Watched Paths", + "watchermodepolling": "Polling", + "watchermoderealtime": "Real Time", + "watcherstatus": "Watcher Status" + } + }, + "title": { + "imex": "ImEX Online", + "rome": "Rome Online" + }, + "updates": { + "apply": "Apply Update", + "applying": "Applying update", + "available": "An update is available.", + "download": "Download Update", + "downloading": "An update is downloading." + } + } +} diff --git a/src/util/typeCaster.ts b/src/util/typeCaster.ts new file mode 100644 index 0000000..2af4ca2 --- /dev/null +++ b/src/util/typeCaster.ts @@ -0,0 +1,63 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +/** + * Casts specified properties of an object to the desired types by specifying keys and their corresponding desired type. + * + * @param obj The object whose properties need to be cast + * @param typeMappings An object where keys are property names from the source object + * and values are the type to cast to ('string', 'number', 'boolean', etc.) + * @returns A new object with the specified properties cast to their desired types + */ +function typeCaster( + obj: T, + typeMappings: Partial< + Record + >, +): T { + const result = { ...obj }; + + for (const key in typeMappings) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + const targetType = typeMappings[key]; + const value = obj[key]; + + switch (targetType) { + case "string": + (result as any)[key] = String(value); + break; + case "number": + (result as any)[key] = Number(value); + break; + case "boolean": + (result as any)[key] = Boolean(value); + break; + case "object": + if (value && typeof value !== "object") { + try { + (result as any)[key] = JSON.parse(String(value)); + } catch { + (result as any)[key] = {}; + } + } + break; + case "array": + if (Array.isArray(value)) { + (result as any)[key] = value; + } else if (value && typeof value === "string") { + try { + const parsed = JSON.parse(value); + (result as any)[key] = Array.isArray(parsed) ? parsed : [parsed]; + } catch { + (result as any)[key] = [value]; + } + } else { + (result as any)[key] = value ? [value] : []; + } + break; + } + } + } + + return result; +} + +export default typeCaster; diff --git a/src/util/types/paintScale.ts b/src/util/types/paintScale.ts new file mode 100644 index 0000000..a3fd053 --- /dev/null +++ b/src/util/types/paintScale.ts @@ -0,0 +1,17 @@ +export enum PaintScaleType { + PPG = "PPG", +} + +export interface PaintScaleConfig { + id: string; + path?: string; + type: PaintScaleType; + pollingInterval: number; +} + +export const paintScaleTypeOptions = Object.values(PaintScaleType).map( + (type) => ({ + value: type, + label: type, + }), +); diff --git a/src/util/ynBoolConverter.ts b/src/util/ynBoolConverter.ts new file mode 100644 index 0000000..2251f6d --- /dev/null +++ b/src/util/ynBoolConverter.ts @@ -0,0 +1,12 @@ +const YNBoolConverter = (original: T): T => { + Object.keys(original).forEach((key) => { + if (original[key] === "Y") { + original[key] = true; + } else if (original[key] === "N") { + original[key] = false; + } + }); + return original; +}; + +export default YNBoolConverter; diff --git a/tests-examples/demo-todo-app.spec.ts b/tests-examples/demo-todo-app.spec.ts new file mode 100644 index 0000000..379e072 --- /dev/null +++ b/tests-examples/demo-todo-app.spec.ts @@ -0,0 +1,489 @@ +import { test, expect, type Page } from "@playwright/test"; + +test.beforeEach(async ({ page }) => { + await page.goto("https://demo.playwright.dev/todomvc"); +}); + +const TODO_ITEMS = [ + "buy some cheese", + "feed the cat", + "book a doctors appointment", +] as const; + +test.describe("New Todo", () => { + test("should allow me to add todo items", async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + // Create 1st todo. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press("Enter"); + + // Make sure the list only has one todo item. + await expect(page.getByTestId("todo-title")).toHaveText([TODO_ITEMS[0]]); + + // Create 2nd todo. + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press("Enter"); + + // Make sure the list now has two todo items. + await expect(page.getByTestId("todo-title")).toHaveText([ + TODO_ITEMS[0], + TODO_ITEMS[1], + ]); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); + + test("should clear text input field when an item is added", async ({ + page, + }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + // Create one todo item. + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press("Enter"); + + // Check that input is empty. + await expect(newTodo).toBeEmpty(); + await checkNumberOfTodosInLocalStorage(page, 1); + }); + + test("should append new items to the bottom of the list", async ({ + page, + }) => { + // Create 3 items. + await createDefaultTodos(page); + + // create a todo count locator + const todoCount = page.getByTestId("todo-count"); + + // Check test using different methods. + await expect(page.getByText("3 items left")).toBeVisible(); + await expect(todoCount).toHaveText("3 items left"); + await expect(todoCount).toContainText("3"); + await expect(todoCount).toHaveText(/3/); + + // Check all items in one call. + await expect(page.getByTestId("todo-title")).toHaveText(TODO_ITEMS); + await checkNumberOfTodosInLocalStorage(page, 3); + }); +}); + +test.describe("Mark all as completed", () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test.afterEach(async ({ page }) => { + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test("should allow me to mark all items as completed", async ({ page }) => { + // Complete all todos. + await page.getByLabel("Mark all as complete").check(); + + // Ensure all todos have 'completed' class. + await expect(page.getByTestId("todo-item")).toHaveClass([ + "completed", + "completed", + "completed", + ]); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + }); + + test("should allow me to clear the complete state of all items", async ({ + page, + }) => { + const toggleAll = page.getByLabel("Mark all as complete"); + // Check and then immediately uncheck. + await toggleAll.check(); + await toggleAll.uncheck(); + + // Should be no completed classes. + await expect(page.getByTestId("todo-item")).toHaveClass(["", "", ""]); + }); + + test("complete all checkbox should update state when items are completed / cleared", async ({ + page, + }) => { + const toggleAll = page.getByLabel("Mark all as complete"); + await toggleAll.check(); + await expect(toggleAll).toBeChecked(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Uncheck first todo. + const firstTodo = page.getByTestId("todo-item").nth(0); + await firstTodo.getByRole("checkbox").uncheck(); + + // Reuse toggleAll locator and make sure its not checked. + await expect(toggleAll).not.toBeChecked(); + + await firstTodo.getByRole("checkbox").check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 3); + + // Assert the toggle all is checked again. + await expect(toggleAll).toBeChecked(); + }); +}); + +test.describe("Item", () => { + test("should allow me to mark items as complete", async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press("Enter"); + } + + // Check first item. + const firstTodo = page.getByTestId("todo-item").nth(0); + await firstTodo.getByRole("checkbox").check(); + await expect(firstTodo).toHaveClass("completed"); + + // Check second item. + const secondTodo = page.getByTestId("todo-item").nth(1); + await expect(secondTodo).not.toHaveClass("completed"); + await secondTodo.getByRole("checkbox").check(); + + // Assert completed class. + await expect(firstTodo).toHaveClass("completed"); + await expect(secondTodo).toHaveClass("completed"); + }); + + test("should allow me to un-mark items as complete", async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + // Create two items. + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press("Enter"); + } + + const firstTodo = page.getByTestId("todo-item").nth(0); + const secondTodo = page.getByTestId("todo-item").nth(1); + const firstTodoCheckbox = firstTodo.getByRole("checkbox"); + + await firstTodoCheckbox.check(); + await expect(firstTodo).toHaveClass("completed"); + await expect(secondTodo).not.toHaveClass("completed"); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await firstTodoCheckbox.uncheck(); + await expect(firstTodo).not.toHaveClass("completed"); + await expect(secondTodo).not.toHaveClass("completed"); + await checkNumberOfCompletedTodosInLocalStorage(page, 0); + }); + + test("should allow me to edit an item", async ({ page }) => { + await createDefaultTodos(page); + + const todoItems = page.getByTestId("todo-item"); + const secondTodo = todoItems.nth(1); + await secondTodo.dblclick(); + await expect(secondTodo.getByRole("textbox", { name: "Edit" })).toHaveValue( + TODO_ITEMS[1], + ); + await secondTodo + .getByRole("textbox", { name: "Edit" }) + .fill("buy some sausages"); + await secondTodo.getByRole("textbox", { name: "Edit" }).press("Enter"); + + // Explicitly assert the new text value. + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + "buy some sausages", + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, "buy some sausages"); + }); +}); + +test.describe("Editing", () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test("should hide other controls when editing", async ({ page }) => { + const todoItem = page.getByTestId("todo-item").nth(1); + await todoItem.dblclick(); + await expect(todoItem.getByRole("checkbox")).not.toBeVisible(); + await expect( + todoItem.locator("label", { + hasText: TODO_ITEMS[1], + }), + ).not.toBeVisible(); + await checkNumberOfTodosInLocalStorage(page, 3); + }); + + test("should save edits on blur", async ({ page }) => { + const todoItems = page.getByTestId("todo-item"); + await todoItems.nth(1).dblclick(); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .fill("buy some sausages"); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .dispatchEvent("blur"); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + "buy some sausages", + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, "buy some sausages"); + }); + + test("should trim entered text", async ({ page }) => { + const todoItems = page.getByTestId("todo-item"); + await todoItems.nth(1).dblclick(); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .fill(" buy some sausages "); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .press("Enter"); + + await expect(todoItems).toHaveText([ + TODO_ITEMS[0], + "buy some sausages", + TODO_ITEMS[2], + ]); + await checkTodosInLocalStorage(page, "buy some sausages"); + }); + + test("should remove the item if an empty text string was entered", async ({ + page, + }) => { + const todoItems = page.getByTestId("todo-item"); + await todoItems.nth(1).dblclick(); + await todoItems.nth(1).getByRole("textbox", { name: "Edit" }).fill(""); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .press("Enter"); + + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test("should cancel edits on escape", async ({ page }) => { + const todoItems = page.getByTestId("todo-item"); + await todoItems.nth(1).dblclick(); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .fill("buy some sausages"); + await todoItems + .nth(1) + .getByRole("textbox", { name: "Edit" }) + .press("Escape"); + await expect(todoItems).toHaveText(TODO_ITEMS); + }); +}); + +test.describe("Counter", () => { + test("should display the current number of todo items", async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + // create a todo count locator + const todoCount = page.getByTestId("todo-count"); + + await newTodo.fill(TODO_ITEMS[0]); + await newTodo.press("Enter"); + + await expect(todoCount).toContainText("1"); + + await newTodo.fill(TODO_ITEMS[1]); + await newTodo.press("Enter"); + await expect(todoCount).toContainText("2"); + + await checkNumberOfTodosInLocalStorage(page, 2); + }); +}); + +test.describe("Clear completed button", () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + }); + + test("should display the correct text", async ({ page }) => { + await page.locator(".todo-list li .toggle").first().check(); + await expect( + page.getByRole("button", { name: "Clear completed" }), + ).toBeVisible(); + }); + + test("should remove completed items when clicked", async ({ page }) => { + const todoItems = page.getByTestId("todo-item"); + await todoItems.nth(1).getByRole("checkbox").check(); + await page.getByRole("button", { name: "Clear completed" }).click(); + await expect(todoItems).toHaveCount(2); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test("should be hidden when there are no items that are completed", async ({ + page, + }) => { + await page.locator(".todo-list li .toggle").first().check(); + await page.getByRole("button", { name: "Clear completed" }).click(); + await expect( + page.getByRole("button", { name: "Clear completed" }), + ).toBeHidden(); + }); +}); + +test.describe("Persistence", () => { + test("should persist its data", async ({ page }) => { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + for (const item of TODO_ITEMS.slice(0, 2)) { + await newTodo.fill(item); + await newTodo.press("Enter"); + } + + const todoItems = page.getByTestId("todo-item"); + const firstTodoCheck = todoItems.nth(0).getByRole("checkbox"); + await firstTodoCheck.check(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(["completed", ""]); + + // Ensure there is 1 completed item. + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + // Now reload. + await page.reload(); + await expect(todoItems).toHaveText([TODO_ITEMS[0], TODO_ITEMS[1]]); + await expect(firstTodoCheck).toBeChecked(); + await expect(todoItems).toHaveClass(["completed", ""]); + }); +}); + +test.describe("Routing", () => { + test.beforeEach(async ({ page }) => { + await createDefaultTodos(page); + // make sure the app had a chance to save updated todos in storage + // before navigating to a new view, otherwise the items can get lost :( + // in some frameworks like Durandal + await checkTodosInLocalStorage(page, TODO_ITEMS[0]); + }); + + test("should allow me to display active items", async ({ page }) => { + const todoItem = page.getByTestId("todo-item"); + await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole("link", { name: "Active" }).click(); + await expect(todoItem).toHaveCount(2); + await expect(todoItem).toHaveText([TODO_ITEMS[0], TODO_ITEMS[2]]); + }); + + test("should respect the back button", async ({ page }) => { + const todoItem = page.getByTestId("todo-item"); + await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); + + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + + await test.step("Showing all items", async () => { + await page.getByRole("link", { name: "All" }).click(); + await expect(todoItem).toHaveCount(3); + }); + + await test.step("Showing active items", async () => { + await page.getByRole("link", { name: "Active" }).click(); + }); + + await test.step("Showing completed items", async () => { + await page.getByRole("link", { name: "Completed" }).click(); + }); + + await expect(todoItem).toHaveCount(1); + await page.goBack(); + await expect(todoItem).toHaveCount(2); + await page.goBack(); + await expect(todoItem).toHaveCount(3); + }); + + test("should allow me to display completed items", async ({ page }) => { + await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole("link", { name: "Completed" }).click(); + await expect(page.getByTestId("todo-item")).toHaveCount(1); + }); + + test("should allow me to display all items", async ({ page }) => { + await page.getByTestId("todo-item").nth(1).getByRole("checkbox").check(); + await checkNumberOfCompletedTodosInLocalStorage(page, 1); + await page.getByRole("link", { name: "Active" }).click(); + await page.getByRole("link", { name: "Completed" }).click(); + await page.getByRole("link", { name: "All" }).click(); + await expect(page.getByTestId("todo-item")).toHaveCount(3); + }); + + test("should highlight the currently applied filter", async ({ page }) => { + await expect(page.getByRole("link", { name: "All" })).toHaveClass( + "selected", + ); + + //create locators for active and completed links + const activeLink = page.getByRole("link", { name: "Active" }); + const completedLink = page.getByRole("link", { name: "Completed" }); + await activeLink.click(); + + // Page change - active items. + await expect(activeLink).toHaveClass("selected"); + await completedLink.click(); + + // Page change - completed items. + await expect(completedLink).toHaveClass("selected"); + }); +}); + +async function createDefaultTodos(page: Page) { + // create a new todo locator + const newTodo = page.getByPlaceholder("What needs to be done?"); + + for (const item of TODO_ITEMS) { + await newTodo.fill(item); + await newTodo.press("Enter"); + } +} + +async function checkNumberOfTodosInLocalStorage(page: Page, expected: number) { + return await page.waitForFunction((e) => { + return JSON.parse(localStorage["react-todos"]).length === e; + }, expected); +} + +async function checkNumberOfCompletedTodosInLocalStorage( + page: Page, + expected: number, +) { + return await page.waitForFunction((e) => { + return ( + JSON.parse(localStorage["react-todos"]).filter( + (todo: any) => todo.completed, + ).length === e + ); + }, expected); +} + +async function checkTodosInLocalStorage(page: Page, title: string) { + return await page.waitForFunction((t) => { + return JSON.parse(localStorage["react-todos"]) + .map((todo: any) => todo.title) + .includes(t); + }, title); +} diff --git a/tests/example.spec.ts b/tests/example.spec.ts new file mode 100644 index 0000000..b60fe7c --- /dev/null +++ b/tests/example.spec.ts @@ -0,0 +1,20 @@ +import { test, expect } from "@playwright/test"; + +test("has title", async ({ page }) => { + await page.goto("https://playwright.dev/"); + + // Expect a title "to contain" a substring. + await expect(page).toHaveTitle(/Playwright/); +}); + +test("get started link", async ({ page }) => { + await page.goto("https://playwright.dev/"); + + // Click the get started link. + await page.getByRole("link", { name: "Get started" }).click(); + + // Expects page to have a heading with the name of Installation. + await expect( + page.getByRole("heading", { name: "Installation" }), + ).toBeVisible(); +}); diff --git a/tests/heapPrune.test.ts b/tests/heapPrune.test.ts new file mode 100644 index 0000000..153b7f1 --- /dev/null +++ b/tests/heapPrune.test.ts @@ -0,0 +1,62 @@ +import { test, expect } from "@playwright/test"; +import fs from "fs"; +import path from "path"; + +// We import the module after setting up a temporary log path by monkey patching electron-log. +// Since the project primarily uses Playwright for tests, we leverage its expect assertion library. + +// NOTE: This is a lightweight test that simulates the pruning logic indirectly by invoking the exported ongoingMemoryDump +// function and creating artificial heap snapshot files exceeding the threshold. + +// Because ongoingMemoryDump sets an interval, we invoke its internal logic by importing the file and manually calling dumpMemoryStats. +// For simplicity and to avoid altering production code for testability, we replicate the size enforcement logic here and assert behavior. + +function createDummySnapshots(dir: string, count: number, sizeBytes: number) { + fs.mkdirSync(dir, { recursive: true }); + for (let i = 0; i < count; i++) { + const file = path.join(dir, `dummy-${i}.heapsnapshot`); + const fd = fs.openSync(file, "w"); + // Write sizeBytes of zeros + const buf = Buffer.alloc(1024 * 1024, 0); // 1MB chunk + let written = 0; + while (written < sizeBytes) { + fs.writeSync(fd, buf, 0, Math.min(buf.length, sizeBytes - written)); + written += Math.min(buf.length, sizeBytes - written); + } + fs.closeSync(fd); + // Stagger mtime for deterministic pruning ordering + const mtime = new Date(Date.now() - (count - i) * 1000); + fs.utimesSync(file, mtime, mtime); + } +} + +test("heap snapshot directory pruning reduces size below simulated hard cap", async () => { + const baseDir = fs.mkdtempSync(path.join(process.cwd(), "heap-test-")); + const heapDir = path.join(baseDir, "heap-snapshots"); + // Simulate oversize: 15 files of 5MB each = 75MB + createDummySnapshots(heapDir, 15, 5 * 1024 * 1024); + // Use smaller cap to keep test resource usage low. + const MAX_DIR_BYTES = 50 * 1024 * 1024; // 50MB simulated cap + const TARGET_REDUCED_BYTES = Math.floor(MAX_DIR_BYTES * 0.9); + const files = fs + .readdirSync(heapDir) + .filter((f) => f.endsWith(".heapsnapshot")); + let totalSize = 0; + const fileStats: Array<{ file: string; size: number; mtimeMs: number }> = []; + for (const file of files) { + const stat = fs.statSync(path.join(heapDir, file)); + totalSize += stat.size; + fileStats.push({ file, size: stat.size, mtimeMs: stat.mtimeMs }); + } + expect(totalSize).toBeGreaterThan(MAX_DIR_BYTES); + fileStats.sort((a, b) => a.mtimeMs - b.mtimeMs); + let bytesAfter = totalSize; + for (const info of fileStats) { + if (bytesAfter <= TARGET_REDUCED_BYTES) break; + fs.unlinkSync(path.join(heapDir, info.file)); + bytesAfter -= info.size; + } + expect(bytesAfter).toBeLessThanOrEqual(TARGET_REDUCED_BYTES); + // Cleanup + fs.rmSync(baseDir, { recursive: true, force: true }); +}); diff --git a/translations.babel b/translations.babel new file mode 100644 index 0000000..fd071eb --- /dev/null +++ b/translations.babel @@ -0,0 +1,656 @@ + + + + i18next + translations.babel + + + + + + main + + + toolbar + + + help + false + + + + + + en-US + false + + + + + + + + + + renderer + + + translation + + + auth + + + labels + + + welcome + false + + + + + + en-US + false + + + + + + + login + + + error + false + + + + + + en-US + false + + + + + login + false + + + + + + en-US + false + + + + + resetpassword + false + + + + + + en-US + false + + + + + + + + + errors + + + errorboundary + false + + + + + + en-US + false + + + + + notificationtitle + false + + + + + + en-US + false + + + + + + + navigation + + + home + false + + + + + + en-US + false + + + + + settings + false + + + + + + en-US + false + + + + + signout + false + + + + + + en-US + false + + + + + + + settings + + + actions + + + addpath + false + + + + + + en-US + false + + + + + startwatcher + false + + + + + + en-US + false + + + + + stopwatcher + false + + + + + + en-US + false + + + + + + + errors + + + duplicatePath + false + + + + + + en-US + false + + + + + + + labels + + + actions + false + + + + + + en-US + false + + + + + addPaintScalePath + false + + + + + + en-US + false + + + + + emsOutFilePath + false + + + + + + en-US + false + + + + + invalidPath + false + + + + + + en-US + false + + + + + paintScalePath + false + + + + + + en-US + false + + + + + paintScaleSettingsInput + false + + + + + + en-US + false + + + + + paintScaleSettingsOutput + false + + + + + + en-US + false + + + + + paintScaleType + false + + + + + + en-US + false + + + + + pollingInterval + false + + + + + + en-US + false + + + + + pollinginterval + false + + + + + + en-US + false + + + + + ppcfilepath + false + + + + + + en-US + true + + + + + remove + false + + + + + + en-US + false + + + + + selectPaintScaleType + false + + + + + + en-US + false + + + + + started + false + + + + + + en-US + false + + + + + stopped + false + + + + + + en-US + false + + + + + validPath + false + + + + + + en-US + false + + + + + watchedpaths + false + + + + + + en-US + false + + + + + watchermodepolling + false + + + + + + en-US + false + + + + + watchermoderealtime + false + + + + + + en-US + false + + + + + watcherstatus + false + + + + + + en-US + false + + + + + + + + + title + + + imex + false + + + + + + en-US + false + + + + + rome + false + + + + + + en-US + false + + + + + + + updates + + + apply + false + + + + + + en-US + false + + + + + applying + false + + + + + + en-US + false + + + + + available + false + + + + + + en-US + false + + + + + download + false + + + + + + en-US + false + + + + + downloading + false + + + + + + en-US + false + + + + + + + + + + + + + false + + + en-US + + src/util/translations/en-US + + + + + src/util/translations/en-US + + + + true + + '%1' + { this.props.t('%1') } + { t('%1') } + + + en-US + + tab + namespaced-json + + diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..155ebaa --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.node.json" }, + { "path": "./tsconfig.web.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..d7105fc --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,17 @@ +{ + "extends": "@electron-toolkit/tsconfig/tsconfig.node.json", + "include": [ + "electron.vite.config.*", + "src/main/**/*", + "src/preload/**/*", + "src/util/**/*", + "src/interfaces/**/*", + "tests/index.spec.ts", + "/resources/**/*" + ], + "compilerOptions": { + "resolveJsonModule": true, + "composite": true, + "types": ["electron-vite/node", "vite/client"] + } +} diff --git a/tsconfig.web.json b/tsconfig.web.json new file mode 100644 index 0000000..e46e2d2 --- /dev/null +++ b/tsconfig.web.json @@ -0,0 +1,20 @@ +{ + "extends": "@electron-toolkit/tsconfig/tsconfig.web.json", + "include": [ + "src/renderer/src/env.d.ts", + "src/renderer/src/**/*", + "src/renderer/src/**/*.tsx", + "src/preload/*.d.ts", + "src/util/**/*" + ], + "compilerOptions": { + "resolveJsonModule": true, + "composite": true, + "jsx": "react-jsx", + "baseUrl": ".", + "types": ["vite/client"], + "paths": { + "@renderer/*": ["src/renderer/src/*"] + } + } +}