From 72f418058fb074f8c01580389130f856a16179c6 Mon Sep 17 00:00:00 2001 From: Badtz Date: Thu, 27 Mar 2025 23:10:40 -0700 Subject: [PATCH 01/10] switch to ssg, add atcute, add iconify --- bun.lock | 53 +++++++++++++++++++++++++++ package.json | 11 +++++- src/app.css | 14 +++++++ src/lib/index.ts | 1 - src/routes/+layout.svelte | 12 +++++- src/routes/+layout.ts | 13 +++++++ src/routes/+page.svelte | 4 +- src/routes/landing/+page.svelte | 2 + src/routes/search/+page.svelte | 2 + src/routes/user/[handle]/+page.svelte | 12 ++++++ src/routes/user/[handle]/+page.ts | 18 +++++++++ svelte.config.js | 13 ++++++- 12 files changed, 146 insertions(+), 9 deletions(-) delete mode 100644 src/lib/index.ts create mode 100644 src/routes/+layout.ts create mode 100644 src/routes/landing/+page.svelte create mode 100644 src/routes/search/+page.svelte create mode 100644 src/routes/user/[handle]/+page.svelte create mode 100644 src/routes/user/[handle]/+page.ts diff --git a/bun.lock b/bun.lock index 77e46c8..bced015 100644 --- a/bun.lock +++ b/bun.lock @@ -4,9 +4,14 @@ "": { "name": "svelte", "devDependencies": { + "@atcute/client": "^2.0.9", + "@atcute/identity": "^0.1.2", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", + "@iconify-json/mynaui": "^1.2.9", + "@iconify/tailwind4": "^1.0.6", "@sveltejs/adapter-auto": "^4.0.0", + "@sveltejs/adapter-static": "^3.0.8", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", "@tailwindcss/vite": "^4.0.0", @@ -30,6 +35,16 @@ "packages": { "@ampproject/remapping": ["@ampproject/remapping@2.3.0", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw=="], + "@antfu/install-pkg": ["@antfu/install-pkg@1.0.0", "", { "dependencies": { "package-manager-detector": "^0.2.8", "tinyexec": "^0.3.2" } }, "sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw=="], + + "@antfu/utils": ["@antfu/utils@8.1.1", "", {}, "sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ=="], + + "@atcute/client": ["@atcute/client@2.0.9", "", {}, "sha512-QNDm9gMP6x9LY77ArwY+urQOBtQW74/onEAz42c40JxRm6Rl9K9cU4ROvNKJ+5cpVmEm1sthEWVRmDr5CSZENA=="], + + "@atcute/identity": ["@atcute/identity@0.1.2", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-YmRCXm/Z4lnJz4RItnr5e6NiTtQaCRb6xIEuaqRs/6wxKHMVEzFY8ROC24L7MO5qiAgIU6GsbWv67YmSo6Y2tQ=="], + + "@badrap/valita": ["@badrap/valita@0.4.3", "", {}, "sha512-C9iZSrVlTb610dxZ2oatK5LwefaHv0Q9eYfVDH3co846x7WinhCfc8jCDTE55yM8WxlmOfX2ckKmsSr7KzZ/gg=="], + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="], "@esbuild/android-arm": ["@esbuild/android-arm@0.25.1", "", { "os": "android", "cpu": "arm" }, "sha512-dp+MshLYux6j/JjdqVLnMglQlFu+MuVeNrmT5nk6q07wNhCdSnB7QZj+7G8VMUGh1q+vj2Bq8kRsuyA00I/k+Q=="], @@ -108,6 +123,14 @@ "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.2", "", {}, "sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ=="], + "@iconify-json/mynaui": ["@iconify-json/mynaui@1.2.9", "", { "dependencies": { "@iconify/types": "*" } }, "sha512-dd5yNIPxD3W/kRd9t8xc1SVh/UqicaYsaDg7dStGjlT1wqjhvkLjj10xeNZARz1vDaOlCoFJnkf2OKIejTnHOw=="], + + "@iconify/tailwind4": ["@iconify/tailwind4@1.0.6", "", { "dependencies": { "@iconify/types": "^2.0.0", "@iconify/utils": "^2.2.1" }, "peerDependencies": { "tailwindcss": ">= 4" } }, "sha512-43ZXe+bC7CuE2LCgROdqbQeFYJi/J7L/k1UpSy8KDQlWVsWxPzLSWbWhlJx4uRYLOh1NRyw02YlDOgzBOFNd+A=="], + + "@iconify/types": ["@iconify/types@2.0.0", "", {}, "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg=="], + + "@iconify/utils": ["@iconify/utils@2.3.0", "", { "dependencies": { "@antfu/install-pkg": "^1.0.0", "@antfu/utils": "^8.1.0", "@iconify/types": "^2.0.0", "debug": "^4.4.0", "globals": "^15.14.0", "kolorist": "^1.8.0", "local-pkg": "^1.0.0", "mlly": "^1.7.4" } }, "sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA=="], + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.8", "", { "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA=="], "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], @@ -170,6 +193,8 @@ "@sveltejs/adapter-auto": ["@sveltejs/adapter-auto@4.0.0", "", { "dependencies": { "import-meta-resolve": "^4.1.0" }, "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-kmuYSQdD2AwThymQF0haQhM8rE5rhutQXG4LNbnbShwhMO4qQGnKaaTy+88DuNSuoQDi58+thpq8XpHc1+oEKQ=="], + "@sveltejs/adapter-static": ["@sveltejs/adapter-static@3.0.8", "", { "peerDependencies": { "@sveltejs/kit": "^2.0.0" } }, "sha512-YaDrquRpZwfcXbnlDsSrBQNCChVOT9MGuSg+dMAyfsAa1SmiAhrA5jUYUiIMC59G92kIbY/AaQOWcBdq+lh+zg=="], + "@sveltejs/kit": ["@sveltejs/kit@2.20.2", "", { "dependencies": { "@types/cookie": "^0.6.0", "cookie": "^0.6.0", "devalue": "^5.1.0", "esm-env": "^1.2.2", "import-meta-resolve": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", "sade": "^1.8.1", "set-cookie-parser": "^2.6.0", "sirv": "^3.0.0" }, "peerDependencies": { "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", "vite": "^5.0.3 || ^6.0.0" }, "bin": { "svelte-kit": "svelte-kit.js" } }, "sha512-Dv8TOAZC9vyfcAB9TMsvUEJsRbklRTeNfcYBPaeH6KnABJ99i3CvCB2eNx8fiiliIqe+9GIchBg4RodRH5p1BQ=="], "@sveltejs/vite-plugin-svelte": ["@sveltejs/vite-plugin-svelte@5.0.3", "", { "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", "debug": "^4.4.0", "deepmerge": "^4.3.1", "kleur": "^4.1.5", "magic-string": "^0.30.15", "vitefu": "^1.0.4" }, "peerDependencies": { "svelte": "^5.0.0", "vite": "^6.0.0" } }, "sha512-MCFS6CrQDu1yGwspm4qtli0e63vaPCehf6V7pIMP15AsWgMKrqDGCPFF/0kn4SP0ii4aySu4Pa62+fIRGFMjgw=="], @@ -260,6 +285,8 @@ "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + "confbox": ["confbox@0.2.1", "", {}, "sha512-hkT3yDPFbs95mNCy1+7qNKC6Pro+/ibzYxtM2iqEigpf0sVw+bg4Zh9/snjsBcf990vfIsg5+1U7VyiyBb3etg=="], + "cookie": ["cookie@0.6.0", "", {}, "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], @@ -308,6 +335,8 @@ "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + "exsolve": ["exsolve@1.0.4", "", {}, "sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-glob": ["fast-glob@3.3.3", "", { "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" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], @@ -380,6 +409,8 @@ "known-css-properties": ["known-css-properties@0.35.0", "", {}, "sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A=="], + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], "lightningcss": ["lightningcss@1.29.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-darwin-arm64": "1.29.2", "lightningcss-darwin-x64": "1.29.2", "lightningcss-freebsd-x64": "1.29.2", "lightningcss-linux-arm-gnueabihf": "1.29.2", "lightningcss-linux-arm64-gnu": "1.29.2", "lightningcss-linux-arm64-musl": "1.29.2", "lightningcss-linux-x64-gnu": "1.29.2", "lightningcss-linux-x64-musl": "1.29.2", "lightningcss-win32-arm64-msvc": "1.29.2", "lightningcss-win32-x64-msvc": "1.29.2" } }, "sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA=="], @@ -406,6 +437,8 @@ "lilconfig": ["lilconfig@2.1.0", "", {}, "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ=="], + "local-pkg": ["local-pkg@1.1.1", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.0.1", "quansync": "^0.2.8" } }, "sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg=="], + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], @@ -420,6 +453,8 @@ "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], + "mlly": ["mlly@1.7.4", "", { "dependencies": { "acorn": "^8.14.0", "pathe": "^2.0.1", "pkg-types": "^1.3.0", "ufo": "^1.5.4" } }, "sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw=="], + "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], "mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="], @@ -436,16 +471,22 @@ "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + "package-manager-detector": ["package-manager-detector@0.2.11", "", { "dependencies": { "quansync": "^0.2.7" } }, "sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + "pkg-types": ["pkg-types@2.1.0", "", { "dependencies": { "confbox": "^0.2.1", "exsolve": "^1.0.1", "pathe": "^2.0.3" } }, "sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A=="], + "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], "postcss-load-config": ["postcss-load-config@3.1.4", "", { "dependencies": { "lilconfig": "^2.0.5", "yaml": "^1.10.2" }, "peerDependencies": { "postcss": ">=8.0.9", "ts-node": ">=9.0.0" }, "optionalPeers": ["postcss", "ts-node"] }, "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg=="], @@ -466,6 +507,8 @@ "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + "quansync": ["quansync@0.2.10", "", {}, "sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A=="], + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="], @@ -510,6 +553,8 @@ "tiny-glob": ["tiny-glob@0.2.9", "", { "dependencies": { "globalyzer": "0.1.0", "globrex": "^0.1.2" } }, "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg=="], + "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], "totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="], @@ -522,6 +567,8 @@ "typescript-eslint": ["typescript-eslint@8.27.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.27.0", "@typescript-eslint/parser": "8.27.0", "@typescript-eslint/utils": "8.27.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-ZZ/8+Y0rRUMuW1gJaPtLWe4ryHbsPLzzibk5Sq+IFa2aOH1Vo0gPr1fbA6pOnzBke7zC2Da4w8AyCgxKXo3lqA=="], + "ufo": ["ufo@1.5.4", "", {}, "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ=="], + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], @@ -546,10 +593,16 @@ "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], + "@iconify/utils/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "mlly/pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="], + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "mlly/pkg-types/confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="], } } diff --git a/package.json b/package.json index 6b15040..093b824 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { - "name": "svelte", + "name": "listy-web", + "license": "MIT", "private": true, "version": "0.0.1", "type": "module", @@ -14,9 +15,14 @@ "lint": "prettier --check . && eslint ." }, "devDependencies": { + "@atcute/client": "^2.0.9", + "@atcute/identity": "^0.1.2", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", + "@iconify-json/mynaui": "^1.2.9", + "@iconify/tailwind4": "^1.0.6", "@sveltejs/adapter-auto": "^4.0.0", + "@sveltejs/adapter-static": "^3.0.8", "@sveltejs/kit": "^2.16.0", "@sveltejs/vite-plugin-svelte": "^5.0.0", "@tailwindcss/vite": "^4.0.0", @@ -34,5 +40,6 @@ "typescript": "^5.0.0", "typescript-eslint": "^8.20.0", "vite": "^6.0.0" - } + }, + "dependencies": {} } diff --git a/src/app.css b/src/app.css index d4b5078..091543c 100644 --- a/src/app.css +++ b/src/app.css @@ -1 +1,15 @@ @import 'tailwindcss'; +@plugin "@iconify/tailwind4" { + scale: 2; +} + +html, +body { + height: 100%; + margin: 0; + overflow: hidden; /* Prevent scrolling */ +} + +#svelte { + height: 100%; +} diff --git a/src/lib/index.ts b/src/lib/index.ts deleted file mode 100644 index 856f2b6..0000000 --- a/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b93e9ba..200e357 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -1,7 +1,15 @@ -{@render children()} + + +
+ {@render children()} +
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts new file mode 100644 index 0000000..198d7e6 --- /dev/null +++ b/src/routes/+layout.ts @@ -0,0 +1,13 @@ +import { CredentialManager, XRPC } from '@atcute/client'; +import type { LayoutLoad } from './$types'; + +export const prerender = true; +export const trailingSlash = 'always'; + +export const load: LayoutLoad = async () => { + const manager = new CredentialManager({ service: 'https://bsky.social' }); + const rpc = new XRPC({ handler: manager }); + return { + rpc + }; +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index cc88df0..ca90b4a 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,2 +1,2 @@ -

Welcome to SvelteKit

-

Visit svelte.dev/docs/kit to read the documentation

+

Home Page

+ diff --git a/src/routes/landing/+page.svelte b/src/routes/landing/+page.svelte new file mode 100644 index 0000000..f1d2660 --- /dev/null +++ b/src/routes/landing/+page.svelte @@ -0,0 +1,2 @@ +

Landing

+ diff --git a/src/routes/search/+page.svelte b/src/routes/search/+page.svelte new file mode 100644 index 0000000..4ac4ed8 --- /dev/null +++ b/src/routes/search/+page.svelte @@ -0,0 +1,2 @@ +

Search

+ diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte new file mode 100644 index 0000000..1392a9e --- /dev/null +++ b/src/routes/user/[handle]/+page.svelte @@ -0,0 +1,12 @@ + +

{data.userData.handle}

+

{data.userData.did}

+ + + diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts new file mode 100644 index 0000000..3d5b01e --- /dev/null +++ b/src/routes/user/[handle]/+page.ts @@ -0,0 +1,18 @@ +import type { PageLoad } from './$types'; + +export const load: PageLoad = async ({ parent, params }) => { + const { rpc } = await parent(); + + const { data: userData } = await rpc.get('com.atproto.identity.resolveHandle', { + params: { + handle: params.handle + } + }); + + return { + userData: { + handle: params.handle, + did: userData.did + } + }; +}; diff --git a/svelte.config.js b/svelte.config.js index 5de1b1d..3c49214 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,5 +1,5 @@ +import adapter from '@sveltejs/adapter-static'; import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; -import adapter from 'svelte-adapter-bun'; /** @type {import('@sveltejs/kit').Config} */ const config = { @@ -11,7 +11,16 @@ const config = { // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list. // If your environment is not supported, or you settled on a specific environment, switch out the adapter. // See https://svelte.dev/docs/kit/adapters for more information about adapters. - adapter: adapter() + adapter: adapter({ + pages: 'build', + assets: 'build', + fallback: '200.html', + precompress: false, + strict: true, + prerender: { + entries: ['*'] + } + }) } }; From 37e68e86bf30155a0f3b599328354400fbbc1c68 Mon Sep 17 00:00:00 2001 From: Badtz Date: Thu, 27 Mar 2025 23:27:29 -0700 Subject: [PATCH 02/10] example component with atcute xrpc handler passing via props --- src/routes/+page.svelte | 7 ++++++- src/routes/user/[handle]/+page.svelte | 2 ++ src/routes/user/[handle]/+page.ts | 3 ++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ca90b4a..64d4d89 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,2 +1,7 @@ -

Home Page

+ + +

Home Page

+ diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index 1392a9e..167bf3a 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -1,4 +1,5 @@ + +

list data: {did}!

+

rpc: {rpc != null}

+ \ No newline at end of file From 299b29adcd7fd61e6959da8b5446da77b5f3fe36 Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 00:48:42 -0700 Subject: [PATCH 04/10] setup types, more intelligent list component implementation example --- .gitignore | 4 ++++ bun.lock | 9 +++++++++ package.json | 4 +++- src/lib/components/list.svelte | 29 +++++++++++++++++++-------- src/routes/+layout.ts | 1 + src/routes/user/[handle]/+page.svelte | 2 +- src/routes/user/[handle]/+page.ts | 20 +++++++++++++++--- tsconfig.json | 3 ++- util/generate-lexicons.sh | 7 +++++++ 9 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 util/generate-lexicons.sh diff --git a/.gitignore b/.gitignore index 3b462cb..2a5dfa9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,9 @@ node_modules +# Types +/util/lexicons +/src/types + # Output .output .vercel diff --git a/bun.lock b/bun.lock index bced015..dd8c7b5 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "devDependencies": { "@atcute/client": "^2.0.9", "@atcute/identity": "^0.1.2", + "@atcute/lex-cli": "^1.0.4", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", "@iconify-json/mynaui": "^1.2.9", @@ -43,6 +44,8 @@ "@atcute/identity": ["@atcute/identity@0.1.2", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-YmRCXm/Z4lnJz4RItnr5e6NiTtQaCRb6xIEuaqRs/6wxKHMVEzFY8ROC24L7MO5qiAgIU6GsbWv67YmSo6Y2tQ=="], + "@atcute/lex-cli": ["@atcute/lex-cli@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.3.11", "@externdefs/collider": "^0.1.0", "picocolors": "^1.1.1", "prettier": "^3.3.3" }, "bin": { "lex-cli": "cli.mjs" } }, "sha512-8mRnjjK+b6Z4wmfFRUYYPswVZhT7PYZBHLMCFNiI1AdrZqaJ1CmoiExYjkVGQkixZURRIaxr49KGBV2iSMF/pQ=="], + "@badrap/valita": ["@badrap/valita@0.4.3", "", {}, "sha512-C9iZSrVlTb610dxZ2oatK5LwefaHv0Q9eYfVDH3co846x7WinhCfc8jCDTE55yM8WxlmOfX2ckKmsSr7KzZ/gg=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="], @@ -115,6 +118,8 @@ "@eslint/plugin-kit": ["@eslint/plugin-kit@0.2.7", "", { "dependencies": { "@eslint/core": "^0.12.0", "levn": "^0.4.1" } }, "sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g=="], + "@externdefs/collider": ["@externdefs/collider@0.1.0", "", { "peerDependencies": { "@badrap/valita": "^0.3.9" } }, "sha512-vmFJEKHhftREiuhhK3WIMKk6bGfm7kM9c5HeVElFCbtqajXqCfwY/GR3f1G0qYWCvbtcoBhIZ2O8ia3A2/pjkw=="], + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], @@ -587,10 +592,14 @@ "zimmerframe": ["zimmerframe@1.1.2", "", {}, "sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w=="], + "@atcute/lex-cli/@badrap/valita": ["@badrap/valita@0.3.16", "", {}, "sha512-slP2blSd6A+xUBgGf+wW6adGd72ojBLxemU0jXQ0fXQcsZWYQ70wTLTJggs6+oxcAqN/bvYA3Ops8SqR2Imyaw=="], + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + "@externdefs/collider/@badrap/valita": ["@badrap/valita@0.3.16", "", {}, "sha512-slP2blSd6A+xUBgGf+wW6adGd72ojBLxemU0jXQ0fXQcsZWYQ70wTLTJggs6+oxcAqN/bvYA3Ops8SqR2Imyaw=="], + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], "@iconify/utils/globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], diff --git a/package.json b/package.json index 093b824..f6aaff9 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,13 @@ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "format": "prettier --write .", - "lint": "prettier --check . && eslint ." + "lint": "prettier --check . && eslint .", + "types": "bash ./util/generate-lexicons.sh" }, "devDependencies": { "@atcute/client": "^2.0.9", "@atcute/identity": "^0.1.2", + "@atcute/lex-cli": "^1.0.4", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", "@iconify-json/mynaui": "^1.2.9", diff --git a/src/lib/components/list.svelte b/src/lib/components/list.svelte index ad729c0..444805b 100644 --- a/src/lib/components/list.svelte +++ b/src/lib/components/list.svelte @@ -1,9 +1,22 @@ - - -

list data: {did}!

-

rpc: {rpc != null}

- \ No newline at end of file + + diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 198d7e6..a02cfe3 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -7,6 +7,7 @@ export const trailingSlash = 'always'; export const load: LayoutLoad = async () => { const manager = new CredentialManager({ service: 'https://bsky.social' }); const rpc = new XRPC({ handler: manager }); + await manager.login({ identifier: 'm.woach.me', password: 'c5sj-oyqa-uxhx-ju45' }); return { rpc }; diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index 167bf3a..c063380 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -9,6 +9,6 @@

{data.userData.handle}

{data.userData.did}

- + diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts index eb272a7..7124945 100644 --- a/src/routes/user/[handle]/+page.ts +++ b/src/routes/user/[handle]/+page.ts @@ -1,3 +1,4 @@ +import type { ComAtprotoRepoListRecords, MeWoachFeedSession } from '@atcute/client/lexicons'; // Import the type import type { PageLoad } from './$types'; export const load: PageLoad = async ({ parent, params }) => { @@ -9,11 +10,24 @@ export const load: PageLoad = async ({ parent, params }) => { } }); + const { + data: { records } + } = await rpc.get('com.atproto.repo.listRecords', { + params: { + repo: userData.did, + collection: 'me.woach.feed.session' + } + }); + + const sessionsValues: MeWoachFeedSession.Record[] = records.map( + (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedSession.Record + ); + return { userData: { handle: params.handle, - did: userData.did - }, - rpc + did: userData.did, + sessions: sessionsValues + } }; }; diff --git a/tsconfig.json b/tsconfig.json index 0b2d886..8116ab2 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "./.svelte-kit/tsconfig.json", "compilerOptions": { + "typeRoots": ["node_modules/@types", "src/types"], "allowJs": true, "checkJs": true, "esModuleInterop": true, @@ -9,7 +10,7 @@ "skipLibCheck": true, "sourceMap": true, "strict": true, - "moduleResolution": "bundler" + "moduleResolution": "bundler", } // Path aliases are handled by https://svelte.dev/docs/kit/configuration#alias // except $lib which is handled by https://svelte.dev/docs/kit/configuration#files diff --git a/util/generate-lexicons.sh b/util/generate-lexicons.sh new file mode 100644 index 0000000..1db6dee --- /dev/null +++ b/util/generate-lexicons.sh @@ -0,0 +1,7 @@ +#!bin/bash + + +pnpm exec lex-cli generate \ + ./util/lexicons/me/woach/**/*.json \ + -o ./src/types/lexicons.ts \ + --description "Contains type declarations for woach.me lexicons" \ No newline at end of file From 9a3819293c424298c962bc75605f809453c4b978 Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 13:56:27 -0700 Subject: [PATCH 05/10] implement utility functions, reactive list updates --- bun.lock | 5 +++ package.json | 1 + src/lib/util.ts | 58 +++++++++++++++++++++++++++ src/routes/+layout.ts | 12 ------ src/routes/+page.svelte | 3 -- src/routes/user/[handle]/+page.svelte | 8 +--- src/routes/user/[handle]/+page.ts | 32 ++++----------- 7 files changed, 74 insertions(+), 45 deletions(-) create mode 100644 src/lib/util.ts diff --git a/bun.lock b/bun.lock index dd8c7b5..59c84b8 100644 --- a/bun.lock +++ b/bun.lock @@ -6,6 +6,7 @@ "devDependencies": { "@atcute/client": "^2.0.9", "@atcute/identity": "^0.1.2", + "@atcute/identity-resolver": "^0.1.2", "@atcute/lex-cli": "^1.0.4", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", @@ -44,8 +45,12 @@ "@atcute/identity": ["@atcute/identity@0.1.2", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-YmRCXm/Z4lnJz4RItnr5e6NiTtQaCRb6xIEuaqRs/6wxKHMVEzFY8ROC24L7MO5qiAgIU6GsbWv67YmSo6Y2tQ=="], + "@atcute/identity-resolver": ["@atcute/identity-resolver@0.1.2", "", { "dependencies": { "@atcute/util-fetch": "^1.0.0", "@badrap/valita": "^0.4.2" }, "peerDependencies": { "@atcute/identity": "^0.1.0" } }, "sha512-fP2VbHD04kVcCdNi/Kszo6jFzqM7Pg3p33oGhfp2zVkwFKaVBlwCaFRWEga/Xvu/IDLwNdASGWnLqoA34SFeSg=="], + "@atcute/lex-cli": ["@atcute/lex-cli@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.3.11", "@externdefs/collider": "^0.1.0", "picocolors": "^1.1.1", "prettier": "^3.3.3" }, "bin": { "lex-cli": "cli.mjs" } }, "sha512-8mRnjjK+b6Z4wmfFRUYYPswVZhT7PYZBHLMCFNiI1AdrZqaJ1CmoiExYjkVGQkixZURRIaxr49KGBV2iSMF/pQ=="], + "@atcute/util-fetch": ["@atcute/util-fetch@1.0.1", "", { "dependencies": { "@badrap/valita": "^0.4.2" } }, "sha512-Clc0E/5ufyGBVfYBUwWNlHONlZCoblSr4Ho50l1LhmRPGB1Wu/AQ9Sz+rsBg7fdaW/auve8ulmwhRhnX2cGRow=="], + "@badrap/valita": ["@badrap/valita@0.4.3", "", {}, "sha512-C9iZSrVlTb610dxZ2oatK5LwefaHv0Q9eYfVDH3co846x7WinhCfc8jCDTE55yM8WxlmOfX2ckKmsSr7KzZ/gg=="], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-kfYGy8IdzTGy+z0vFGvExZtxkFlA4zAxgKEahG9KE1ScBjpQnFsNOX8KTU5ojNru5ed5CVoJYXFtoxaq5nFbjQ=="], diff --git a/package.json b/package.json index f6aaff9..993ccd6 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "devDependencies": { "@atcute/client": "^2.0.9", "@atcute/identity": "^0.1.2", + "@atcute/identity-resolver": "^0.1.2", "@atcute/lex-cli": "^1.0.4", "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", diff --git a/src/lib/util.ts b/src/lib/util.ts new file mode 100644 index 0000000..93a0a7d --- /dev/null +++ b/src/lib/util.ts @@ -0,0 +1,58 @@ +import { CredentialManager, XRPC } from '@atcute/client'; +import { getPdsEndpoint } from '@atcute/identity'; +import { + AtprotoWebDidDocumentResolver, + CompositeDidDocumentResolver, + PlcDidDocumentResolver, + XrpcHandleResolver +} from '@atcute/identity-resolver'; + +const didDocumentResolver = new CompositeDidDocumentResolver({ + methods: { + plc: new PlcDidDocumentResolver(), + web: new AtprotoWebDidDocumentResolver() + } +}); + +const handleResolver = new XrpcHandleResolver({ + serviceUrl: 'https://public.api.bsky.app' +}); + +async function resolvePDS(did: string) { + const doc = await didDocumentResolver.resolve(did as `did:plc:${string}` | `did:web:${string}`); + const pds = getPdsEndpoint(doc); + return pds; +} + +export async function resolveHandle(handle: string) { + if (!handle.includes('.')) { + throw new Error(`Invalid DID: ${handle}`); + } + return await handleResolver.resolve(handle as `${string}.${string}`); +} + +export async function createRPC(did: string) { + if (!did.startsWith('did:')) did = await resolveHandle(did); + + const pds = await resolvePDS(did); + if (!pds) { + throw new Error(`Failed to resolve PDS for DID: ${did}`); + } + + const manager = new CredentialManager({ service: pds }); + const rpc = new XRPC({ handler: manager }); + + return rpc; +} + +export async function getSessions(rpc: XRPC, did: string) { + const { + data: { records } + } = await rpc.get('com.atproto.repo.listRecords', { + params: { + repo: did, + collection: 'me.woach.feed.session' + } + }); + return records; +} diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index a02cfe3..ba58d86 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1,14 +1,2 @@ -import { CredentialManager, XRPC } from '@atcute/client'; -import type { LayoutLoad } from './$types'; - export const prerender = true; export const trailingSlash = 'always'; - -export const load: LayoutLoad = async () => { - const manager = new CredentialManager({ service: 'https://bsky.social' }); - const rpc = new XRPC({ handler: manager }); - await manager.login({ identifier: 'm.woach.me', password: 'c5sj-oyqa-uxhx-ju45' }); - return { - rpc - }; -}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 64d4d89..ffba1b5 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,7 +1,4 @@

Home Page

- - diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index c063380..7aea26f 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -3,12 +3,8 @@ import type { PageProps } from './$types'; let { data }: PageProps = $props(); - - -

{data.userData.handle}

-

{data.userData.did}

- - +

{data.handle}

+ diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts index 7124945..154cfd6 100644 --- a/src/routes/user/[handle]/+page.ts +++ b/src/routes/user/[handle]/+page.ts @@ -1,33 +1,17 @@ -import type { ComAtprotoRepoListRecords, MeWoachFeedSession } from '@atcute/client/lexicons'; // Import the type +import { createRPC, getSessions, resolveHandle } from '$lib/util'; +import type { ComAtprotoRepoListRecords, MeWoachFeedSession } from '@atcute/client/lexicons'; import type { PageLoad } from './$types'; -export const load: PageLoad = async ({ parent, params }) => { - const { rpc } = await parent(); +export const load: PageLoad = async ({ params }) => { + const did = await resolveHandle(params.handle); + const rpc = await createRPC(did); - const { data: userData } = await rpc.get('com.atproto.identity.resolveHandle', { - params: { - handle: params.handle - } - }); - - const { - data: { records } - } = await rpc.get('com.atproto.repo.listRecords', { - params: { - repo: userData.did, - collection: 'me.woach.feed.session' - } - }); - - const sessionsValues: MeWoachFeedSession.Record[] = records.map( + const sessions: MeWoachFeedSession.Record[] = (await getSessions(rpc, did)).map( (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedSession.Record ); return { - userData: { - handle: params.handle, - did: userData.did, - sessions: sessionsValues - } + handle: params.handle, + sessions: sessions }; }; From e30d3da1766fca2d9ebc1eeed55b7ea9826352f3 Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 14:04:56 -0700 Subject: [PATCH 06/10] basic activity feed --- src/lib/components/activity.svelte | 16 ++++++++++++++++ src/lib/util.ts | 12 ++++++++++++ src/routes/user/[handle]/+page.svelte | 2 ++ src/routes/user/[handle]/+page.ts | 17 ++++++++++++++--- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/lib/components/activity.svelte diff --git a/src/lib/components/activity.svelte b/src/lib/components/activity.svelte new file mode 100644 index 0000000..88c2a83 --- /dev/null +++ b/src/lib/components/activity.svelte @@ -0,0 +1,16 @@ + + +
    + {#each activity as activityItem} +
  • +
    +

    {activityItem.performedAt}

    +

    {activityItem.progress}

    +

    {activityItem.session.uri}

    +
    +
  • + {/each} +
diff --git a/src/lib/util.ts b/src/lib/util.ts index 93a0a7d..09139b1 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -56,3 +56,15 @@ export async function getSessions(rpc: XRPC, did: string) { }); return records; } + +export async function getActivity(rpc: XRPC, did: string) { + const { + data: { records } + } = await rpc.get('com.atproto.repo.listRecords', { + params: { + repo: did, + collection: 'me.woach.feed.activity' + } + }); + return records; +} diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index 7aea26f..4c5d477 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -1,4 +1,5 @@ -
    - {#each activity as activityItem} -
  • -
    -

    {activityItem.performedAt}

    -

    {activityItem.progress}

    -

    {activityItem.session.uri}

    -
    -
  • - {/each} -
+
+

Activity:

+
    + {#each activity as activityItem} +
  • +
    +

    {activityItem.performedAt}

    +

    {activityItem.progress}

    +

    {activityItem.session.uri}

    +
    +
  • + {/each} +
+
diff --git a/src/lib/components/list.svelte b/src/lib/components/list.svelte index 444805b..69b3dcd 100644 --- a/src/lib/components/list.svelte +++ b/src/lib/components/list.svelte @@ -3,20 +3,23 @@ export let sessions: MeWoachFeedSession.Record[] = []; - +
+

List:

+ +
diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index 4c5d477..274b5f0 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -8,5 +8,7 @@

{data.handle}

- - +
+ + +
diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts index f0e9d58..dfe0416 100644 --- a/src/routes/user/[handle]/+page.ts +++ b/src/routes/user/[handle]/+page.ts @@ -18,8 +18,6 @@ export const load: PageLoad = async ({ params }) => { (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedActivity.Record ); - console.log(activity); - return { handle: params.handle, sessions: sessions, From e876d5846e6b4e36e2eaf3b42f9b850cf1b50138 Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 15:56:30 -0700 Subject: [PATCH 08/10] add session and content resolution for activity --- src/lib/components/activity.svelte | 27 ++++++++++++++++++++----- src/lib/components/list.svelte | 7 ------- src/lib/util.ts | 32 ++++++++++++++++++++++++++++++ src/routes/user/[handle]/+page.ts | 32 +++++++++++++++++++++++++++--- 4 files changed, 83 insertions(+), 15 deletions(-) diff --git a/src/lib/components/activity.svelte b/src/lib/components/activity.svelte index 72846c4..5025313 100644 --- a/src/lib/components/activity.svelte +++ b/src/lib/components/activity.svelte @@ -1,6 +1,14 @@
@@ -9,9 +17,18 @@ {#each activity as activityItem}
  • -

    {activityItem.performedAt}

    -

    {activityItem.progress}

    -

    {activityItem.session.uri}

    +

    {activityItem.content.id}

    +

    + Watched episode {activityItem.activity.progress} at {activityItem.activity.performedAt} +

    + {#if activityItem.session.participants?.length} +

    With:

    + {#each activityItem.session.participants ?? [] as participant} + {participant.uri.split('at://')[1]} + {/each} + {/if}
  • {/each} diff --git a/src/lib/components/list.svelte b/src/lib/components/list.svelte index 69b3dcd..332ab89 100644 --- a/src/lib/components/list.svelte +++ b/src/lib/components/list.svelte @@ -11,13 +11,6 @@
    {session.label}

    {session.createdAt}

    - {#if session.participants?.length} - {#each session.participants ?? [] as participant} - {participant.uri.split('at://')[1]} - {/each} - {/if}
    {/each} diff --git a/src/lib/util.ts b/src/lib/util.ts index 09139b1..ea6fe97 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -7,6 +7,8 @@ import { XrpcHandleResolver } from '@atcute/identity-resolver'; +import type { At } from '@atcute/client/lexicons'; + const didDocumentResolver = new CompositeDidDocumentResolver({ methods: { plc: new PlcDidDocumentResolver(), @@ -68,3 +70,33 @@ export async function getActivity(rpc: XRPC, did: string) { }); return records; } + +export async function resolveSession(rpc: XRPC, uri: At.Uri) { + const repo = uri.split('at://')[1].split('/')[0]; + const rkey = uri.split('/')[4]; + const { + data: { value } + } = await rpc.get('com.atproto.repo.getRecord', { + params: { + repo, + rkey, + collection: 'me.woach.feed.session' + } + }); + return value; +} + +export async function resolveMedia(rpc: XRPC, uri: At.Uri) { + const repo = uri.split('at://')[1].split('/')[0]; + const rkey = uri.split('/')[4]; + const { + data: { value } + } = await rpc.get('com.atproto.repo.getRecord', { + params: { + repo, + rkey, + collection: 'me.woach.content.anilist' + } + }); + return value; +} diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts index dfe0416..467a4eb 100644 --- a/src/routes/user/[handle]/+page.ts +++ b/src/routes/user/[handle]/+page.ts @@ -1,6 +1,14 @@ -import { createRPC, getActivity, getSessions, resolveHandle } from '$lib/util'; +import { + createRPC, + getActivity, + getSessions, + resolveHandle, + resolveMedia, + resolveSession +} from '$lib/util'; import type { ComAtprotoRepoListRecords, + MeWoachContentAnilist, MeWoachFeedActivity, MeWoachFeedSession } from '@atcute/client/lexicons'; @@ -14,10 +22,28 @@ export const load: PageLoad = async ({ params }) => { (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedSession.Record ); - const activity: MeWoachFeedActivity.Record[] = (await getActivity(rpc, did)).map( - (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedActivity.Record + const activity: { + session: MeWoachFeedSession.Record; + activity: MeWoachFeedActivity.Record; + }[] = await Promise.all( + (await getActivity(rpc, did)).map(async (activityRecord: ComAtprotoRepoListRecords.Record) => { + const session = (await resolveSession( + rpc, + (activityRecord.value as MeWoachFeedActivity.Record).session.uri + )) as MeWoachFeedSession.Record; + + const content = (await resolveMedia(rpc, session.content.uri)) as MeWoachContentAnilist.Main; + + return { + session, + activity: activityRecord.value as MeWoachFeedActivity.Record, + content + }; + }) ); + console.log(activity); + return { handle: params.handle, sessions: sessions, From 504a63293df50ba28e2acef3791f37fbc5183376 Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 16:06:50 -0700 Subject: [PATCH 09/10] add lexicon repo as submodule --- .gitignore | 2 +- .gitmodules | 3 +++ util/anylists | 1 + util/generate-lexicons.sh | 4 +++- 4 files changed, 8 insertions(+), 2 deletions(-) create mode 100644 .gitmodules create mode 160000 util/anylists diff --git a/.gitignore b/.gitignore index 2a5dfa9..7ccb443 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ node_modules # Types -/util/lexicons +/util/anylists /src/types # Output diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..9888b8e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "util/anylists"] + path = util/anylists + url = ssh://forgejo@winry.woach.me:922/Julia/anylists.git diff --git a/util/anylists b/util/anylists new file mode 160000 index 0000000..90fa614 --- /dev/null +++ b/util/anylists @@ -0,0 +1 @@ +Subproject commit 90fa6148a5e48ee6b95ddfe74eb3818dfef71528 diff --git a/util/generate-lexicons.sh b/util/generate-lexicons.sh index 1db6dee..811ad47 100644 --- a/util/generate-lexicons.sh +++ b/util/generate-lexicons.sh @@ -1,7 +1,9 @@ #!bin/bash +git submodule update --remote + pnpm exec lex-cli generate \ - ./util/lexicons/me/woach/**/*.json \ + ./util/anylists/lexicons/me/woach/**/*.json \ -o ./src/types/lexicons.ts \ --description "Contains type declarations for woach.me lexicons" \ No newline at end of file From 504c8ecd6e0f9d8be54d190451cfb31de494c88c Mon Sep 17 00:00:00 2001 From: Badtz Date: Fri, 28 Mar 2025 17:30:20 -0700 Subject: [PATCH 10/10] add simple +1 buttons for list --- src/lib/components/list.svelte | 29 ++++++++++++-- src/lib/util.ts | 54 ++++++++++++++++++++++++++- src/routes/user/[handle]/+page.svelte | 2 +- src/routes/user/[handle]/+page.ts | 22 ++++++++--- 4 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/lib/components/list.svelte b/src/lib/components/list.svelte index 332ab89..d6ad39e 100644 --- a/src/lib/components/list.svelte +++ b/src/lib/components/list.svelte @@ -1,6 +1,22 @@
    @@ -9,8 +25,13 @@ {#each sessions as session}
  • - {session.label} -

    {session.createdAt}

    + {session.record.label} +

    {session.record.createdAt}

    +

    {session.progress}

    +
  • {/each} diff --git a/src/lib/util.ts b/src/lib/util.ts index ea6fe97..cd16435 100644 --- a/src/lib/util.ts +++ b/src/lib/util.ts @@ -7,7 +7,7 @@ import { XrpcHandleResolver } from '@atcute/identity-resolver'; -import type { At } from '@atcute/client/lexicons'; +import type { At, MeWoachFeedActivity } from '@atcute/client/lexicons'; const didDocumentResolver = new CompositeDidDocumentResolver({ methods: { @@ -43,6 +43,7 @@ export async function createRPC(did: string) { const manager = new CredentialManager({ service: pds }); const rpc = new XRPC({ handler: manager }); + // await manager.login({ identifier: '', password: '' }); return rpc; } @@ -100,3 +101,54 @@ export async function resolveMedia(rpc: XRPC, uri: At.Uri) { }); return value; } + +export async function addActivity( + did: At.DID, + rpc: XRPC, + uri: At.Uri, + cid: At.CID, + count: number = 1, + performedAt: string = new Date().toISOString() +) { + const activityRecord: MeWoachFeedActivity.Record = { + $type: 'me.woach.feed.activity', + createdAt: new Date().toISOString(), + progress: count, + session: { cid, uri }, + performedAt + }; + + const result = await rpc.call('com.atproto.repo.createRecord', { + data: { + repo: did, + collection: 'me.woach.feed.activity', + record: activityRecord + } + }); + + return result.data.uri; +} + +export async function getProgress(rpc: XRPC, did: string, uri: At.Uri) { + const currentProgress = await rpc.get('com.atproto.repo.listRecords', { + params: { + repo: did, + collection: 'me.woach.feed.activity' + } + }); + + const filteredRecords = currentProgress.data.records.filter((a) => { + const record = a.value as MeWoachFeedActivity.Record; + return record.session.uri === uri; + }); + + let lastProgress = 0; + if (filteredRecords.length > 0) { + const lastUpdate = filteredRecords[0]?.value as MeWoachFeedActivity.Record; + lastProgress = Number(lastUpdate.progress); + + return lastProgress; + } else { + return 0; + } +} diff --git a/src/routes/user/[handle]/+page.svelte b/src/routes/user/[handle]/+page.svelte index 274b5f0..bd2feb0 100644 --- a/src/routes/user/[handle]/+page.svelte +++ b/src/routes/user/[handle]/+page.svelte @@ -10,5 +10,5 @@
    - +
    diff --git a/src/routes/user/[handle]/+page.ts b/src/routes/user/[handle]/+page.ts index 467a4eb..e692e3f 100644 --- a/src/routes/user/[handle]/+page.ts +++ b/src/routes/user/[handle]/+page.ts @@ -1,6 +1,7 @@ import { createRPC, getActivity, + getProgress, getSessions, resolveHandle, resolveMedia, @@ -18,13 +19,24 @@ export const load: PageLoad = async ({ params }) => { const did = await resolveHandle(params.handle); const rpc = await createRPC(did); - const sessions: MeWoachFeedSession.Record[] = (await getSessions(rpc, did)).map( - (record: ComAtprotoRepoListRecords.Record) => record.value as MeWoachFeedSession.Record + const sessions: { + record: MeWoachFeedSession.Record; + uri: string; + cid: string; + progress: number; + }[] = await Promise.all( + (await getSessions(rpc, did)).map(async (record: ComAtprotoRepoListRecords.Record) => ({ + record: record.value as MeWoachFeedSession.Record, + uri: record.uri, + cid: record.cid, + progress: await getProgress(rpc, did, record.uri) + })) ); const activity: { session: MeWoachFeedSession.Record; activity: MeWoachFeedActivity.Record; + content: MeWoachContentAnilist.Main; }[] = await Promise.all( (await getActivity(rpc, did)).map(async (activityRecord: ComAtprotoRepoListRecords.Record) => { const session = (await resolveSession( @@ -42,11 +54,11 @@ export const load: PageLoad = async ({ params }) => { }) ); - console.log(activity); - return { handle: params.handle, sessions: sessions, - activity: activity + activity: activity, + rpc, + did }; };