diff --git a/package-lock.json b/package-lock.json index ab24aea..855ef95 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,17 +9,23 @@ "version": "0.1.0", "license": "MIT", "dependencies": { + "@tanstack/react-query": "^5.90.21", "@tanstack/react-router": "^1.161.1", + "@trpc/client": "^11.10.0", + "@trpc/react-query": "^11.10.0", + "@trpc/server": "^11.10.0", "better-sqlite3": "^12.6.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "drizzle-orm": "^0.45.1", "electron-squirrel-startup": "^1.0.1", + "electron-trpc": "^0.7.1", "framer-motion": "^12.34.2", "lucide-react": "^0.575.0", "react": "^19.2.4", "react-dom": "^19.2.4", - "tailwind-merge": "^3.5.0" + "tailwind-merge": "^3.5.0", + "zod": "^4.3.6" }, "devDependencies": { "@electron-forge/cli": "^7.11.1", @@ -3209,7 +3215,6 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -3222,7 +3227,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.0" @@ -3244,6 +3248,32 @@ "url": "https://github.com/sponsors/tannerlinsley" } }, + "node_modules/@tanstack/query-core": { + "version": "5.90.20", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.90.20.tgz", + "integrity": "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.90.21", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.90.21.tgz", + "integrity": "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.90.20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@tanstack/react-router": { "version": "1.161.1", "resolved": "https://registry.npmjs.org/@tanstack/react-router/-/react-router-1.161.1.tgz", @@ -3343,6 +3373,16 @@ "node": ">= 12" } }, + "node_modules/@tanstack/router-generator/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@tanstack/router-plugin": { "version": "1.161.1", "resolved": "https://registry.npmjs.org/@tanstack/router-plugin/-/router-plugin-1.161.1.tgz", @@ -3396,6 +3436,16 @@ } } }, + "node_modules/@tanstack/router-plugin/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, "node_modules/@tanstack/router-utils": { "version": "1.158.0", "resolved": "https://registry.npmjs.org/@tanstack/router-utils/-/router-utils-1.158.0.tgz", @@ -3472,6 +3522,47 @@ "node": ">= 10" } }, + "node_modules/@trpc/client": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/@trpc/client/-/client-11.10.0.tgz", + "integrity": "sha512-h0s2AwDtuhS8INRb4hlo4z3RKCkarWqlOy+3ffJgrlDxzzW6aLUN+9nDrcN4huPje1Em15tbCOqhIc6oaKYTRw==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "@trpc/server": "11.10.0", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/react-query": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/@trpc/react-query/-/react-query-11.10.0.tgz", + "integrity": "sha512-SKLpwEMU32mpDTCc3msMxb0fx113x4Jsiw0/t+ENY6AtyvhvDMRF1bpWtoNyY6zpX5wN4JCQMhHef8k0T1rJIw==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "@tanstack/react-query": "^5.80.3", + "@trpc/client": "11.10.0", + "@trpc/server": "11.10.0", + "react": ">=18.2.0", + "typescript": ">=5.7.2" + } + }, + "node_modules/@trpc/server": { + "version": "11.10.0", + "resolved": "https://registry.npmjs.org/@trpc/server/-/server-11.10.0.tgz", + "integrity": "sha512-zZjTrR6He61e5TiT7e/bQqab/jRcXBZM8Fg78Yoo8uh5pz60dzzbYuONNUCOkafv5ppXVMms4NHYfNZgzw50vg==", + "funding": [ + "https://trpc.io/sponsor" + ], + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.7.2" + } + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -3531,7 +3622,6 @@ "version": "6.0.3", "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, "license": "MIT", "dependencies": { "@types/http-cache-semantics": "*", @@ -3591,7 +3681,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", - "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { @@ -3612,7 +3701,6 @@ "version": "3.1.4", "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -3632,7 +3720,6 @@ "version": "25.3.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz", "integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==", - "devOptional": true, "license": "MIT", "dependencies": { "undici-types": "~7.18.0" @@ -3662,7 +3749,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, "license": "MIT", "dependencies": { "@types/node": "*" @@ -3686,7 +3772,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -4698,7 +4783,6 @@ "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.", - "dev": true, "license": "MIT", "optional": true }, @@ -4788,7 +4872,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" @@ -4879,7 +4962,6 @@ "version": "5.0.4", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.6.0" @@ -4889,7 +4971,6 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, "license": "MIT", "dependencies": { "clone-response": "^1.0.2", @@ -5234,7 +5315,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, "license": "MIT", "dependencies": { "mimic-response": "^1.0.0" @@ -5443,7 +5523,6 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -5517,7 +5596,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -5527,7 +5605,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -5545,7 +5623,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", @@ -5572,7 +5650,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, "license": "MIT", "optional": true }, @@ -6288,7 +6365,6 @@ "version": "40.6.0", "resolved": "https://registry.npmjs.org/electron/-/electron-40.6.0.tgz", "integrity": "sha512-ett8W+yOFGDuM0vhJMamYSkrbV3LoaffzJd9GfjI96zRAxyrNqUSKqBpf/WGbQCweDxX2pkUCUfrv4wwKpsFZA==", - "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { @@ -6736,6 +6812,20 @@ "dev": true, "license": "ISC" }, + "node_modules/electron-trpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/electron-trpc/-/electron-trpc-0.7.1.tgz", + "integrity": "sha512-aWjZ5pLeVhrX9A9d8O8YgR8N+q4IXXzc76CJT1PwtDijIw+y5I+c75IAAtZ4JayYLeR3ll95PNGl5RTBu2qePw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "@trpc/client": ">10.0.0", + "@trpc/server": ">10.0.0", + "electron": ">19.0.0" + } + }, "node_modules/electron-winstaller": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/electron-winstaller/-/electron-winstaller-5.4.0.tgz", @@ -6800,7 +6890,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.1.1", @@ -6822,7 +6911,6 @@ "version": "24.10.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.13.tgz", "integrity": "sha512-oH72nZRfDv9lADUBSo104Aq7gPHpQZc4BTx38r9xf9pg5LfP6EzSyH2n7qFmmxRQXh7YlUXODcYsg6PuTDSxGg==", - "dev": true, "license": "MIT", "dependencies": { "undici-types": "~7.16.0" @@ -6832,7 +6920,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", @@ -6847,7 +6934,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" @@ -6857,7 +6943,6 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -6867,14 +6952,12 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, "license": "MIT" }, "node_modules/electron/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==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" @@ -6925,7 +7008,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -7021,7 +7103,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7031,7 +7113,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -7108,7 +7190,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, "license": "MIT", "optional": true }, @@ -7178,7 +7259,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=10" @@ -7683,7 +7764,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -7782,7 +7862,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" @@ -8206,7 +8285,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -8301,7 +8379,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, "license": "BSD-3-Clause", "optional": true, "dependencies": { @@ -8352,7 +8429,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "define-properties": "^1.2.1", @@ -8390,7 +8467,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -8403,7 +8480,6 @@ "version": "11.8.6", "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, "license": "MIT", "dependencies": { "@sindresorhus/is": "^4.0.0", @@ -8429,7 +8505,6 @@ "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==", - "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -8466,7 +8541,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -8544,7 +8619,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, "license": "BSD-2-Clause" }, "node_modules/http-proxy-agent": { @@ -8566,7 +8640,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", @@ -9340,7 +9413,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, "license": "MIT" }, "node_modules/json-parse-even-better-errors": { @@ -9368,7 +9440,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, "license": "ISC", "optional": true }, @@ -9412,7 +9483,6 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, "license": "MIT", "dependencies": { "json-buffer": "3.0.1" @@ -9608,7 +9678,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -9678,7 +9747,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -9781,7 +9849,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=4" @@ -9944,7 +10011,6 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, "license": "MIT" }, "node_modules/mute-stream": { @@ -10135,7 +10201,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -10204,7 +10269,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -10410,7 +10475,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -10616,7 +10680,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, "license": "MIT" }, "node_modules/picocolors": { @@ -10939,7 +11002,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -11011,7 +11073,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -11390,7 +11451,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, "license": "MIT" }, "node_modules/resolve-from": { @@ -11417,7 +11477,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, "license": "MIT", "dependencies": { "lowercase-keys": "^2.0.0" @@ -11492,7 +11551,6 @@ "version": "2.15.4", "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, "license": "BSD-3-Clause", "optional": true, "dependencies": { @@ -11737,7 +11795,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, "license": "MIT", "optional": true }, @@ -11745,7 +11802,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -11762,7 +11818,6 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, "license": "(MIT OR CC0-1.0)", "optional": true, "engines": { @@ -12155,7 +12210,6 @@ "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==", - "dev": true, "license": "BSD-3-Clause", "optional": true }, @@ -12407,7 +12461,6 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, "license": "Apache-2.0", "dependencies": { "debug": "^4.1.0" @@ -13474,7 +13527,6 @@ "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", "bin": { "tsc": "bin/tsc", @@ -13507,7 +13559,6 @@ "version": "7.18.2", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", - "devOptional": true, "license": "MIT" }, "node_modules/unique-filename": { @@ -14097,7 +14148,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", @@ -14131,10 +14181,9 @@ } }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "dev": true, + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/package.json b/package.json index eb92c10..2b52a39 100644 --- a/package.json +++ b/package.json @@ -44,16 +44,22 @@ "vite": "^5.4.21" }, "dependencies": { + "@tanstack/react-query": "^5.90.21", "@tanstack/react-router": "^1.161.1", + "@trpc/client": "^11.10.0", + "@trpc/react-query": "^11.10.0", + "@trpc/server": "^11.10.0", "better-sqlite3": "^12.6.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "drizzle-orm": "^0.45.1", "electron-squirrel-startup": "^1.0.1", + "electron-trpc": "^0.7.1", "framer-motion": "^12.34.2", "lucide-react": "^0.575.0", "react": "^19.2.4", "react-dom": "^19.2.4", - "tailwind-merge": "^3.5.0" + "tailwind-merge": "^3.5.0", + "zod": "^4.3.6" } } diff --git a/prd.json b/prd.json index f6358db..d897c8b 100644 --- a/prd.json +++ b/prd.json @@ -49,8 +49,8 @@ "Typecheck passes" ], "priority": 3, - "passes": false, - "notes": "" + "passes": true, + "notes": "Completed: electron-trpc IPC bridge, appRouter with stub routers for all 7 domains (health, clients, projects, tasks, checkpoints, notes, ai), renderer TRPCProvider+QueryClientProvider, health.ping returns 'pong' displayed in HomePage, Zod validates all procedure inputs" }, { "id": "US-004", diff --git a/src/main/index.ts b/src/main/index.ts index 33a1da5..7ff171b 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -1,14 +1,16 @@ import { app, BrowserWindow } from 'electron'; import path from 'node:path'; import started from 'electron-squirrel-startup'; +import { createIPCHandler } from 'electron-trpc/main'; import { initDb } from './db'; +import { appRouter } from './router'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (started) { app.quit(); } -const createWindow = () => { +const createWindow = (): BrowserWindow => { // Create the browser window. const mainWindow = new BrowserWindow({ width: 1280, @@ -36,6 +38,8 @@ const createWindow = () => { if (process.env.NODE_ENV === 'development') { mainWindow.webContents.openDevTools(); } + + return mainWindow; }; // This method will be called when Electron has finished @@ -43,7 +47,8 @@ const createWindow = () => { // Some APIs can only be used after this event occurs. app.on('ready', () => { initDb(); - createWindow(); + const win = createWindow(); + createIPCHandler({ router: appRouter, windows: [win] }); }); // Quit when all windows are closed, except on macOS. There, it's common diff --git a/src/main/router/index.ts b/src/main/router/index.ts new file mode 100644 index 0000000..4df5f92 --- /dev/null +++ b/src/main/router/index.ts @@ -0,0 +1,163 @@ +import { initTRPC } from '@trpc/server'; +import { z } from 'zod'; + +const t = initTRPC.create(); + +const router = t.router; +const publicProcedure = t.procedure; + +// Health router — ping/pong verification +const healthRouter = router({ + ping: publicProcedure.query(() => 'pong' as const), +}); + +// Stub routers — full implementations come in later user stories +const clientsRouter = router({ + list: publicProcedure.query(() => []), + create: publicProcedure + .input(z.object({ name: z.string(), parentId: z.string().optional(), industry: z.string().optional() })) + .mutation(() => null), + update: publicProcedure + .input(z.object({ id: z.string(), name: z.string().optional(), industry: z.string().optional() })) + .mutation(() => null), + delete: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), + deleteWithCascade: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), +}); + +const projectsRouter = router({ + list: publicProcedure + .input(z.object({ clientId: z.string().optional(), includeArchived: z.boolean().optional() }).optional()) + .query(() => []), + listAll: publicProcedure.query(() => [] as Array<{ id: string; name: string }>), + get: publicProcedure + .input(z.object({ id: z.string() })) + .query(() => null), + create: publicProcedure + .input(z.object({ name: z.string(), clientId: z.string().optional() })) + .mutation(() => null), + update: publicProcedure + .input(z.object({ + id: z.string(), + name: z.string().optional(), + clientId: z.string().optional(), + status: z.enum(['active', 'archived']).optional(), + aiSummary: z.string().optional(), + })) + .mutation(() => null), + delete: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), +}); + +const tasksRouter = router({ + list: publicProcedure + .input(z.object({ + projectId: z.string().optional(), + status: z.enum(['todo', 'in_progress', 'done']).optional(), + search: z.string().optional(), + orderBy: z.enum(['dueDate', 'priority', 'createdAt']).optional(), + }).optional()) + .query(() => []), + create: publicProcedure + .input(z.object({ + title: z.string(), + description: z.string().optional(), + status: z.string().optional(), + priority: z.string().optional(), + assignee: z.string().optional(), + dueDate: z.number().optional(), + projectId: z.string().optional(), + })) + .mutation(() => null), + update: publicProcedure + .input(z.object({ + id: z.string(), + title: z.string().optional(), + description: z.string().optional(), + status: z.string().optional(), + priority: z.string().optional(), + assignee: z.string().optional(), + dueDate: z.number().optional(), + projectId: z.string().optional(), + })) + .mutation(() => null), + delete: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), +}); + +const checkpointsRouter = router({ + list: publicProcedure + .input(z.object({ projectId: z.string().optional() }).optional()) + .query(() => []), + create: publicProcedure + .input(z.object({ + projectId: z.string(), + title: z.string(), + date: z.number(), + isAiSuggested: z.number().optional(), + isApproved: z.number().optional(), + })) + .mutation(() => null), + update: publicProcedure + .input(z.object({ + id: z.string(), + title: z.string().optional(), + date: z.number().optional(), + isApproved: z.number().optional(), + })) + .mutation(() => null), + delete: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), +}); + +const notesRouter = router({ + list: publicProcedure + .input(z.object({ projectId: z.string().optional() }).optional()) + .query(() => []), + get: publicProcedure + .input(z.object({ id: z.string() })) + .query(() => null), + create: publicProcedure + .input(z.object({ title: z.string(), content: z.string(), projectId: z.string().optional() })) + .mutation(() => null), + update: publicProcedure + .input(z.object({ id: z.string(), title: z.string().optional(), content: z.string().optional() })) + .mutation(() => null), + delete: publicProcedure + .input(z.object({ id: z.string() })) + .mutation(() => null), +}); + +const aiRouter = router({ + chat: publicProcedure + .input(z.object({ + message: z.string(), + context: z.object({ + type: z.enum(['global', 'project']), + projectId: z.string().optional(), + }), + })) + .mutation(() => ({ response: '' })), + setToken: publicProcedure + .input(z.object({ token: z.string() })) + .mutation(() => null), + hasToken: publicProcedure.query(() => false), +}); + +export const appRouter = router({ + health: healthRouter, + clients: clientsRouter, + projects: projectsRouter, + tasks: tasksRouter, + checkpoints: checkpointsRouter, + notes: notesRouter, + ai: aiRouter, +}); + +export type AppRouter = typeof appRouter; diff --git a/src/preload/index.ts b/src/preload/index.ts index 5e9d369..1738f4d 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -1,2 +1,7 @@ // See the Electron documentation for details on how to use preload scripts: // https://www.electronjs.org/docs/latest/tutorial/process-model#preload-scripts +import { exposeElectronTRPC } from 'electron-trpc/main'; + +process.once('loaded', () => { + exposeElectronTRPC(); +}); diff --git a/src/renderer/index.tsx b/src/renderer/index.tsx index 8fa0e6b..48122b2 100644 --- a/src/renderer/index.tsx +++ b/src/renderer/index.tsx @@ -1,14 +1,34 @@ -import { StrictMode } from 'react'; +import { StrictMode, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { RouterProvider } from '@tanstack/react-router'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ipcLink } from 'electron-trpc/renderer'; import { router } from './router'; +import { trpc } from './lib/trpc'; import './globals.css'; +function App() { + const [queryClient] = useState(() => new QueryClient()); + const [trpcClient] = useState(() => + trpc.createClient({ + links: [ipcLink()], + }), + ); + + return ( + + + + + + ); +} + const rootElement = document.getElementById('root'); if (!rootElement) throw new Error('Root element not found'); createRoot(rootElement).render( - + , ); diff --git a/src/renderer/lib/trpc.ts b/src/renderer/lib/trpc.ts new file mode 100644 index 0000000..12c8f5e --- /dev/null +++ b/src/renderer/lib/trpc.ts @@ -0,0 +1,4 @@ +import { createTRPCReact } from '@trpc/react-query'; +import type { AppRouter } from '../../main/router'; + +export const trpc = createTRPCReact(); diff --git a/src/renderer/routes/index.tsx b/src/renderer/routes/index.tsx index 5a0f6e1..25aca86 100644 --- a/src/renderer/routes/index.tsx +++ b/src/renderer/routes/index.tsx @@ -1,10 +1,13 @@ import { createFileRoute } from '@tanstack/react-router'; +import { trpc } from '@/lib/trpc'; export const Route = createFileRoute('/')({ component: HomePage, }); function HomePage() { + const pingQuery = trpc.health.ping.useQuery(); + return (
@@ -27,6 +30,11 @@ function HomePage() {

Adiuva is ready. Start building.

+ {pingQuery.data && ( +

+ tRPC IPC bridge: {pingQuery.data} +

+ )}
); }