social bookmarking for atproto

[appview] rewrite in typescript using hono and bun

diddyfo.id a7de7db2 d0f63cb2

verified
+730 -2543
+1
.gitignore
··· 1 1 .DS_Store 2 + backend/node_modules
+3 -5
backend/.gitignore
··· 1 - # https://dart.dev/guides/libraries/private-files 2 - # Created by `dart pub` 3 - .dart_tool/ 4 - config.yaml 5 - *.db 1 + # deps 2 + ../../clippr-ts/node_modules/ 3 + config.toml
-3
backend/CHANGELOG.md
··· 1 - # clippr-be changelog 2 - ## 0.1.0 3 - - Initial version.
+22 -9
backend/README.md
··· 1 - # clippr-be 2 - the reference appview for clippr, written in Dart and using the [atproto.dart](https://github.com/myConsciousness/atproto.dart) library 1 + # clippr-ts 2 + typescript implementation of clippr appview using ~~bun~~ deno and hono 3 + 4 + ## run and develop 5 + ```sh 6 + deno install 7 + deno run dev 8 + ``` 9 + 10 + open http://localhost:9090 and enjoy 11 + 12 + ## current status 13 + right now we're not running on bun because there are 14 + [some issues with the jetstream library](https://github.com/oven-sh/bun/issues/18807), which haven't been fixed yet. 3 15 4 - ## set up and run 5 - ```bash 6 - cp config.example.yaml config.yaml 7 - vi config.yaml # modify settings here 8 - chmod +x tools/build_and_run.sh 9 - ./tools/build_and_run.sh 10 - ``` 16 + ### checklist before it's usable 17 + * [ ] Ingesting content from the firehose (using Jetstream) 18 + * [ ] Creating the lexicon documents and validating content that comes in from the firehose 19 + * [ ] Indexing valid content from the firehose into a database 20 + * [ ] Handling OAuth authentication (public OAuth for the moment) 21 + * [ ] Creating responses to API calls 22 + * [ ] Create records through the API 23 + * [ ] Interact with the frontend
-30
backend/analysis_options.yaml
··· 1 - # This file configures the static analysis results for your project (errors, 2 - # warnings, and lints). 3 - # 4 - # This enables the 'recommended' set of lints from `package:lints`. 5 - # This set helps identify many issues that may lead to problems when running 6 - # or consuming Dart code, and enforces writing Dart using a single, idiomatic 7 - # style and format. 8 - # 9 - # If you want a smaller set of lints you can change this to specify 10 - # 'package:lints/core.yaml'. These are just the most critical lints 11 - # (the recommended set includes the core lints). 12 - # The core lints are also what is used by pub.dev for scoring packages. 13 - 14 - include: package:lints/recommended.yaml 15 - 16 - # Uncomment the following section to specify additional rules. 17 - 18 - # linter: 19 - # rules: 20 - # - camel_case_types 21 - 22 - # analyzer: 23 - # exclude: 24 - # - path/to/excluded/files/** 25 - 26 - # For more information about the core and recommended set of lints, see 27 - # https://dart.dev/go/core-lints 28 - 29 - # For additional information about configuring this file, see 30 - # https://dart.dev/guides/language/analysis-options
-25
backend/bin/clippr.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'package:clippr/config/config.dart' show Config; 8 - import 'package:clippr/config/pubspec.dart' show ClipprPubspec; 9 - import 'package:clippr/server/logger.dart' show Logger; 10 - import 'package:clippr/server/server.dart'; 11 - 12 - void main(List<String> arguments) { 13 - ClipprPubspec(); // initialize pubspec 14 - Logger(); // initialize logger 15 - Logger.logInfo("${ClipprPubspec.getName()} ${ClipprPubspec.getVersion()}"); 16 - Logger.logInfo("Initializing config..."); 17 - Config(); // initialize config 18 - Logger.logInfo("Initializing database at ${Config.getDatabaseName()}..."); 19 - launchDatabase(); 20 - Logger.logInfo("Initializing firehose..."); 21 - launchFirehose(); 22 - Logger.logInfo("Starting server at ${Config.getHostname()}:${Config.getPort()}"); 23 - launchWebServer(); 24 - Logger.logInfo("Server launched!"); 25 - }
+409
backend/bun.lock
··· 1 + { 2 + "lockfileVersion": 1, 3 + "workspaces": { 4 + "": { 5 + "name": "clippr-ts", 6 + "dependencies": { 7 + "@skyware/jetstream": "^0.2.2", 8 + "drizzle-orm": "^0.44.2", 9 + "hono": "^4.8.3", 10 + "toml": "^3.0.0", 11 + }, 12 + "devDependencies": { 13 + "@eslint/js": "^9.30.1", 14 + "@types/bun": "^1.2.17", 15 + "drizzle-kit": "^0.31.4", 16 + "eslint": "^9.30.1", 17 + "globals": "^16.3.0", 18 + "typescript-eslint": "^8.35.1", 19 + }, 20 + }, 21 + }, 22 + "packages": { 23 + "@atcute/bluesky": ["@atcute/bluesky@1.0.15", "", { "peerDependencies": { "@atcute/client": "^1.0.0 || ^2.0.0" } }, "sha512-+EFiybmKQ97aBAgtaD+cKRJER5AMn3cZMkEwEg/pDdWyzxYJ9m1UgemmLdTgI8VrxPufKqdXS2nl7uO7TY6BPA=="], 24 + 25 + "@atcute/client": ["@atcute/client@2.0.9", "", {}, "sha512-QNDm9gMP6x9LY77ArwY+urQOBtQW74/onEAz42c40JxRm6Rl9K9cU4ROvNKJ+5cpVmEm1sthEWVRmDr5CSZENA=="], 26 + 27 + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], 28 + 29 + "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], 30 + 31 + "@esbuild-kit/esm-loader": ["@esbuild-kit/esm-loader@2.6.5", "", { "dependencies": { "@esbuild-kit/core-utils": "^3.3.2", "get-tsconfig": "^4.7.0" } }, "sha512-FxEMIkJKnodyA1OaCUoEvbYRkoZlLZ4d/eXFu9Fh8CbBBgP5EmZxrfTRyN0qpXZ4vOvqnE5YdRdcrmUUXuU+dA=="], 32 + 33 + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.5", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA=="], 34 + 35 + "@esbuild/android-arm": ["@esbuild/android-arm@0.25.5", "", { "os": "android", "cpu": "arm" }, "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA=="], 36 + 37 + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.5", "", { "os": "android", "cpu": "arm64" }, "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg=="], 38 + 39 + "@esbuild/android-x64": ["@esbuild/android-x64@0.25.5", "", { "os": "android", "cpu": "x64" }, "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw=="], 40 + 41 + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ=="], 42 + 43 + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ=="], 44 + 45 + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.5", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw=="], 46 + 47 + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.5", "", { "os": "freebsd", "cpu": "x64" }, "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw=="], 48 + 49 + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.5", "", { "os": "linux", "cpu": "arm" }, "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw=="], 50 + 51 + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg=="], 52 + 53 + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.5", "", { "os": "linux", "cpu": "ia32" }, "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA=="], 54 + 55 + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg=="], 56 + 57 + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg=="], 58 + 59 + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.5", "", { "os": "linux", "cpu": "ppc64" }, "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ=="], 60 + 61 + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.5", "", { "os": "linux", "cpu": "none" }, "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA=="], 62 + 63 + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.5", "", { "os": "linux", "cpu": "s390x" }, "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ=="], 64 + 65 + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.5", "", { "os": "linux", "cpu": "x64" }, "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw=="], 66 + 67 + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.5", "", { "os": "none", "cpu": "arm64" }, "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw=="], 68 + 69 + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.5", "", { "os": "none", "cpu": "x64" }, "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ=="], 70 + 71 + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.5", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw=="], 72 + 73 + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.5", "", { "os": "openbsd", "cpu": "x64" }, "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg=="], 74 + 75 + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.5", "", { "os": "sunos", "cpu": "x64" }, "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA=="], 76 + 77 + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw=="], 78 + 79 + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ=="], 80 + 81 + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.5", "", { "os": "win32", "cpu": "x64" }, "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g=="], 82 + 83 + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="], 84 + 85 + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="], 86 + 87 + "@eslint/config-array": ["@eslint/config-array@0.21.0", "", { "dependencies": { "@eslint/object-schema": "^2.1.6", "debug": "^4.3.1", "minimatch": "^3.1.2" } }, "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ=="], 88 + 89 + "@eslint/config-helpers": ["@eslint/config-helpers@0.3.0", "", {}, "sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw=="], 90 + 91 + "@eslint/core": ["@eslint/core@0.14.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg=="], 92 + 93 + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.1", "", { "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" } }, "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ=="], 94 + 95 + "@eslint/js": ["@eslint/js@9.30.1", "", {}, "sha512-zXhuECFlyep42KZUhWjfvsmXGX39W8K8LFb8AWXM9gSV9dQB+MrJGLKvW6Zw0Ggnbpw0VHTtrhFXYe3Gym18jg=="], 96 + 97 + "@eslint/object-schema": ["@eslint/object-schema@2.1.6", "", {}, "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA=="], 98 + 99 + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.3.3", "", { "dependencies": { "@eslint/core": "^0.15.1", "levn": "^0.4.1" } }, "sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag=="], 100 + 101 + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], 102 + 103 + "@humanfs/node": ["@humanfs/node@0.16.6", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.3.0" } }, "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw=="], 104 + 105 + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], 106 + 107 + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], 108 + 109 + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], 110 + 111 + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], 112 + 113 + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], 114 + 115 + "@skyware/jetstream": ["@skyware/jetstream@0.2.2", "", { "dependencies": { "@atcute/bluesky": "^1.0.6", "partysocket": "^1.0.2" } }, "sha512-d1MtWPTIFEciSzV8OClXZCJoz0DJ7aupt4EZSwpGAASYG0ZIPmZTt7RVJkoFzQyqRPHAMD7CvEwu0ut3MHX1og=="], 116 + 117 + "@types/bun": ["@types/bun@1.2.17", "", { "dependencies": { "bun-types": "1.2.17" } }, "sha512-l/BYs/JYt+cXA/0+wUhulYJB6a6p//GTPiJ7nV+QHa8iiId4HZmnu/3J/SowP5g0rTiERY2kfGKXEK5Ehltx4Q=="], 118 + 119 + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], 120 + 121 + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 122 + 123 + "@types/node": ["@types/node@24.0.10", "", { "dependencies": { "undici-types": "~7.8.0" } }, "sha512-ENHwaH+JIRTDIEEbDK6QSQntAYGtbvdDXnMXnZaZ6k13Du1dPMmprkEHIL7ok2Wl2aZevetwTAb5S+7yIF+enA=="], 124 + 125 + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.35.1", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/type-utils": "8.35.1", "@typescript-eslint/utils": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.35.1", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-9XNTlo7P7RJxbVeICaIIIEipqxLKguyh+3UbXuT2XQuFp6d8VOeDEGuz5IiX0dgZo8CiI6aOFLg4e8cF71SFVg=="], 126 + 127 + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.35.1", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/typescript-estree": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-3MyiDfrfLeK06bi/g9DqJxP5pV74LNv4rFTyvGDmT3x2p1yp1lOd+qYZfiRPIOf/oON+WRZR5wxxuF85qOar+w=="], 128 + 129 + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.35.1", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.35.1", "@typescript-eslint/types": "^8.35.1", "debug": "^4.3.4" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-VYxn/5LOpVxADAuP3NrnxxHYfzVtQzLKeldIhDhzC8UHaiQvYlXvKuVho1qLduFbJjjy5U5bkGwa3rUGUb1Q6Q=="], 130 + 131 + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.35.1", "", { "dependencies": { "@typescript-eslint/types": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1" } }, "sha512-s/Bpd4i7ht2934nG+UoSPlYXd08KYz3bmjLEb7Ye1UVob0d1ENiT3lY8bsCmik4RqfSbPw9xJJHbugpPpP5JUg=="], 132 + 133 + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.35.1", "", { "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-K5/U9VmT9dTHoNowWZpz+/TObS3xqC5h0xAIjXPw+MNcKV9qg6eSatEnmeAwkjHijhACH0/N7bkhKvbt1+DXWQ=="], 134 + 135 + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.35.1", "", { "dependencies": { "@typescript-eslint/typescript-estree": "8.35.1", "@typescript-eslint/utils": "8.35.1", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-HOrUBlfVRz5W2LIKpXzZoy6VTZzMu2n8q9C2V/cFngIC5U1nStJgv0tMV4sZPzdf4wQm9/ToWUFPMN9Vq9VJQQ=="], 136 + 137 + "@typescript-eslint/types": ["@typescript-eslint/types@8.35.1", "", {}, "sha512-q/O04vVnKHfrrhNAscndAn1tuQhIkwqnaW+eu5waD5IPts2eX1dgJxgqcPx5BX109/qAz7IG6VrEPTOYKCNfRQ=="], 138 + 139 + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.35.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.35.1", "@typescript-eslint/tsconfig-utils": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/visitor-keys": "8.35.1", "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" }, "peerDependencies": { "typescript": ">=4.8.4 <5.9.0" } }, "sha512-Vvpuvj4tBxIka7cPs6Y1uvM7gJgdF5Uu9F+mBJBPY4MhvjrjWGK4H0lVgLJd/8PWZ23FTqsaJaLEkBCFUk8Y9g=="], 140 + 141 + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.35.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.35.1", "@typescript-eslint/types": "8.35.1", "@typescript-eslint/typescript-estree": "8.35.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-lhnwatFmOFcazAsUm3ZnZFpXSxiwoa1Lj50HphnDe1Et01NF4+hrdXONSUHIcbVu2eFb1bAf+5yjXkGVkXBKAQ=="], 142 + 143 + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.35.1", "", { "dependencies": { "@typescript-eslint/types": "8.35.1", "eslint-visitor-keys": "^4.2.1" } }, "sha512-VRwixir4zBWCSTP/ljEo091lbpypz57PoeAQ9imjG+vbeof9LplljsL1mos4ccG6H9IjfrVGM359RozUnuFhpw=="], 144 + 145 + "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], 146 + 147 + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], 148 + 149 + "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], 150 + 151 + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], 152 + 153 + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], 154 + 155 + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 156 + 157 + "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], 158 + 159 + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], 160 + 161 + "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], 162 + 163 + "bun-types": ["bun-types@1.2.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ElC7ItwT3SCQwYZDYoAH+q6KT4Fxjl8DtZ6qDulUFBmXA8YB4xo+l54J9ZJN+k2pphfn9vk7kfubeSd5QfTVJQ=="], 164 + 165 + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 166 + 167 + "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 168 + 169 + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], 170 + 171 + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 172 + 173 + "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 174 + 175 + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], 176 + 177 + "debug": ["debug@4.4.1", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], 178 + 179 + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 180 + 181 + "drizzle-kit": ["drizzle-kit@0.31.4", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.25.4", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-tCPWVZWZqWVx2XUsVpJRnH9Mx0ClVOf5YUHerZ5so1OKSlqww4zy1R5ksEdGRcO3tM3zj0PYN6V48TbQCL1RfA=="], 182 + 183 + "drizzle-orm": ["drizzle-orm@0.44.2", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-zGAqBzWWkVSFjZpwPOrmCrgO++1kZ5H/rZ4qTGeGOe18iXGVJWf3WPfHOVwFIbmi8kHjfJstC6rJomzGx8g/dQ=="], 184 + 185 + "esbuild": ["esbuild@0.25.5", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.5", "@esbuild/android-arm": "0.25.5", "@esbuild/android-arm64": "0.25.5", "@esbuild/android-x64": "0.25.5", "@esbuild/darwin-arm64": "0.25.5", "@esbuild/darwin-x64": "0.25.5", "@esbuild/freebsd-arm64": "0.25.5", "@esbuild/freebsd-x64": "0.25.5", "@esbuild/linux-arm": "0.25.5", "@esbuild/linux-arm64": "0.25.5", "@esbuild/linux-ia32": "0.25.5", "@esbuild/linux-loong64": "0.25.5", "@esbuild/linux-mips64el": "0.25.5", "@esbuild/linux-ppc64": "0.25.5", "@esbuild/linux-riscv64": "0.25.5", "@esbuild/linux-s390x": "0.25.5", "@esbuild/linux-x64": "0.25.5", "@esbuild/netbsd-arm64": "0.25.5", "@esbuild/netbsd-x64": "0.25.5", "@esbuild/openbsd-arm64": "0.25.5", "@esbuild/openbsd-x64": "0.25.5", "@esbuild/sunos-x64": "0.25.5", "@esbuild/win32-arm64": "0.25.5", "@esbuild/win32-ia32": "0.25.5", "@esbuild/win32-x64": "0.25.5" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ=="], 186 + 187 + "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], 188 + 189 + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], 190 + 191 + "eslint": ["eslint@9.30.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.0", "@eslint/config-helpers": "^0.3.0", "@eslint/core": "^0.14.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.30.1", "@eslint/plugin-kit": "^0.3.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "@types/json-schema": "^7.0.15", "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" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-zmxXPNMOXmwm9E0yQLi5uqXHs7uq2UIiqEKo3Gq+3fwo1XrJ+hijAZImyF7hclW3E6oHz43Yk3RP8at6OTKflQ=="], 192 + 193 + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], 194 + 195 + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], 196 + 197 + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], 198 + 199 + "esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="], 200 + 201 + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], 202 + 203 + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], 204 + 205 + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], 206 + 207 + "event-target-polyfill": ["event-target-polyfill@0.0.4", "", {}, "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="], 208 + 209 + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], 210 + 211 + "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=="], 212 + 213 + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], 214 + 215 + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], 216 + 217 + "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], 218 + 219 + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], 220 + 221 + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], 222 + 223 + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], 224 + 225 + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], 226 + 227 + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], 228 + 229 + "get-tsconfig": ["get-tsconfig@4.10.1", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ=="], 230 + 231 + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 232 + 233 + "globals": ["globals@16.3.0", "", {}, "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ=="], 234 + 235 + "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], 236 + 237 + "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], 238 + 239 + "hono": ["hono@4.8.3", "", {}, "sha512-jYZ6ZtfWjzBdh8H/0CIFfCBHaFL75k+KMzaM177hrWWm2TWL39YMYaJgB74uK/niRc866NMlH9B8uCvIo284WQ=="], 240 + 241 + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], 242 + 243 + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], 244 + 245 + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 246 + 247 + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 248 + 249 + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 250 + 251 + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], 252 + 253 + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], 254 + 255 + "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], 256 + 257 + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], 258 + 259 + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 260 + 261 + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], 262 + 263 + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 264 + 265 + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 266 + 267 + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], 268 + 269 + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], 270 + 271 + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], 272 + 273 + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 274 + 275 + "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 276 + 277 + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], 278 + 279 + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], 280 + 281 + "optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], 282 + 283 + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], 284 + 285 + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], 286 + 287 + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], 288 + 289 + "partysocket": ["partysocket@1.1.4", "", { "dependencies": { "event-target-polyfill": "^0.0.4" } }, "sha512-jXP7PFj2h5/v4UjDS8P7MZy6NJUQ7sspiFyxL4uc/+oKOL+KdtXzHnTV8INPGxBrLTXgalyG3kd12Qm7WrYc3A=="], 290 + 291 + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], 292 + 293 + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], 294 + 295 + "picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 296 + 297 + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], 298 + 299 + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], 300 + 301 + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], 302 + 303 + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], 304 + 305 + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], 306 + 307 + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], 308 + 309 + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], 310 + 311 + "semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], 312 + 313 + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 314 + 315 + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], 316 + 317 + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 318 + 319 + "source-map-support": ["source-map-support@0.5.21", "", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], 320 + 321 + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], 322 + 323 + "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 324 + 325 + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], 326 + 327 + "toml": ["toml@3.0.0", "", {}, "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w=="], 328 + 329 + "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], 330 + 331 + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], 332 + 333 + "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="], 334 + 335 + "typescript-eslint": ["typescript-eslint@8.35.1", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.35.1", "@typescript-eslint/parser": "8.35.1", "@typescript-eslint/utils": "8.35.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <5.9.0" } }, "sha512-xslJjFzhOmHYQzSB/QTeASAHbjmxOGEP6Coh93TXmUBFQoJ1VU35UHIDmG06Jd6taf3wqqC1ntBnCMeymy5Ovw=="], 336 + 337 + "undici-types": ["undici-types@7.8.0", "", {}, "sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw=="], 338 + 339 + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], 340 + 341 + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 342 + 343 + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 344 + 345 + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 346 + 347 + "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], 348 + 349 + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], 350 + 351 + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], 352 + 353 + "@eslint/plugin-kit/@eslint/core": ["@eslint/core@0.15.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA=="], 354 + 355 + "@humanfs/node/@humanwhocodes/retry": ["@humanwhocodes/retry@0.3.1", "", {}, "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA=="], 356 + 357 + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], 358 + 359 + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], 360 + 361 + "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 362 + 363 + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], 364 + 365 + "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.18.20", "", { "os": "android", "cpu": "arm64" }, "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ=="], 366 + 367 + "@esbuild-kit/core-utils/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.18.20", "", { "os": "android", "cpu": "x64" }, "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg=="], 368 + 369 + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.18.20", "", { "os": "darwin", "cpu": "arm64" }, "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA=="], 370 + 371 + "@esbuild-kit/core-utils/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.18.20", "", { "os": "darwin", "cpu": "x64" }, "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ=="], 372 + 373 + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.18.20", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw=="], 374 + 375 + "@esbuild-kit/core-utils/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.18.20", "", { "os": "freebsd", "cpu": "x64" }, "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ=="], 376 + 377 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.18.20", "", { "os": "linux", "cpu": "arm" }, "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg=="], 378 + 379 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.18.20", "", { "os": "linux", "cpu": "arm64" }, "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA=="], 380 + 381 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.18.20", "", { "os": "linux", "cpu": "ia32" }, "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA=="], 382 + 383 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg=="], 384 + 385 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ=="], 386 + 387 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.18.20", "", { "os": "linux", "cpu": "ppc64" }, "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA=="], 388 + 389 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.18.20", "", { "os": "linux", "cpu": "none" }, "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A=="], 390 + 391 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.18.20", "", { "os": "linux", "cpu": "s390x" }, "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ=="], 392 + 393 + "@esbuild-kit/core-utils/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.18.20", "", { "os": "linux", "cpu": "x64" }, "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w=="], 394 + 395 + "@esbuild-kit/core-utils/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.18.20", "", { "os": "none", "cpu": "x64" }, "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A=="], 396 + 397 + "@esbuild-kit/core-utils/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.18.20", "", { "os": "openbsd", "cpu": "x64" }, "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg=="], 398 + 399 + "@esbuild-kit/core-utils/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.18.20", "", { "os": "sunos", "cpu": "x64" }, "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ=="], 400 + 401 + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.18.20", "", { "os": "win32", "cpu": "arm64" }, "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg=="], 402 + 403 + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.18.20", "", { "os": "win32", "cpu": "ia32" }, "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g=="], 404 + 405 + "@esbuild-kit/core-utils/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.18.20", "", { "os": "win32", "cpu": "x64" }, "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ=="], 406 + 407 + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], 408 + } 409 + }
+14
backend/config.example.toml
··· 1 + ## This is a configuration file for Clippr. 2 + ## Please copy to "config.example.toml" before starting the server, otherwise it will not start. 3 + ## Modify as necessary. 4 + 5 + hostname = "localhost" 6 + port = 9090 7 + 8 + ## How the SQLite database is stored. 9 + [database] 10 + name = "clippr.db" 11 + 12 + ## How the server interacts with the ATproto network. 13 + [network] 14 + firehose = "jetstream1.us-east.bsky.network"
-16
backend/config.example.yaml
··· 1 - ## Clippr-BE config 2 - ## If this is not copied to "config.yaml", the server will not launch. 3 - ## Modify what you need! 4 - 5 - ## Configure where the server opens up to. 6 - server: 7 - hostname: localhost 8 - port: 9090 9 - database_name: "clippr.db" 10 - 11 - ## General AT Protocol settings (relay communication for the moment) 12 - network: 13 - firehose_provider: "jetstream1.us-east.bsky.network" 14 - 15 - ## OAuth settings, for authentication 16 - oauth:
+15
backend/drizzle.config.ts
··· 1 + import 'dotenv/config'; 2 + import {defineConfig} from 'drizzle-kit'; 3 + import { Config } from "./src/config"; 4 + 5 + const config = Config.getInstance(); 6 + const dbname = config.get("database.name"); 7 + 8 + export default defineConfig({ 9 + out: './drizzle', 10 + schema: './src/db/schema.ts', 11 + dialect: 'sqlite', 12 + dbCredentials: { 13 + url: dbname, 14 + }, 15 + });
+12
backend/eslint.config.mjs
··· 1 + import js from "@eslint/js"; 2 + import globals from "globals"; 3 + import tseslint from "typescript-eslint"; 4 + import {defineConfig} from "eslint/config"; 5 + 6 + 7 + export default defineConfig([ 8 + {files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], plugins: {js}, extends: ["js/recommended"]}, 9 + {files: ["**/*.{js,mjs,cjs,ts,mts,cts}"], languageOptions: {globals: globals.browser}}, 10 + tseslint.configs.recommended, 11 + tseslint.configs.stylistic 12 + ]);
-7
backend/lib/auth/create_session.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - // Blank for now...
-10
backend/lib/auth/oauth.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - class OAuth { 8 - late final String clientId; 9 - late final String clientName; 10 - }
-53
backend/lib/clip_id/clip_id.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - /// A class that implements the ``ClipID`` system that we use to create valid, de-duplicated record keys for Clips. 8 - /// 9 - /// To provide an example, say we want to convert the link ``https://blog.example.com/~archives/hello-world.html`` into a ClipID. 10 - /// 11 - /// To do this, first we will remove the scheme from the link. If you plan to support non-HTTP schemes such as Gemini, 12 - /// you would precede the hostname with the scheme (Example: ``gemini:blog.example.com``). 13 - /// 14 - /// Separating the hostname from the file path is simple, simply divide the two with a colon 15 - /// (``blog.example.com:/~archives/hello-world.html``). 16 - /// If there is no file path (i.e. the link is an index page on root) make the link path a tilde. 17 - /// 18 - /// We replace the slash separators with tildes. To account for paths with tildes, simply add an underscore before one (``_~archives``). 19 - /// 20 - /// The final ClipID should be `blog.example.com:_~archives~hello-world.html`. 21 - /// This is not a perfect system and could be replaced or modified at any moment when issues arrive, 22 - /// however we believe it is functional for the moment. 23 - class ClipID { 24 - /// The scheme of the ClipID. 25 - String? scheme; 26 - /// The hostname of the ClipID. 27 - String? hostname; 28 - /// The filepath of the ClipID. 29 - String? path; 30 - /// The segments of the filepath. 31 - List<String>? pathSegments; 32 - 33 - ClipID(Uri url) { 34 - scheme = url.scheme; 35 - hostname = url.host; 36 - if (url.hasEmptyPath || url.pathSegments.isEmpty) { 37 - path = "~"; 38 - pathSegments = ["~"]; 39 - } else { 40 - path = url.path; 41 - path = path?.replaceAll("~", "_~"); 42 - path = path?.replaceFirst("/", ""); 43 - path = path?.replaceAll("/", "~"); 44 - pathSegments = path?.split(RegExp(r"(?<!_)~")); 45 - } 46 - } 47 - 48 - /// Prints out the full ClipID. 49 - @override 50 - String toString() { 51 - return "$scheme:$hostname:$path"; 52 - } 53 - }
-46
backend/lib/config/config.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'dart:io'; 8 - import 'package:clippr/server/logger.dart' show Logger; 9 - import 'package:yaml/yaml.dart'; 10 - 11 - class Config { 12 - static Map? yamlDoc; 13 - 14 - Config() { 15 - File file = File('config.yaml'); 16 - if (file.existsSync()) { 17 - yamlDoc = loadYaml(file.readAsStringSync()) as Map; 18 - return; 19 - } 20 - 21 - file = File('config.yml'); 22 - if (file.existsSync()) { 23 - yamlDoc = loadYaml(file.readAsStringSync()) as Map; 24 - return; 25 - } 26 - 27 - Logger.logSevere("Failed to read config.yaml"); 28 - exit(1); 29 - } 30 - 31 - static int getPort() { 32 - return yamlDoc?['server']['port']; 33 - } 34 - 35 - static String getHostname() { 36 - return yamlDoc?['server']['hostname']; 37 - } 38 - 39 - static String getDatabaseName() { 40 - return yamlDoc?['server']['database_name']; 41 - } 42 - 43 - static String getFirehoseProvider() { 44 - return yamlDoc?['network']['firehose_provider']; 45 - } 46 - }
-26
backend/lib/config/pubspec.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'dart:io'; 8 - 9 - import 'package:pubspec_parse/pubspec_parse.dart'; 10 - 11 - class ClipprPubspec { 12 - static late Pubspec pubspec; 13 - 14 - ClipprPubspec() { 15 - final pubspecFile = File("pubspec.yaml").readAsStringSync(); 16 - pubspec = Pubspec.parse(pubspecFile); 17 - } 18 - 19 - static String getVersion() { 20 - return pubspec.version.toString(); 21 - } 22 - 23 - static String getName() { 24 - return pubspec.name; 25 - } 26 - }
-89
backend/lib/db/database.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'dart:convert'; 8 - import 'dart:io'; 9 - 10 - import 'package:atproto/atproto.dart'; 11 - import 'package:clippr/config/config.dart'; 12 - import 'package:drift/drift.dart'; 13 - import 'package:drift/native.dart'; 14 - 15 - part 'database.g.dart'; 16 - 17 - class Clips extends Table { 18 - DateTimeColumn get timestamp => 19 - dateTime().named("time_us").withDefault(currentDateAndTime)(); 20 - TextColumn get did => text()(); 21 - TextColumn get recordKey => text().named("rkey")(); 22 - TextColumn get url => text()(); 23 - TextColumn get title => text()(); 24 - TextColumn get description => text()(); 25 - TextColumn get notes => text().nullable()(); 26 - TextColumn get tags => text().map(const StrongRefConverter()).nullable()(); 27 - BoolColumn get unlisted => boolean()(); 28 - BoolColumn get unread => boolean().nullable()(); 29 - TextColumn get languages => 30 - text().map(const StringArrayConverter()).nullable()(); 31 - DateTimeColumn get createdAt => dateTime()(); 32 - @override 33 - Set<Column<Object>> get primaryKey => {timestamp}; 34 - } 35 - 36 - class Tags extends Table { 37 - DateTimeColumn get timestamp => 38 - dateTime().named("time_us").withDefault(currentDateAndTime)(); 39 - TextColumn get did => text()(); 40 - TextColumn get recordKey => text().named('rkey')(); 41 - TextColumn get name => text()(); 42 - TextColumn get color => text().nullable()(); 43 - DateTimeColumn get createdAt => dateTime()(); 44 - @override 45 - Set<Column<Object>> get primaryKey => {timestamp}; 46 - } 47 - 48 - @DriftDatabase(tables: [Clips]) 49 - class AppDatabase extends _$AppDatabase { 50 - AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection()); 51 - 52 - @override 53 - int get schemaVersion => 1; 54 - 55 - static QueryExecutor _openConnection() { 56 - return NativeDatabase.createInBackground(File(Config.getDatabaseName())); 57 - } 58 - } 59 - 60 - /// Convert an array of strings to and from JSON for Drift. 61 - class StringArrayConverter extends TypeConverter<List<String>, String> { 62 - const StringArrayConverter(); 63 - 64 - @override 65 - List<String> fromSql(String fromDb) { 66 - return (jsonDecode(fromDb) as List<dynamic>).cast<String>(); 67 - } 68 - 69 - @override 70 - String toSql(List<String> value) { 71 - return jsonEncode(value); 72 - } 73 - } 74 - 75 - /// Convert [StrongRef] to and from JSON for Drift. 76 - class StrongRefConverter extends TypeConverter<StrongRef, String> { 77 - const StrongRefConverter(); 78 - 79 - @override 80 - StrongRef fromSql(String fromDb) { 81 - final map = jsonDecode(fromDb); 82 - return StrongRef.fromJson(map); 83 - } 84 - 85 - @override 86 - String toSql(StrongRef value) { 87 - return jsonEncode(value.toJson()); 88 - } 89 - }
-1065
backend/lib/db/database.g.dart
··· 1 - // GENERATED CODE - DO NOT MODIFY BY HAND 2 - 3 - part of 'database.dart'; 4 - 5 - // ignore_for_file: type=lint 6 - class $ClipsTable extends Clips with TableInfo<$ClipsTable, Clip> { 7 - @override 8 - final GeneratedDatabase attachedDatabase; 9 - final String? _alias; 10 - $ClipsTable(this.attachedDatabase, [this._alias]); 11 - static const VerificationMeta _timestampMeta = const VerificationMeta( 12 - 'timestamp', 13 - ); 14 - @override 15 - late final GeneratedColumn<DateTime> timestamp = GeneratedColumn<DateTime>( 16 - 'time_us', 17 - aliasedName, 18 - false, 19 - type: DriftSqlType.dateTime, 20 - requiredDuringInsert: false, 21 - defaultValue: currentDateAndTime, 22 - ); 23 - static const VerificationMeta _didMeta = const VerificationMeta('did'); 24 - @override 25 - late final GeneratedColumn<String> did = GeneratedColumn<String>( 26 - 'did', 27 - aliasedName, 28 - false, 29 - type: DriftSqlType.string, 30 - requiredDuringInsert: true, 31 - ); 32 - static const VerificationMeta _recordKeyMeta = const VerificationMeta( 33 - 'recordKey', 34 - ); 35 - @override 36 - late final GeneratedColumn<String> recordKey = GeneratedColumn<String>( 37 - 'rkey', 38 - aliasedName, 39 - false, 40 - type: DriftSqlType.string, 41 - requiredDuringInsert: true, 42 - ); 43 - static const VerificationMeta _urlMeta = const VerificationMeta('url'); 44 - @override 45 - late final GeneratedColumn<String> url = GeneratedColumn<String>( 46 - 'url', 47 - aliasedName, 48 - false, 49 - type: DriftSqlType.string, 50 - requiredDuringInsert: true, 51 - ); 52 - static const VerificationMeta _titleMeta = const VerificationMeta('title'); 53 - @override 54 - late final GeneratedColumn<String> title = GeneratedColumn<String>( 55 - 'title', 56 - aliasedName, 57 - false, 58 - type: DriftSqlType.string, 59 - requiredDuringInsert: true, 60 - ); 61 - static const VerificationMeta _descriptionMeta = const VerificationMeta( 62 - 'description', 63 - ); 64 - @override 65 - late final GeneratedColumn<String> description = GeneratedColumn<String>( 66 - 'description', 67 - aliasedName, 68 - false, 69 - type: DriftSqlType.string, 70 - requiredDuringInsert: true, 71 - ); 72 - static const VerificationMeta _notesMeta = const VerificationMeta('notes'); 73 - @override 74 - late final GeneratedColumn<String> notes = GeneratedColumn<String>( 75 - 'notes', 76 - aliasedName, 77 - true, 78 - type: DriftSqlType.string, 79 - requiredDuringInsert: false, 80 - ); 81 - @override 82 - late final GeneratedColumnWithTypeConverter<StrongRef?, String> tags = 83 - GeneratedColumn<String>( 84 - 'tags', 85 - aliasedName, 86 - true, 87 - type: DriftSqlType.string, 88 - requiredDuringInsert: false, 89 - ).withConverter<StrongRef?>($ClipsTable.$convertertagsn); 90 - static const VerificationMeta _unlistedMeta = const VerificationMeta( 91 - 'unlisted', 92 - ); 93 - @override 94 - late final GeneratedColumn<bool> unlisted = GeneratedColumn<bool>( 95 - 'unlisted', 96 - aliasedName, 97 - false, 98 - type: DriftSqlType.bool, 99 - requiredDuringInsert: true, 100 - defaultConstraints: GeneratedColumn.constraintIsAlways( 101 - 'CHECK ("unlisted" IN (0, 1))', 102 - ), 103 - ); 104 - static const VerificationMeta _unreadMeta = const VerificationMeta('unread'); 105 - @override 106 - late final GeneratedColumn<bool> unread = GeneratedColumn<bool>( 107 - 'unread', 108 - aliasedName, 109 - true, 110 - type: DriftSqlType.bool, 111 - requiredDuringInsert: false, 112 - defaultConstraints: GeneratedColumn.constraintIsAlways( 113 - 'CHECK ("unread" IN (0, 1))', 114 - ), 115 - ); 116 - @override 117 - late final GeneratedColumnWithTypeConverter<List<String>?, String> languages = 118 - GeneratedColumn<String>( 119 - 'languages', 120 - aliasedName, 121 - true, 122 - type: DriftSqlType.string, 123 - requiredDuringInsert: false, 124 - ).withConverter<List<String>?>($ClipsTable.$converterlanguagesn); 125 - static const VerificationMeta _createdAtMeta = const VerificationMeta( 126 - 'createdAt', 127 - ); 128 - @override 129 - late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>( 130 - 'created_at', 131 - aliasedName, 132 - false, 133 - type: DriftSqlType.dateTime, 134 - requiredDuringInsert: true, 135 - ); 136 - @override 137 - List<GeneratedColumn> get $columns => [ 138 - timestamp, 139 - did, 140 - recordKey, 141 - url, 142 - title, 143 - description, 144 - notes, 145 - tags, 146 - unlisted, 147 - unread, 148 - languages, 149 - createdAt, 150 - ]; 151 - @override 152 - String get aliasedName => _alias ?? actualTableName; 153 - @override 154 - String get actualTableName => $name; 155 - static const String $name = 'clips'; 156 - @override 157 - VerificationContext validateIntegrity( 158 - Insertable<Clip> instance, { 159 - bool isInserting = false, 160 - }) { 161 - final context = VerificationContext(); 162 - final data = instance.toColumns(true); 163 - if (data.containsKey('time_us')) { 164 - context.handle( 165 - _timestampMeta, 166 - timestamp.isAcceptableOrUnknown(data['time_us']!, _timestampMeta), 167 - ); 168 - } 169 - if (data.containsKey('did')) { 170 - context.handle( 171 - _didMeta, 172 - did.isAcceptableOrUnknown(data['did']!, _didMeta), 173 - ); 174 - } else if (isInserting) { 175 - context.missing(_didMeta); 176 - } 177 - if (data.containsKey('rkey')) { 178 - context.handle( 179 - _recordKeyMeta, 180 - recordKey.isAcceptableOrUnknown(data['rkey']!, _recordKeyMeta), 181 - ); 182 - } else if (isInserting) { 183 - context.missing(_recordKeyMeta); 184 - } 185 - if (data.containsKey('url')) { 186 - context.handle( 187 - _urlMeta, 188 - url.isAcceptableOrUnknown(data['url']!, _urlMeta), 189 - ); 190 - } else if (isInserting) { 191 - context.missing(_urlMeta); 192 - } 193 - if (data.containsKey('title')) { 194 - context.handle( 195 - _titleMeta, 196 - title.isAcceptableOrUnknown(data['title']!, _titleMeta), 197 - ); 198 - } else if (isInserting) { 199 - context.missing(_titleMeta); 200 - } 201 - if (data.containsKey('description')) { 202 - context.handle( 203 - _descriptionMeta, 204 - description.isAcceptableOrUnknown( 205 - data['description']!, 206 - _descriptionMeta, 207 - ), 208 - ); 209 - } else if (isInserting) { 210 - context.missing(_descriptionMeta); 211 - } 212 - if (data.containsKey('notes')) { 213 - context.handle( 214 - _notesMeta, 215 - notes.isAcceptableOrUnknown(data['notes']!, _notesMeta), 216 - ); 217 - } 218 - if (data.containsKey('unlisted')) { 219 - context.handle( 220 - _unlistedMeta, 221 - unlisted.isAcceptableOrUnknown(data['unlisted']!, _unlistedMeta), 222 - ); 223 - } else if (isInserting) { 224 - context.missing(_unlistedMeta); 225 - } 226 - if (data.containsKey('unread')) { 227 - context.handle( 228 - _unreadMeta, 229 - unread.isAcceptableOrUnknown(data['unread']!, _unreadMeta), 230 - ); 231 - } 232 - if (data.containsKey('created_at')) { 233 - context.handle( 234 - _createdAtMeta, 235 - createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta), 236 - ); 237 - } else if (isInserting) { 238 - context.missing(_createdAtMeta); 239 - } 240 - return context; 241 - } 242 - 243 - @override 244 - Set<GeneratedColumn> get $primaryKey => {timestamp}; 245 - @override 246 - Clip map(Map<String, dynamic> data, {String? tablePrefix}) { 247 - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; 248 - return Clip( 249 - timestamp: attachedDatabase.typeMapping.read( 250 - DriftSqlType.dateTime, 251 - data['${effectivePrefix}time_us'], 252 - )!, 253 - did: attachedDatabase.typeMapping.read( 254 - DriftSqlType.string, 255 - data['${effectivePrefix}did'], 256 - )!, 257 - recordKey: attachedDatabase.typeMapping.read( 258 - DriftSqlType.string, 259 - data['${effectivePrefix}rkey'], 260 - )!, 261 - url: attachedDatabase.typeMapping.read( 262 - DriftSqlType.string, 263 - data['${effectivePrefix}url'], 264 - )!, 265 - title: attachedDatabase.typeMapping.read( 266 - DriftSqlType.string, 267 - data['${effectivePrefix}title'], 268 - )!, 269 - description: attachedDatabase.typeMapping.read( 270 - DriftSqlType.string, 271 - data['${effectivePrefix}description'], 272 - )!, 273 - notes: attachedDatabase.typeMapping.read( 274 - DriftSqlType.string, 275 - data['${effectivePrefix}notes'], 276 - ), 277 - tags: $ClipsTable.$convertertagsn.fromSql( 278 - attachedDatabase.typeMapping.read( 279 - DriftSqlType.string, 280 - data['${effectivePrefix}tags'], 281 - ), 282 - ), 283 - unlisted: attachedDatabase.typeMapping.read( 284 - DriftSqlType.bool, 285 - data['${effectivePrefix}unlisted'], 286 - )!, 287 - unread: attachedDatabase.typeMapping.read( 288 - DriftSqlType.bool, 289 - data['${effectivePrefix}unread'], 290 - ), 291 - languages: $ClipsTable.$converterlanguagesn.fromSql( 292 - attachedDatabase.typeMapping.read( 293 - DriftSqlType.string, 294 - data['${effectivePrefix}languages'], 295 - ), 296 - ), 297 - createdAt: attachedDatabase.typeMapping.read( 298 - DriftSqlType.dateTime, 299 - data['${effectivePrefix}created_at'], 300 - )!, 301 - ); 302 - } 303 - 304 - @override 305 - $ClipsTable createAlias(String alias) { 306 - return $ClipsTable(attachedDatabase, alias); 307 - } 308 - 309 - static TypeConverter<StrongRef, String> $convertertags = 310 - const StrongRefConverter(); 311 - static TypeConverter<StrongRef?, String?> $convertertagsn = 312 - NullAwareTypeConverter.wrap($convertertags); 313 - static TypeConverter<List<String>, String> $converterlanguages = 314 - const StringArrayConverter(); 315 - static TypeConverter<List<String>?, String?> $converterlanguagesn = 316 - NullAwareTypeConverter.wrap($converterlanguages); 317 - } 318 - 319 - class Clip extends DataClass implements Insertable<Clip> { 320 - final DateTime timestamp; 321 - final String did; 322 - final String recordKey; 323 - final String url; 324 - final String title; 325 - final String description; 326 - final String? notes; 327 - final StrongRef? tags; 328 - final bool unlisted; 329 - final bool? unread; 330 - final List<String>? languages; 331 - final DateTime createdAt; 332 - const Clip({ 333 - required this.timestamp, 334 - required this.did, 335 - required this.recordKey, 336 - required this.url, 337 - required this.title, 338 - required this.description, 339 - this.notes, 340 - this.tags, 341 - required this.unlisted, 342 - this.unread, 343 - this.languages, 344 - required this.createdAt, 345 - }); 346 - @override 347 - Map<String, Expression> toColumns(bool nullToAbsent) { 348 - final map = <String, Expression>{}; 349 - map['time_us'] = Variable<DateTime>(timestamp); 350 - map['did'] = Variable<String>(did); 351 - map['rkey'] = Variable<String>(recordKey); 352 - map['url'] = Variable<String>(url); 353 - map['title'] = Variable<String>(title); 354 - map['description'] = Variable<String>(description); 355 - if (!nullToAbsent || notes != null) { 356 - map['notes'] = Variable<String>(notes); 357 - } 358 - if (!nullToAbsent || tags != null) { 359 - map['tags'] = Variable<String>($ClipsTable.$convertertagsn.toSql(tags)); 360 - } 361 - map['unlisted'] = Variable<bool>(unlisted); 362 - if (!nullToAbsent || unread != null) { 363 - map['unread'] = Variable<bool>(unread); 364 - } 365 - if (!nullToAbsent || languages != null) { 366 - map['languages'] = Variable<String>( 367 - $ClipsTable.$converterlanguagesn.toSql(languages), 368 - ); 369 - } 370 - map['created_at'] = Variable<DateTime>(createdAt); 371 - return map; 372 - } 373 - 374 - ClipsCompanion toCompanion(bool nullToAbsent) { 375 - return ClipsCompanion( 376 - timestamp: Value(timestamp), 377 - did: Value(did), 378 - recordKey: Value(recordKey), 379 - url: Value(url), 380 - title: Value(title), 381 - description: Value(description), 382 - notes: notes == null && nullToAbsent 383 - ? const Value.absent() 384 - : Value(notes), 385 - tags: tags == null && nullToAbsent ? const Value.absent() : Value(tags), 386 - unlisted: Value(unlisted), 387 - unread: unread == null && nullToAbsent 388 - ? const Value.absent() 389 - : Value(unread), 390 - languages: languages == null && nullToAbsent 391 - ? const Value.absent() 392 - : Value(languages), 393 - createdAt: Value(createdAt), 394 - ); 395 - } 396 - 397 - factory Clip.fromJson( 398 - Map<String, dynamic> json, { 399 - ValueSerializer? serializer, 400 - }) { 401 - serializer ??= driftRuntimeOptions.defaultSerializer; 402 - return Clip( 403 - timestamp: serializer.fromJson<DateTime>(json['timestamp']), 404 - did: serializer.fromJson<String>(json['did']), 405 - recordKey: serializer.fromJson<String>(json['recordKey']), 406 - url: serializer.fromJson<String>(json['url']), 407 - title: serializer.fromJson<String>(json['title']), 408 - description: serializer.fromJson<String>(json['description']), 409 - notes: serializer.fromJson<String?>(json['notes']), 410 - tags: serializer.fromJson<StrongRef?>(json['tags']), 411 - unlisted: serializer.fromJson<bool>(json['unlisted']), 412 - unread: serializer.fromJson<bool?>(json['unread']), 413 - languages: serializer.fromJson<List<String>?>(json['languages']), 414 - createdAt: serializer.fromJson<DateTime>(json['createdAt']), 415 - ); 416 - } 417 - @override 418 - Map<String, dynamic> toJson({ValueSerializer? serializer}) { 419 - serializer ??= driftRuntimeOptions.defaultSerializer; 420 - return <String, dynamic>{ 421 - 'timestamp': serializer.toJson<DateTime>(timestamp), 422 - 'did': serializer.toJson<String>(did), 423 - 'recordKey': serializer.toJson<String>(recordKey), 424 - 'url': serializer.toJson<String>(url), 425 - 'title': serializer.toJson<String>(title), 426 - 'description': serializer.toJson<String>(description), 427 - 'notes': serializer.toJson<String?>(notes), 428 - 'tags': serializer.toJson<StrongRef?>(tags), 429 - 'unlisted': serializer.toJson<bool>(unlisted), 430 - 'unread': serializer.toJson<bool?>(unread), 431 - 'languages': serializer.toJson<List<String>?>(languages), 432 - 'createdAt': serializer.toJson<DateTime>(createdAt), 433 - }; 434 - } 435 - 436 - Clip copyWith({ 437 - DateTime? timestamp, 438 - String? did, 439 - String? recordKey, 440 - String? url, 441 - String? title, 442 - String? description, 443 - Value<String?> notes = const Value.absent(), 444 - Value<StrongRef?> tags = const Value.absent(), 445 - bool? unlisted, 446 - Value<bool?> unread = const Value.absent(), 447 - Value<List<String>?> languages = const Value.absent(), 448 - DateTime? createdAt, 449 - }) => Clip( 450 - timestamp: timestamp ?? this.timestamp, 451 - did: did ?? this.did, 452 - recordKey: recordKey ?? this.recordKey, 453 - url: url ?? this.url, 454 - title: title ?? this.title, 455 - description: description ?? this.description, 456 - notes: notes.present ? notes.value : this.notes, 457 - tags: tags.present ? tags.value : this.tags, 458 - unlisted: unlisted ?? this.unlisted, 459 - unread: unread.present ? unread.value : this.unread, 460 - languages: languages.present ? languages.value : this.languages, 461 - createdAt: createdAt ?? this.createdAt, 462 - ); 463 - Clip copyWithCompanion(ClipsCompanion data) { 464 - return Clip( 465 - timestamp: data.timestamp.present ? data.timestamp.value : this.timestamp, 466 - did: data.did.present ? data.did.value : this.did, 467 - recordKey: data.recordKey.present ? data.recordKey.value : this.recordKey, 468 - url: data.url.present ? data.url.value : this.url, 469 - title: data.title.present ? data.title.value : this.title, 470 - description: data.description.present 471 - ? data.description.value 472 - : this.description, 473 - notes: data.notes.present ? data.notes.value : this.notes, 474 - tags: data.tags.present ? data.tags.value : this.tags, 475 - unlisted: data.unlisted.present ? data.unlisted.value : this.unlisted, 476 - unread: data.unread.present ? data.unread.value : this.unread, 477 - languages: data.languages.present ? data.languages.value : this.languages, 478 - createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, 479 - ); 480 - } 481 - 482 - @override 483 - String toString() { 484 - return (StringBuffer('Clip(') 485 - ..write('timestamp: $timestamp, ') 486 - ..write('did: $did, ') 487 - ..write('recordKey: $recordKey, ') 488 - ..write('url: $url, ') 489 - ..write('title: $title, ') 490 - ..write('description: $description, ') 491 - ..write('notes: $notes, ') 492 - ..write('tags: $tags, ') 493 - ..write('unlisted: $unlisted, ') 494 - ..write('unread: $unread, ') 495 - ..write('languages: $languages, ') 496 - ..write('createdAt: $createdAt') 497 - ..write(')')) 498 - .toString(); 499 - } 500 - 501 - @override 502 - int get hashCode => Object.hash( 503 - timestamp, 504 - did, 505 - recordKey, 506 - url, 507 - title, 508 - description, 509 - notes, 510 - tags, 511 - unlisted, 512 - unread, 513 - languages, 514 - createdAt, 515 - ); 516 - @override 517 - bool operator ==(Object other) => 518 - identical(this, other) || 519 - (other is Clip && 520 - other.timestamp == this.timestamp && 521 - other.did == this.did && 522 - other.recordKey == this.recordKey && 523 - other.url == this.url && 524 - other.title == this.title && 525 - other.description == this.description && 526 - other.notes == this.notes && 527 - other.tags == this.tags && 528 - other.unlisted == this.unlisted && 529 - other.unread == this.unread && 530 - other.languages == this.languages && 531 - other.createdAt == this.createdAt); 532 - } 533 - 534 - class ClipsCompanion extends UpdateCompanion<Clip> { 535 - final Value<DateTime> timestamp; 536 - final Value<String> did; 537 - final Value<String> recordKey; 538 - final Value<String> url; 539 - final Value<String> title; 540 - final Value<String> description; 541 - final Value<String?> notes; 542 - final Value<StrongRef?> tags; 543 - final Value<bool> unlisted; 544 - final Value<bool?> unread; 545 - final Value<List<String>?> languages; 546 - final Value<DateTime> createdAt; 547 - final Value<int> rowid; 548 - const ClipsCompanion({ 549 - this.timestamp = const Value.absent(), 550 - this.did = const Value.absent(), 551 - this.recordKey = const Value.absent(), 552 - this.url = const Value.absent(), 553 - this.title = const Value.absent(), 554 - this.description = const Value.absent(), 555 - this.notes = const Value.absent(), 556 - this.tags = const Value.absent(), 557 - this.unlisted = const Value.absent(), 558 - this.unread = const Value.absent(), 559 - this.languages = const Value.absent(), 560 - this.createdAt = const Value.absent(), 561 - this.rowid = const Value.absent(), 562 - }); 563 - ClipsCompanion.insert({ 564 - this.timestamp = const Value.absent(), 565 - required String did, 566 - required String recordKey, 567 - required String url, 568 - required String title, 569 - required String description, 570 - this.notes = const Value.absent(), 571 - this.tags = const Value.absent(), 572 - required bool unlisted, 573 - this.unread = const Value.absent(), 574 - this.languages = const Value.absent(), 575 - required DateTime createdAt, 576 - this.rowid = const Value.absent(), 577 - }) : did = Value(did), 578 - recordKey = Value(recordKey), 579 - url = Value(url), 580 - title = Value(title), 581 - description = Value(description), 582 - unlisted = Value(unlisted), 583 - createdAt = Value(createdAt); 584 - static Insertable<Clip> custom({ 585 - Expression<DateTime>? timestamp, 586 - Expression<String>? did, 587 - Expression<String>? recordKey, 588 - Expression<String>? url, 589 - Expression<String>? title, 590 - Expression<String>? description, 591 - Expression<String>? notes, 592 - Expression<String>? tags, 593 - Expression<bool>? unlisted, 594 - Expression<bool>? unread, 595 - Expression<String>? languages, 596 - Expression<DateTime>? createdAt, 597 - Expression<int>? rowid, 598 - }) { 599 - return RawValuesInsertable({ 600 - if (timestamp != null) 'time_us': timestamp, 601 - if (did != null) 'did': did, 602 - if (recordKey != null) 'rkey': recordKey, 603 - if (url != null) 'url': url, 604 - if (title != null) 'title': title, 605 - if (description != null) 'description': description, 606 - if (notes != null) 'notes': notes, 607 - if (tags != null) 'tags': tags, 608 - if (unlisted != null) 'unlisted': unlisted, 609 - if (unread != null) 'unread': unread, 610 - if (languages != null) 'languages': languages, 611 - if (createdAt != null) 'created_at': createdAt, 612 - if (rowid != null) 'rowid': rowid, 613 - }); 614 - } 615 - 616 - ClipsCompanion copyWith({ 617 - Value<DateTime>? timestamp, 618 - Value<String>? did, 619 - Value<String>? recordKey, 620 - Value<String>? url, 621 - Value<String>? title, 622 - Value<String>? description, 623 - Value<String?>? notes, 624 - Value<StrongRef?>? tags, 625 - Value<bool>? unlisted, 626 - Value<bool?>? unread, 627 - Value<List<String>?>? languages, 628 - Value<DateTime>? createdAt, 629 - Value<int>? rowid, 630 - }) { 631 - return ClipsCompanion( 632 - timestamp: timestamp ?? this.timestamp, 633 - did: did ?? this.did, 634 - recordKey: recordKey ?? this.recordKey, 635 - url: url ?? this.url, 636 - title: title ?? this.title, 637 - description: description ?? this.description, 638 - notes: notes ?? this.notes, 639 - tags: tags ?? this.tags, 640 - unlisted: unlisted ?? this.unlisted, 641 - unread: unread ?? this.unread, 642 - languages: languages ?? this.languages, 643 - createdAt: createdAt ?? this.createdAt, 644 - rowid: rowid ?? this.rowid, 645 - ); 646 - } 647 - 648 - @override 649 - Map<String, Expression> toColumns(bool nullToAbsent) { 650 - final map = <String, Expression>{}; 651 - if (timestamp.present) { 652 - map['time_us'] = Variable<DateTime>(timestamp.value); 653 - } 654 - if (did.present) { 655 - map['did'] = Variable<String>(did.value); 656 - } 657 - if (recordKey.present) { 658 - map['rkey'] = Variable<String>(recordKey.value); 659 - } 660 - if (url.present) { 661 - map['url'] = Variable<String>(url.value); 662 - } 663 - if (title.present) { 664 - map['title'] = Variable<String>(title.value); 665 - } 666 - if (description.present) { 667 - map['description'] = Variable<String>(description.value); 668 - } 669 - if (notes.present) { 670 - map['notes'] = Variable<String>(notes.value); 671 - } 672 - if (tags.present) { 673 - map['tags'] = Variable<String>( 674 - $ClipsTable.$convertertagsn.toSql(tags.value), 675 - ); 676 - } 677 - if (unlisted.present) { 678 - map['unlisted'] = Variable<bool>(unlisted.value); 679 - } 680 - if (unread.present) { 681 - map['unread'] = Variable<bool>(unread.value); 682 - } 683 - if (languages.present) { 684 - map['languages'] = Variable<String>( 685 - $ClipsTable.$converterlanguagesn.toSql(languages.value), 686 - ); 687 - } 688 - if (createdAt.present) { 689 - map['created_at'] = Variable<DateTime>(createdAt.value); 690 - } 691 - if (rowid.present) { 692 - map['rowid'] = Variable<int>(rowid.value); 693 - } 694 - return map; 695 - } 696 - 697 - @override 698 - String toString() { 699 - return (StringBuffer('ClipsCompanion(') 700 - ..write('timestamp: $timestamp, ') 701 - ..write('did: $did, ') 702 - ..write('recordKey: $recordKey, ') 703 - ..write('url: $url, ') 704 - ..write('title: $title, ') 705 - ..write('description: $description, ') 706 - ..write('notes: $notes, ') 707 - ..write('tags: $tags, ') 708 - ..write('unlisted: $unlisted, ') 709 - ..write('unread: $unread, ') 710 - ..write('languages: $languages, ') 711 - ..write('createdAt: $createdAt, ') 712 - ..write('rowid: $rowid') 713 - ..write(')')) 714 - .toString(); 715 - } 716 - } 717 - 718 - abstract class _$AppDatabase extends GeneratedDatabase { 719 - _$AppDatabase(QueryExecutor e) : super(e); 720 - $AppDatabaseManager get managers => $AppDatabaseManager(this); 721 - late final $ClipsTable clips = $ClipsTable(this); 722 - @override 723 - Iterable<TableInfo<Table, Object?>> get allTables => 724 - allSchemaEntities.whereType<TableInfo<Table, Object?>>(); 725 - @override 726 - List<DatabaseSchemaEntity> get allSchemaEntities => [clips]; 727 - } 728 - 729 - typedef $$ClipsTableCreateCompanionBuilder = 730 - ClipsCompanion Function({ 731 - Value<DateTime> timestamp, 732 - required String did, 733 - required String recordKey, 734 - required String url, 735 - required String title, 736 - required String description, 737 - Value<String?> notes, 738 - Value<StrongRef?> tags, 739 - required bool unlisted, 740 - Value<bool?> unread, 741 - Value<List<String>?> languages, 742 - required DateTime createdAt, 743 - Value<int> rowid, 744 - }); 745 - typedef $$ClipsTableUpdateCompanionBuilder = 746 - ClipsCompanion Function({ 747 - Value<DateTime> timestamp, 748 - Value<String> did, 749 - Value<String> recordKey, 750 - Value<String> url, 751 - Value<String> title, 752 - Value<String> description, 753 - Value<String?> notes, 754 - Value<StrongRef?> tags, 755 - Value<bool> unlisted, 756 - Value<bool?> unread, 757 - Value<List<String>?> languages, 758 - Value<DateTime> createdAt, 759 - Value<int> rowid, 760 - }); 761 - 762 - class $$ClipsTableFilterComposer extends Composer<_$AppDatabase, $ClipsTable> { 763 - $$ClipsTableFilterComposer({ 764 - required super.$db, 765 - required super.$table, 766 - super.joinBuilder, 767 - super.$addJoinBuilderToRootComposer, 768 - super.$removeJoinBuilderFromRootComposer, 769 - }); 770 - ColumnFilters<DateTime> get timestamp => $composableBuilder( 771 - column: $table.timestamp, 772 - builder: (column) => ColumnFilters(column), 773 - ); 774 - 775 - ColumnFilters<String> get did => $composableBuilder( 776 - column: $table.did, 777 - builder: (column) => ColumnFilters(column), 778 - ); 779 - 780 - ColumnFilters<String> get recordKey => $composableBuilder( 781 - column: $table.recordKey, 782 - builder: (column) => ColumnFilters(column), 783 - ); 784 - 785 - ColumnFilters<String> get url => $composableBuilder( 786 - column: $table.url, 787 - builder: (column) => ColumnFilters(column), 788 - ); 789 - 790 - ColumnFilters<String> get title => $composableBuilder( 791 - column: $table.title, 792 - builder: (column) => ColumnFilters(column), 793 - ); 794 - 795 - ColumnFilters<String> get description => $composableBuilder( 796 - column: $table.description, 797 - builder: (column) => ColumnFilters(column), 798 - ); 799 - 800 - ColumnFilters<String> get notes => $composableBuilder( 801 - column: $table.notes, 802 - builder: (column) => ColumnFilters(column), 803 - ); 804 - 805 - ColumnWithTypeConverterFilters<StrongRef?, StrongRef, String> get tags => 806 - $composableBuilder( 807 - column: $table.tags, 808 - builder: (column) => ColumnWithTypeConverterFilters(column), 809 - ); 810 - 811 - ColumnFilters<bool> get unlisted => $composableBuilder( 812 - column: $table.unlisted, 813 - builder: (column) => ColumnFilters(column), 814 - ); 815 - 816 - ColumnFilters<bool> get unread => $composableBuilder( 817 - column: $table.unread, 818 - builder: (column) => ColumnFilters(column), 819 - ); 820 - 821 - ColumnWithTypeConverterFilters<List<String>?, List<String>, String> 822 - get languages => $composableBuilder( 823 - column: $table.languages, 824 - builder: (column) => ColumnWithTypeConverterFilters(column), 825 - ); 826 - 827 - ColumnFilters<DateTime> get createdAt => $composableBuilder( 828 - column: $table.createdAt, 829 - builder: (column) => ColumnFilters(column), 830 - ); 831 - } 832 - 833 - class $$ClipsTableOrderingComposer 834 - extends Composer<_$AppDatabase, $ClipsTable> { 835 - $$ClipsTableOrderingComposer({ 836 - required super.$db, 837 - required super.$table, 838 - super.joinBuilder, 839 - super.$addJoinBuilderToRootComposer, 840 - super.$removeJoinBuilderFromRootComposer, 841 - }); 842 - ColumnOrderings<DateTime> get timestamp => $composableBuilder( 843 - column: $table.timestamp, 844 - builder: (column) => ColumnOrderings(column), 845 - ); 846 - 847 - ColumnOrderings<String> get did => $composableBuilder( 848 - column: $table.did, 849 - builder: (column) => ColumnOrderings(column), 850 - ); 851 - 852 - ColumnOrderings<String> get recordKey => $composableBuilder( 853 - column: $table.recordKey, 854 - builder: (column) => ColumnOrderings(column), 855 - ); 856 - 857 - ColumnOrderings<String> get url => $composableBuilder( 858 - column: $table.url, 859 - builder: (column) => ColumnOrderings(column), 860 - ); 861 - 862 - ColumnOrderings<String> get title => $composableBuilder( 863 - column: $table.title, 864 - builder: (column) => ColumnOrderings(column), 865 - ); 866 - 867 - ColumnOrderings<String> get description => $composableBuilder( 868 - column: $table.description, 869 - builder: (column) => ColumnOrderings(column), 870 - ); 871 - 872 - ColumnOrderings<String> get notes => $composableBuilder( 873 - column: $table.notes, 874 - builder: (column) => ColumnOrderings(column), 875 - ); 876 - 877 - ColumnOrderings<String> get tags => $composableBuilder( 878 - column: $table.tags, 879 - builder: (column) => ColumnOrderings(column), 880 - ); 881 - 882 - ColumnOrderings<bool> get unlisted => $composableBuilder( 883 - column: $table.unlisted, 884 - builder: (column) => ColumnOrderings(column), 885 - ); 886 - 887 - ColumnOrderings<bool> get unread => $composableBuilder( 888 - column: $table.unread, 889 - builder: (column) => ColumnOrderings(column), 890 - ); 891 - 892 - ColumnOrderings<String> get languages => $composableBuilder( 893 - column: $table.languages, 894 - builder: (column) => ColumnOrderings(column), 895 - ); 896 - 897 - ColumnOrderings<DateTime> get createdAt => $composableBuilder( 898 - column: $table.createdAt, 899 - builder: (column) => ColumnOrderings(column), 900 - ); 901 - } 902 - 903 - class $$ClipsTableAnnotationComposer 904 - extends Composer<_$AppDatabase, $ClipsTable> { 905 - $$ClipsTableAnnotationComposer({ 906 - required super.$db, 907 - required super.$table, 908 - super.joinBuilder, 909 - super.$addJoinBuilderToRootComposer, 910 - super.$removeJoinBuilderFromRootComposer, 911 - }); 912 - GeneratedColumn<DateTime> get timestamp => 913 - $composableBuilder(column: $table.timestamp, builder: (column) => column); 914 - 915 - GeneratedColumn<String> get did => 916 - $composableBuilder(column: $table.did, builder: (column) => column); 917 - 918 - GeneratedColumn<String> get recordKey => 919 - $composableBuilder(column: $table.recordKey, builder: (column) => column); 920 - 921 - GeneratedColumn<String> get url => 922 - $composableBuilder(column: $table.url, builder: (column) => column); 923 - 924 - GeneratedColumn<String> get title => 925 - $composableBuilder(column: $table.title, builder: (column) => column); 926 - 927 - GeneratedColumn<String> get description => $composableBuilder( 928 - column: $table.description, 929 - builder: (column) => column, 930 - ); 931 - 932 - GeneratedColumn<String> get notes => 933 - $composableBuilder(column: $table.notes, builder: (column) => column); 934 - 935 - GeneratedColumnWithTypeConverter<StrongRef?, String> get tags => 936 - $composableBuilder(column: $table.tags, builder: (column) => column); 937 - 938 - GeneratedColumn<bool> get unlisted => 939 - $composableBuilder(column: $table.unlisted, builder: (column) => column); 940 - 941 - GeneratedColumn<bool> get unread => 942 - $composableBuilder(column: $table.unread, builder: (column) => column); 943 - 944 - GeneratedColumnWithTypeConverter<List<String>?, String> get languages => 945 - $composableBuilder(column: $table.languages, builder: (column) => column); 946 - 947 - GeneratedColumn<DateTime> get createdAt => 948 - $composableBuilder(column: $table.createdAt, builder: (column) => column); 949 - } 950 - 951 - class $$ClipsTableTableManager 952 - extends 953 - RootTableManager< 954 - _$AppDatabase, 955 - $ClipsTable, 956 - Clip, 957 - $$ClipsTableFilterComposer, 958 - $$ClipsTableOrderingComposer, 959 - $$ClipsTableAnnotationComposer, 960 - $$ClipsTableCreateCompanionBuilder, 961 - $$ClipsTableUpdateCompanionBuilder, 962 - (Clip, BaseReferences<_$AppDatabase, $ClipsTable, Clip>), 963 - Clip, 964 - PrefetchHooks Function() 965 - > { 966 - $$ClipsTableTableManager(_$AppDatabase db, $ClipsTable table) 967 - : super( 968 - TableManagerState( 969 - db: db, 970 - table: table, 971 - createFilteringComposer: () => 972 - $$ClipsTableFilterComposer($db: db, $table: table), 973 - createOrderingComposer: () => 974 - $$ClipsTableOrderingComposer($db: db, $table: table), 975 - createComputedFieldComposer: () => 976 - $$ClipsTableAnnotationComposer($db: db, $table: table), 977 - updateCompanionCallback: 978 - ({ 979 - Value<DateTime> timestamp = const Value.absent(), 980 - Value<String> did = const Value.absent(), 981 - Value<String> recordKey = const Value.absent(), 982 - Value<String> url = const Value.absent(), 983 - Value<String> title = const Value.absent(), 984 - Value<String> description = const Value.absent(), 985 - Value<String?> notes = const Value.absent(), 986 - Value<StrongRef?> tags = const Value.absent(), 987 - Value<bool> unlisted = const Value.absent(), 988 - Value<bool?> unread = const Value.absent(), 989 - Value<List<String>?> languages = const Value.absent(), 990 - Value<DateTime> createdAt = const Value.absent(), 991 - Value<int> rowid = const Value.absent(), 992 - }) => ClipsCompanion( 993 - timestamp: timestamp, 994 - did: did, 995 - recordKey: recordKey, 996 - url: url, 997 - title: title, 998 - description: description, 999 - notes: notes, 1000 - tags: tags, 1001 - unlisted: unlisted, 1002 - unread: unread, 1003 - languages: languages, 1004 - createdAt: createdAt, 1005 - rowid: rowid, 1006 - ), 1007 - createCompanionCallback: 1008 - ({ 1009 - Value<DateTime> timestamp = const Value.absent(), 1010 - required String did, 1011 - required String recordKey, 1012 - required String url, 1013 - required String title, 1014 - required String description, 1015 - Value<String?> notes = const Value.absent(), 1016 - Value<StrongRef?> tags = const Value.absent(), 1017 - required bool unlisted, 1018 - Value<bool?> unread = const Value.absent(), 1019 - Value<List<String>?> languages = const Value.absent(), 1020 - required DateTime createdAt, 1021 - Value<int> rowid = const Value.absent(), 1022 - }) => ClipsCompanion.insert( 1023 - timestamp: timestamp, 1024 - did: did, 1025 - recordKey: recordKey, 1026 - url: url, 1027 - title: title, 1028 - description: description, 1029 - notes: notes, 1030 - tags: tags, 1031 - unlisted: unlisted, 1032 - unread: unread, 1033 - languages: languages, 1034 - createdAt: createdAt, 1035 - rowid: rowid, 1036 - ), 1037 - withReferenceMapper: (p0) => p0 1038 - .map((e) => (e.readTable(table), BaseReferences(db, table, e))) 1039 - .toList(), 1040 - prefetchHooksCallback: null, 1041 - ), 1042 - ); 1043 - } 1044 - 1045 - typedef $$ClipsTableProcessedTableManager = 1046 - ProcessedTableManager< 1047 - _$AppDatabase, 1048 - $ClipsTable, 1049 - Clip, 1050 - $$ClipsTableFilterComposer, 1051 - $$ClipsTableOrderingComposer, 1052 - $$ClipsTableAnnotationComposer, 1053 - $$ClipsTableCreateCompanionBuilder, 1054 - $$ClipsTableUpdateCompanionBuilder, 1055 - (Clip, BaseReferences<_$AppDatabase, $ClipsTable, Clip>), 1056 - Clip, 1057 - PrefetchHooks Function() 1058 - >; 1059 - 1060 - class $AppDatabaseManager { 1061 - final _$AppDatabase _db; 1062 - $AppDatabaseManager(this._db); 1063 - $$ClipsTableTableManager get clips => 1064 - $$ClipsTableTableManager(_db, _db.clips); 1065 - }
-77
backend/lib/server/firehose.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'dart:async'; 8 - import 'dart:convert'; 9 - 10 - import 'package:clippr/server/logger.dart'; 11 - import 'package:web_socket_channel/web_socket_channel.dart'; 12 - 13 - /// This class creates a WebSocket connection to a Jetstream-based firehose. 14 - /// 15 - /// All instances operate their own separate connection to the firehose. 16 - /// As such, new instances should be created as little as possible. 17 - class Firehose { 18 - /// [Uri] containing a link to the firehose's WebSocket subscription link. 19 - static late final Uri firehoseProvider; 20 - /// Raw WebSocket stream 21 - static late final WebSocketChannel _channel; 22 - /// Controllable version of stream 23 - static final StreamController<Map<String, dynamic>> _messageController = 24 - StreamController.broadcast(); 25 - /// Stream of messages to access from other places 26 - static Stream<Map<String, dynamic>> get messageStream => _messageController.stream; 27 - 28 - /// Create a new [Firehose] instance using a provided URL string. 29 - Firehose(String firehoseUrl) { 30 - if (firehoseUrl.startsWith("wss://") || firehoseUrl.startsWith("ws://")) { 31 - firehoseUrl = firehoseUrl.replaceFirst("ws://", ""); 32 - firehoseUrl = firehoseUrl.replaceFirst("wss://", ""); 33 - } 34 - if (firehoseUrl.endsWith("/subscribe")) { 35 - firehoseUrl = firehoseUrl.replaceFirst("/subscribe", ""); 36 - } 37 - // This is hardcoded for the moment. This is not ideal and we should end up 38 - // splitting this code into its own separate package with tests and custom 39 - // query parameters but right now we just need to fetch our stuff. 40 - firehoseProvider = Uri.parse( 41 - 'wss://$firehoseUrl/subscribe?wantedCollections=social.clippr.*', 42 - ); 43 - } 44 - 45 - /// Connect to the firehose. 46 - /// 47 - /// TODO: Implement support for the query parameters. 48 - Future<void> connect() async { 49 - _channel = WebSocketChannel.connect(firehoseProvider); 50 - await _channel.ready; 51 - 52 - _channel.stream.listen( // Pass raw WebSocket stream to controller 53 - (message) { 54 - try { 55 - final jsonMessage = jsonDecode(message); 56 - _messageController.add(jsonMessage); 57 - } catch (e) { 58 - print('Invalid JSON: $e'); 59 - } 60 - }, 61 - onDone: () { 62 - Logger.logSevere('WebSocket connection closed by firehose'); 63 - _messageController.close(); 64 - }, 65 - onError: (error) { 66 - Logger.logSevere('WebSocket error: $error'); 67 - _messageController.close(); 68 - }, 69 - ); 70 - } 71 - 72 - /// Disconnect from the firehose. 73 - void disconnect() { 74 - _channel.sink.close(1000, "Normal closure"); 75 - _messageController.close(); 76 - } 77 - }
-56
backend/lib/server/logger.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'package:logging/logging.dart' as logging; 8 - 9 - class Logger { 10 - static late logging.Logger log; 11 - Logger() { 12 - log = logging.Logger('defaultLogger'); 13 - logging.Logger.root.level = logging.Level.ALL; 14 - logging.Logger.root.onRecord.listen((record) { 15 - print('${record.level.name} [${record.time}]: ${record.message}'); 16 - if (record.error != null) { 17 - print('Given error: ${record.error}'); 18 - } 19 - if (record.stackTrace != null) { 20 - print('Stack trace: ${record.stackTrace}'); 21 - } 22 - }); 23 - } 24 - 25 - static void logShout(String message, [Object? error, StackTrace? stackTrace]) { 26 - log.shout(message, error, stackTrace); 27 - } 28 - 29 - static void logSevere(String message, [Object? error, StackTrace? stackTrace]) { 30 - log.severe(message, error, stackTrace); 31 - } 32 - 33 - static void logWarning(String message, [Object? error, StackTrace? stackTrace]) { 34 - log.warning(message, error, stackTrace); 35 - } 36 - 37 - static void logInfo(String message, [Object? error, StackTrace? stackTrace]) { 38 - log.info(message, error, stackTrace); 39 - } 40 - 41 - static void logConfig(String message, [Object? error, StackTrace? stackTrace]) { 42 - log.config(message, error, stackTrace); 43 - } 44 - 45 - static void logFine(String message, [Object? error, StackTrace? stackTrace]) { 46 - log.fine(message, error, stackTrace); 47 - } 48 - 49 - static void logFiner(String message, [Object? error, StackTrace? stackTrace]) { 50 - log.finer(message, error, stackTrace); 51 - } 52 - 53 - static void logFinest(String message, [Object? error, StackTrace? stackTrace]) { 54 - log.finest(message, error, stackTrace); 55 - } 56 - }
-33
backend/lib/server/routes.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'package:shelf/shelf.dart'; 8 - import 'package:shelf_router/shelf_router.dart'; 9 - import 'package:shelf_router_classes/shelf_router_classes.dart'; 10 - 11 - class MiscRouter { 12 - @Route('GET', '/') 13 - Response getIndex(Request request) { 14 - return Response.ok("hello from clippr appview!"); 15 - } 16 - } 17 - 18 - @RoutePrefix('/xrpc') 19 - class XrpcRouter { 20 - @Route('GET', '') 21 - @Route('GET', '/') 22 - Response getRootXrpc(Request request) { 23 - return Response.badRequest(); 24 - } 25 - } 26 - 27 - @RoutePrefix('/oauth') 28 - class OAuthRouter { 29 - @Route('GET', '/client-metadata.json') 30 - Response getOauthClientMetadata(Request request) { 31 - return Response.internalServerError(body: "Not ready yet!"); 32 - } 33 - }
-61
backend/lib/server/server.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'dart:io'; 8 - import 'package:clippr/db/database.dart'; 9 - import 'package:clippr/server/firehose.dart'; 10 - import 'package:clippr/server/logger.dart'; 11 - import 'package:clippr/server/routes.dart'; 12 - import 'package:clippr/config/config.dart'; 13 - import 'package:shelf/shelf.dart'; 14 - import 'package:shelf/shelf_io.dart' as io; 15 - import 'package:shelf_router/shelf_router.dart'; 16 - import 'package:shelf_router_classes/shelf_router_classes.dart'; 17 - 18 - void launchWebServer() async { 19 - Router router = getRoutersByClass([MiscRouter, OAuthRouter, XrpcRouter]); 20 - final app = const Pipeline() 21 - .addMiddleware(serverLogger()) 22 - .addHandler(router.call); 23 - 24 - HttpServer _ = await io.serve(app, Config.getHostname(), Config.getPort()); 25 - } 26 - 27 - void launchDatabase() { 28 - var database = AppDatabase(); 29 - } 30 - 31 - void launchFirehose() { 32 - var firehose = Firehose(Config.getFirehoseProvider()); 33 - firehose.connect(); 34 - // Firehose.messageStream.listen((message) { 35 - // print(message); 36 - // }); 37 - } 38 - 39 - Middleware serverLogger() { 40 - return (Handler innerHandler) { 41 - return (Request request) async { 42 - final startTime = DateTime.now(); 43 - try { 44 - final response = await innerHandler(request); 45 - final endTime = DateTime.now(); 46 - final duration = endTime.difference(startTime); // Time to serve route 47 - Logger.logFine( 48 - '${request.method} ${request.requestedUri.path} [${response.statusCode}] in $duration', 49 - ); 50 - return response; 51 - } catch (e, stackTrace) { 52 - Logger.logSevere( 53 - 'Error handling ${request.method} ${request.requestedUri.path}', 54 - e, 55 - stackTrace, 56 - ); 57 - rethrow; 58 - } 59 - }; 60 - }; 61 - }
+23
backend/package.json
··· 1 + { 2 + "name": "clippr-ts", 3 + "version": "0.1.0", 4 + "homepage": "https://tangled.sh/@hexmani.ac/clippr-ts", 5 + "license": "AGPL-3.0-or-later", 6 + "scripts": { 7 + "dev": "bun run --hot src/index.ts" 8 + }, 9 + "dependencies": { 10 + "@skyware/jetstream": "^0.2.2", 11 + "drizzle-orm": "^0.44.2", 12 + "hono": "^4.8.3", 13 + "toml": "^3.0.0" 14 + }, 15 + "devDependencies": { 16 + "@eslint/js": "^9.30.1", 17 + "@types/bun": "^1.2.17", 18 + "drizzle-kit": "^0.31.4", 19 + "eslint": "^9.30.1", 20 + "globals": "^16.3.0", 21 + "typescript-eslint": "^8.35.1" 22 + } 23 + }
-797
backend/pubspec.lock
··· 1 - # Generated by pub 2 - # See https://dart.dev/tools/pub/glossary#lockfile 3 - packages: 4 - _fe_analyzer_shared: 5 - dependency: transitive 6 - description: 7 - name: _fe_analyzer_shared 8 - sha256: e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f 9 - url: "https://pub.dev" 10 - source: hosted 11 - version: "82.0.0" 12 - analyzer: 13 - dependency: transitive 14 - description: 15 - name: analyzer 16 - sha256: "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0" 17 - url: "https://pub.dev" 18 - source: hosted 19 - version: "7.4.5" 20 - args: 21 - dependency: transitive 22 - description: 23 - name: args 24 - sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 25 - url: "https://pub.dev" 26 - source: hosted 27 - version: "2.7.0" 28 - async: 29 - dependency: transitive 30 - description: 31 - name: async 32 - sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" 33 - url: "https://pub.dev" 34 - source: hosted 35 - version: "2.13.0" 36 - at_identifier: 37 - dependency: transitive 38 - description: 39 - name: at_identifier 40 - sha256: "7c8778202d17ec4e63b38a6a58480503fbf0d7fc1d62e0d64580a9b6cbe142f7" 41 - url: "https://pub.dev" 42 - source: hosted 43 - version: "0.2.2" 44 - at_uri: 45 - dependency: transitive 46 - description: 47 - name: at_uri 48 - sha256: "1156d9d70460fcfcb30e744d7f8c7d544eff073b3142b772f0d02aca10dd064f" 49 - url: "https://pub.dev" 50 - source: hosted 51 - version: "0.4.0" 52 - atproto: 53 - dependency: "direct main" 54 - description: 55 - name: atproto 56 - sha256: "0f3d342c4d629e9994d58dbadd4281074641ac75a18cd514b212a3b15f86019e" 57 - url: "https://pub.dev" 58 - source: hosted 59 - version: "0.13.3" 60 - atproto_core: 61 - dependency: transitive 62 - description: 63 - name: atproto_core 64 - sha256: "13e7f5f0f3d9e5be59eefd5f427adf45ffdeaa59001d4ea7c91764ba21f1e9ba" 65 - url: "https://pub.dev" 66 - source: hosted 67 - version: "0.11.2" 68 - atproto_oauth: 69 - dependency: transitive 70 - description: 71 - name: atproto_oauth 72 - sha256: "8a0c64455c38c45773ebab5fdd55bf214541461f3a97fe0e6184a5eeb8222f03" 73 - url: "https://pub.dev" 74 - source: hosted 75 - version: "0.1.0" 76 - base_codecs: 77 - dependency: transitive 78 - description: 79 - name: base_codecs 80 - sha256: "41701a12ede9912663decd708279924ece5018566daa7d1f484d5f4f10894f91" 81 - url: "https://pub.dev" 82 - source: hosted 83 - version: "1.0.1" 84 - boolean_selector: 85 - dependency: transitive 86 - description: 87 - name: boolean_selector 88 - sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" 89 - url: "https://pub.dev" 90 - source: hosted 91 - version: "2.1.2" 92 - buffer: 93 - dependency: transitive 94 - description: 95 - name: buffer 96 - sha256: "389da2ec2c16283c8787e0adaede82b1842102f8c8aae2f49003a766c5c6b3d1" 97 - url: "https://pub.dev" 98 - source: hosted 99 - version: "1.2.3" 100 - build: 101 - dependency: transitive 102 - description: 103 - name: build 104 - sha256: "486337d40a48d75049f2a01efceefc1412e3a6d6342d39624753e7d5a4e70016" 105 - url: "https://pub.dev" 106 - source: hosted 107 - version: "2.5.1" 108 - build_config: 109 - dependency: transitive 110 - description: 111 - name: build_config 112 - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" 113 - url: "https://pub.dev" 114 - source: hosted 115 - version: "1.1.2" 116 - build_daemon: 117 - dependency: transitive 118 - description: 119 - name: build_daemon 120 - sha256: "8e928697a82be082206edb0b9c99c5a4ad6bc31c9e9b8b2f291ae65cd4a25daa" 121 - url: "https://pub.dev" 122 - source: hosted 123 - version: "4.0.4" 124 - build_resolvers: 125 - dependency: transitive 126 - description: 127 - name: build_resolvers 128 - sha256: abe6e4b5b36ce2bf01aec8f2a59424d1ecfc3cb340e7145a64359adc7233a0d1 129 - url: "https://pub.dev" 130 - source: hosted 131 - version: "2.5.1" 132 - build_runner: 133 - dependency: "direct dev" 134 - description: 135 - name: build_runner 136 - sha256: "398ec7898b9b60be126067835a8202240b26dc54aa34d91d0198a539dcd5942e" 137 - url: "https://pub.dev" 138 - source: hosted 139 - version: "2.5.1" 140 - build_runner_core: 141 - dependency: transitive 142 - description: 143 - name: build_runner_core 144 - sha256: "9821dbf604ed74a6dabeaba0c33ac58190332ea238862a62cdf25fc8eba226b8" 145 - url: "https://pub.dev" 146 - source: hosted 147 - version: "9.0.1" 148 - built_collection: 149 - dependency: transitive 150 - description: 151 - name: built_collection 152 - sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" 153 - url: "https://pub.dev" 154 - source: hosted 155 - version: "5.1.1" 156 - built_value: 157 - dependency: transitive 158 - description: 159 - name: built_value 160 - sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27" 161 - url: "https://pub.dev" 162 - source: hosted 163 - version: "8.10.1" 164 - cbor: 165 - dependency: transitive 166 - description: 167 - name: cbor 168 - sha256: f5239dd6b6ad24df67d1449e87d7180727d6f43b87b3c9402e6398c7a2d9609b 169 - url: "https://pub.dev" 170 - source: hosted 171 - version: "6.3.7" 172 - characters: 173 - dependency: transitive 174 - description: 175 - name: characters 176 - sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 177 - url: "https://pub.dev" 178 - source: hosted 179 - version: "1.4.0" 180 - charcode: 181 - dependency: transitive 182 - description: 183 - name: charcode 184 - sha256: fb0f1107cac15a5ea6ef0a6ef71a807b9e4267c713bb93e00e92d737cc8dbd8a 185 - url: "https://pub.dev" 186 - source: hosted 187 - version: "1.4.0" 188 - checked_yaml: 189 - dependency: transitive 190 - description: 191 - name: checked_yaml 192 - sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" 193 - url: "https://pub.dev" 194 - source: hosted 195 - version: "2.0.4" 196 - cli_config: 197 - dependency: transitive 198 - description: 199 - name: cli_config 200 - sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec 201 - url: "https://pub.dev" 202 - source: hosted 203 - version: "0.2.0" 204 - cli_util: 205 - dependency: transitive 206 - description: 207 - name: cli_util 208 - sha256: ff6785f7e9e3c38ac98b2fb035701789de90154024a75b6cb926445e83197d1c 209 - url: "https://pub.dev" 210 - source: hosted 211 - version: "0.4.2" 212 - code_builder: 213 - dependency: transitive 214 - description: 215 - name: code_builder 216 - sha256: "0ec10bf4a89e4c613960bf1e8b42c64127021740fb21640c29c909826a5eea3e" 217 - url: "https://pub.dev" 218 - source: hosted 219 - version: "4.10.1" 220 - collection: 221 - dependency: transitive 222 - description: 223 - name: collection 224 - sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" 225 - url: "https://pub.dev" 226 - source: hosted 227 - version: "1.19.1" 228 - convert: 229 - dependency: transitive 230 - description: 231 - name: convert 232 - sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 233 - url: "https://pub.dev" 234 - source: hosted 235 - version: "3.1.2" 236 - coverage: 237 - dependency: transitive 238 - description: 239 - name: coverage 240 - sha256: aa07dbe5f2294c827b7edb9a87bba44a9c15a3cc81bc8da2ca19b37322d30080 241 - url: "https://pub.dev" 242 - source: hosted 243 - version: "1.14.1" 244 - crypto: 245 - dependency: transitive 246 - description: 247 - name: crypto 248 - sha256: "1e445881f28f22d6140f181e07737b22f1e099a5e1ff94b0af2f9e4a463f4855" 249 - url: "https://pub.dev" 250 - source: hosted 251 - version: "3.0.6" 252 - dart_multihash: 253 - dependency: transitive 254 - description: 255 - name: dart_multihash 256 - sha256: "7bef7091497c531f94bf82102805a69d97e4e5d120000dcbbc4a1da679060e0a" 257 - url: "https://pub.dev" 258 - source: hosted 259 - version: "1.0.1" 260 - dart_style: 261 - dependency: transitive 262 - description: 263 - name: dart_style 264 - sha256: "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af" 265 - url: "https://pub.dev" 266 - source: hosted 267 - version: "3.1.0" 268 - drift: 269 - dependency: "direct main" 270 - description: 271 - name: drift 272 - sha256: e60c715f045dd33624fc533efb0075e057debec9f39e83843e518f488a0e21fb 273 - url: "https://pub.dev" 274 - source: hosted 275 - version: "2.27.0" 276 - drift_dev: 277 - dependency: "direct dev" 278 - description: 279 - name: drift_dev 280 - sha256: "7ad88b8982e753eadcdbc0ea7c7d30500598af733601428b5c9d264baf5106d6" 281 - url: "https://pub.dev" 282 - source: hosted 283 - version: "2.27.0" 284 - ffi: 285 - dependency: transitive 286 - description: 287 - name: ffi 288 - sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" 289 - url: "https://pub.dev" 290 - source: hosted 291 - version: "2.1.4" 292 - file: 293 - dependency: transitive 294 - description: 295 - name: file 296 - sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 297 - url: "https://pub.dev" 298 - source: hosted 299 - version: "7.0.1" 300 - fixnum: 301 - dependency: transitive 302 - description: 303 - name: fixnum 304 - sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be 305 - url: "https://pub.dev" 306 - source: hosted 307 - version: "1.1.1" 308 - freezed_annotation: 309 - dependency: transitive 310 - description: 311 - name: freezed_annotation 312 - sha256: c2e2d632dd9b8a2b7751117abcfc2b4888ecfe181bd9fca7170d9ef02e595fe2 313 - url: "https://pub.dev" 314 - source: hosted 315 - version: "2.4.4" 316 - frontend_server_client: 317 - dependency: transitive 318 - description: 319 - name: frontend_server_client 320 - sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 321 - url: "https://pub.dev" 322 - source: hosted 323 - version: "4.0.0" 324 - glob: 325 - dependency: transitive 326 - description: 327 - name: glob 328 - sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de 329 - url: "https://pub.dev" 330 - source: hosted 331 - version: "2.1.3" 332 - graphs: 333 - dependency: transitive 334 - description: 335 - name: graphs 336 - sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" 337 - url: "https://pub.dev" 338 - source: hosted 339 - version: "2.3.2" 340 - hex: 341 - dependency: transitive 342 - description: 343 - name: hex 344 - sha256: "4e7cd54e4b59ba026432a6be2dd9d96e4c5205725194997193bf871703b82c4a" 345 - url: "https://pub.dev" 346 - source: hosted 347 - version: "0.2.0" 348 - http: 349 - dependency: transitive 350 - description: 351 - name: http 352 - sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" 353 - url: "https://pub.dev" 354 - source: hosted 355 - version: "1.4.0" 356 - http_methods: 357 - dependency: transitive 358 - description: 359 - name: http_methods 360 - sha256: "6bccce8f1ec7b5d701e7921dca35e202d425b57e317ba1a37f2638590e29e566" 361 - url: "https://pub.dev" 362 - source: hosted 363 - version: "1.1.1" 364 - http_multi_server: 365 - dependency: transitive 366 - description: 367 - name: http_multi_server 368 - sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 369 - url: "https://pub.dev" 370 - source: hosted 371 - version: "3.2.2" 372 - http_parser: 373 - dependency: transitive 374 - description: 375 - name: http_parser 376 - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" 377 - url: "https://pub.dev" 378 - source: hosted 379 - version: "4.1.2" 380 - ieee754: 381 - dependency: transitive 382 - description: 383 - name: ieee754 384 - sha256: "7d87451c164a56c156180d34a4e93779372edd191d2c219206100b976203128c" 385 - url: "https://pub.dev" 386 - source: hosted 387 - version: "1.0.3" 388 - io: 389 - dependency: transitive 390 - description: 391 - name: io 392 - sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b 393 - url: "https://pub.dev" 394 - source: hosted 395 - version: "1.0.5" 396 - js: 397 - dependency: transitive 398 - description: 399 - name: js 400 - sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" 401 - url: "https://pub.dev" 402 - source: hosted 403 - version: "0.7.2" 404 - json_annotation: 405 - dependency: "direct main" 406 - description: 407 - name: json_annotation 408 - sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1" 409 - url: "https://pub.dev" 410 - source: hosted 411 - version: "4.9.0" 412 - lexicon: 413 - dependency: "direct main" 414 - description: 415 - name: lexicon 416 - sha256: "045e9773e539048c4816177baab71ea007fc5337034a926ccd68dc2669cd150a" 417 - url: "https://pub.dev" 418 - source: hosted 419 - version: "0.2.5" 420 - lints: 421 - dependency: "direct dev" 422 - description: 423 - name: lints 424 - sha256: a5e2b223cb7c9c8efdc663ef484fdd95bb243bff242ef5b13e26883547fce9a0 425 - url: "https://pub.dev" 426 - source: hosted 427 - version: "6.0.0" 428 - logging: 429 - dependency: "direct main" 430 - description: 431 - name: logging 432 - sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 433 - url: "https://pub.dev" 434 - source: hosted 435 - version: "1.3.0" 436 - matcher: 437 - dependency: transitive 438 - description: 439 - name: matcher 440 - sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 441 - url: "https://pub.dev" 442 - source: hosted 443 - version: "0.12.17" 444 - meta: 445 - dependency: transitive 446 - description: 447 - name: meta 448 - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" 449 - url: "https://pub.dev" 450 - source: hosted 451 - version: "1.17.0" 452 - mime: 453 - dependency: transitive 454 - description: 455 - name: mime 456 - sha256: "801fd0b26f14a4a58ccb09d5892c3fbdeff209594300a542492cf13fba9d247a" 457 - url: "https://pub.dev" 458 - source: hosted 459 - version: "1.0.6" 460 - multiformats: 461 - dependency: "direct main" 462 - description: 463 - name: multiformats 464 - sha256: aa2fa36d2e4d0069dac993b35ee52e5165d67f15b995d68f797466065a6d05a5 465 - url: "https://pub.dev" 466 - source: hosted 467 - version: "0.2.3" 468 - node_preamble: 469 - dependency: transitive 470 - description: 471 - name: node_preamble 472 - sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" 473 - url: "https://pub.dev" 474 - source: hosted 475 - version: "2.0.2" 476 - nsid: 477 - dependency: transitive 478 - description: 479 - name: nsid 480 - sha256: f0e58c3899f7c224a7c9fb991be5bb2c18de0f920bec4e807ae2d3572cb718c1 481 - url: "https://pub.dev" 482 - source: hosted 483 - version: "0.4.1" 484 - oauth2: 485 - dependency: "direct main" 486 - description: 487 - name: oauth2 488 - sha256: c84470642cbb2bec450ccab2f8520c079cd1ca546a76ffd5c40589e07f4e8bf4 489 - url: "https://pub.dev" 490 - source: hosted 491 - version: "2.0.3" 492 - package_config: 493 - dependency: transitive 494 - description: 495 - name: package_config 496 - sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc 497 - url: "https://pub.dev" 498 - source: hosted 499 - version: "2.2.0" 500 - path: 501 - dependency: transitive 502 - description: 503 - name: path 504 - sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" 505 - url: "https://pub.dev" 506 - source: hosted 507 - version: "1.9.1" 508 - pointycastle: 509 - dependency: transitive 510 - description: 511 - name: pointycastle 512 - sha256: "4be0097fcf3fd3e8449e53730c631200ebc7b88016acecab2b0da2f0149222fe" 513 - url: "https://pub.dev" 514 - source: hosted 515 - version: "3.9.1" 516 - pool: 517 - dependency: transitive 518 - description: 519 - name: pool 520 - sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" 521 - url: "https://pub.dev" 522 - source: hosted 523 - version: "1.5.1" 524 - pub_semver: 525 - dependency: transitive 526 - description: 527 - name: pub_semver 528 - sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" 529 - url: "https://pub.dev" 530 - source: hosted 531 - version: "2.2.0" 532 - pubspec_parse: 533 - dependency: "direct main" 534 - description: 535 - name: pubspec_parse 536 - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" 537 - url: "https://pub.dev" 538 - source: hosted 539 - version: "1.5.0" 540 - recase: 541 - dependency: transitive 542 - description: 543 - name: recase 544 - sha256: e4eb4ec2dcdee52dcf99cb4ceabaffc631d7424ee55e56f280bc039737f89213 545 - url: "https://pub.dev" 546 - source: hosted 547 - version: "4.1.0" 548 - shelf: 549 - dependency: "direct main" 550 - description: 551 - name: shelf 552 - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 553 - url: "https://pub.dev" 554 - source: hosted 555 - version: "1.4.2" 556 - shelf_packages_handler: 557 - dependency: transitive 558 - description: 559 - name: shelf_packages_handler 560 - sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" 561 - url: "https://pub.dev" 562 - source: hosted 563 - version: "3.0.2" 564 - shelf_router: 565 - dependency: "direct main" 566 - description: 567 - name: shelf_router 568 - sha256: f5e5d492440a7fb165fe1e2e1a623f31f734d3370900070b2b1e0d0428d59864 569 - url: "https://pub.dev" 570 - source: hosted 571 - version: "1.1.4" 572 - shelf_router_classes: 573 - dependency: "direct main" 574 - description: 575 - name: shelf_router_classes 576 - sha256: "75a02b9559c384974b03e4370166c2323cf73e33c5b8f5d299bc4c825dd99741" 577 - url: "https://pub.dev" 578 - source: hosted 579 - version: "1.0.3" 580 - shelf_static: 581 - dependency: transitive 582 - description: 583 - name: shelf_static 584 - sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 585 - url: "https://pub.dev" 586 - source: hosted 587 - version: "1.1.3" 588 - shelf_web_socket: 589 - dependency: transitive 590 - description: 591 - name: shelf_web_socket 592 - sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" 593 - url: "https://pub.dev" 594 - source: hosted 595 - version: "3.0.0" 596 - source_gen: 597 - dependency: transitive 598 - description: 599 - name: source_gen 600 - sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" 601 - url: "https://pub.dev" 602 - source: hosted 603 - version: "2.0.0" 604 - source_map_stack_trace: 605 - dependency: transitive 606 - description: 607 - name: source_map_stack_trace 608 - sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b 609 - url: "https://pub.dev" 610 - source: hosted 611 - version: "2.1.2" 612 - source_maps: 613 - dependency: transitive 614 - description: 615 - name: source_maps 616 - sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" 617 - url: "https://pub.dev" 618 - source: hosted 619 - version: "0.10.13" 620 - source_span: 621 - dependency: transitive 622 - description: 623 - name: source_span 624 - sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" 625 - url: "https://pub.dev" 626 - source: hosted 627 - version: "1.10.1" 628 - sqlite3: 629 - dependency: "direct main" 630 - description: 631 - name: sqlite3 632 - sha256: c0503c69b44d5714e6abbf4c1f51a3c3cc42b75ce785f44404765e4635481d38 633 - url: "https://pub.dev" 634 - source: hosted 635 - version: "2.7.6" 636 - sqlparser: 637 - dependency: transitive 638 - description: 639 - name: sqlparser 640 - sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee" 641 - url: "https://pub.dev" 642 - source: hosted 643 - version: "0.41.0" 644 - stack_trace: 645 - dependency: transitive 646 - description: 647 - name: stack_trace 648 - sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" 649 - url: "https://pub.dev" 650 - source: hosted 651 - version: "1.12.1" 652 - stream_channel: 653 - dependency: transitive 654 - description: 655 - name: stream_channel 656 - sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" 657 - url: "https://pub.dev" 658 - source: hosted 659 - version: "2.1.4" 660 - stream_transform: 661 - dependency: transitive 662 - description: 663 - name: stream_transform 664 - sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 665 - url: "https://pub.dev" 666 - source: hosted 667 - version: "2.1.1" 668 - string_scanner: 669 - dependency: transitive 670 - description: 671 - name: string_scanner 672 - sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" 673 - url: "https://pub.dev" 674 - source: hosted 675 - version: "1.4.1" 676 - term_glyph: 677 - dependency: transitive 678 - description: 679 - name: term_glyph 680 - sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" 681 - url: "https://pub.dev" 682 - source: hosted 683 - version: "1.2.2" 684 - test: 685 - dependency: "direct dev" 686 - description: 687 - name: test 688 - sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" 689 - url: "https://pub.dev" 690 - source: hosted 691 - version: "1.26.2" 692 - test_api: 693 - dependency: transitive 694 - description: 695 - name: test_api 696 - sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" 697 - url: "https://pub.dev" 698 - source: hosted 699 - version: "0.7.6" 700 - test_core: 701 - dependency: transitive 702 - description: 703 - name: test_core 704 - sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" 705 - url: "https://pub.dev" 706 - source: hosted 707 - version: "0.6.11" 708 - timing: 709 - dependency: transitive 710 - description: 711 - name: timing 712 - sha256: "62ee18aca144e4a9f29d212f5a4c6a053be252b895ab14b5821996cff4ed90fe" 713 - url: "https://pub.dev" 714 - source: hosted 715 - version: "1.0.2" 716 - typed_data: 717 - dependency: transitive 718 - description: 719 - name: typed_data 720 - sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 721 - url: "https://pub.dev" 722 - source: hosted 723 - version: "1.4.0" 724 - universal_io: 725 - dependency: transitive 726 - description: 727 - name: universal_io 728 - sha256: "1722b2dcc462b4b2f3ee7d188dad008b6eb4c40bbd03a3de451d82c78bba9aad" 729 - url: "https://pub.dev" 730 - source: hosted 731 - version: "2.2.2" 732 - vm_service: 733 - dependency: transitive 734 - description: 735 - name: vm_service 736 - sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" 737 - url: "https://pub.dev" 738 - source: hosted 739 - version: "15.0.2" 740 - watcher: 741 - dependency: transitive 742 - description: 743 - name: watcher 744 - sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a" 745 - url: "https://pub.dev" 746 - source: hosted 747 - version: "1.1.2" 748 - web: 749 - dependency: transitive 750 - description: 751 - name: web 752 - sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" 753 - url: "https://pub.dev" 754 - source: hosted 755 - version: "1.1.1" 756 - web_socket: 757 - dependency: transitive 758 - description: 759 - name: web_socket 760 - sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" 761 - url: "https://pub.dev" 762 - source: hosted 763 - version: "1.0.1" 764 - web_socket_channel: 765 - dependency: "direct main" 766 - description: 767 - name: web_socket_channel 768 - sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 769 - url: "https://pub.dev" 770 - source: hosted 771 - version: "3.0.3" 772 - webkit_inspection_protocol: 773 - dependency: transitive 774 - description: 775 - name: webkit_inspection_protocol 776 - sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" 777 - url: "https://pub.dev" 778 - source: hosted 779 - version: "1.2.1" 780 - xrpc: 781 - dependency: transitive 782 - description: 783 - name: xrpc 784 - sha256: bacfa0f6824fdeaa631aad1a5fd064c3f140c771fed94cbd04df3b7d1e008709 785 - url: "https://pub.dev" 786 - source: hosted 787 - version: "0.6.1" 788 - yaml: 789 - dependency: "direct main" 790 - description: 791 - name: yaml 792 - sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce 793 - url: "https://pub.dev" 794 - source: hosted 795 - version: "3.1.3" 796 - sdks: 797 - dart: ">=3.8.1 <4.0.0"
-31
backend/pubspec.yaml
··· 1 - name: clippr 2 - description: official appview for clippr 3 - version: 0.1.0 4 - publish_to: none 5 - repository: https://tangled.sh/@noob.quest/clippr 6 - issue_tracker: https://tangled.sh/@noob.quest/clippr/issues 7 - 8 - environment: 9 - sdk: ^3.8.1 10 - 11 - dependencies: 12 - atproto: ^0.13.3 13 - drift: ^2.27.0 14 - json_annotation: ^4.9.0 15 - lexicon: ^0.2.5 16 - logging: ^1.3.0 17 - multiformats: ^0.2.3 18 - oauth2: ^2.0.3 19 - pubspec_parse: ^1.5.0 20 - shelf: ^1.4.2 21 - shelf_router: ^1.1.4 22 - shelf_router_classes: ^1.0.3 23 - sqlite3: ^2.7.6 24 - web_socket_channel: ^3.0.3 25 - yaml: ^3.1.3 26 - 27 - dev_dependencies: 28 - build_runner: ^2.4.15 29 - drift_dev: ^2.27.0 30 - lints: ^6.0.0 31 - test: ^1.24.0
+43
backend/src/config.ts
··· 1 + import {readFileSync} from "fs"; 2 + import * as toml from "toml"; 3 + 4 + export class Config { 5 + private static instance: Config; 6 + private readonly configData: any; 7 + 8 + private constructor() { 9 + let tomlString; 10 + try { 11 + tomlString = readFileSync("config.toml", "utf-8"); 12 + } catch { 13 + throw new Error("Config file not found"); 14 + } 15 + this.configData = toml.parse(tomlString); 16 + } 17 + 18 + static getInstance(): Config { 19 + if (!Config.instance) { 20 + try { 21 + Config.instance = new Config(); 22 + } catch (e) { 23 + console.error(e); 24 + process.exit(1); 25 + } 26 + } 27 + return Config.instance; 28 + } 29 + 30 + get<T = any>(path: string): T | undefined { 31 + const keys = path.split("."); 32 + let value = this.configData; 33 + for (const key of keys) { 34 + if (value == null) return undefined; 35 + value = value[key]; 36 + } 37 + return value; 38 + } 39 + 40 + getAll(): any { 41 + return this.configData; 42 + } 43 + }
+6
backend/src/database.ts
··· 1 + import {drizzle} from 'drizzle-orm/bun-sqlite'; 2 + import {Config} from "./config"; 3 + 4 + const config = Config.getInstance(); 5 + 6 + const db = drizzle(config.get("database.name"));
+8
backend/src/db/schema.ts
··· 1 + import { int, sqliteTable, text } from "drizzle-orm/sqlite-core"; 2 + 3 + export const usersTable = sqliteTable("users_table", { 4 + id: int().primaryKey({ autoIncrement: true }), 5 + name: text().notNull(), 6 + age: int().notNull(), 7 + email: text().notNull().unique(), 8 + });
+24
backend/src/index.ts
··· 1 + import {Config} from "./config"; 2 + import app from "./server"; 3 + import {readFromFirehose, startFirehose} from "./jetstream"; 4 + 5 + function main() { 6 + console.log("clippr-ts starting...") 7 + 8 + console.log('initializing config') 9 + const config = Config.getInstance(); //; Get config from config.toml 10 + 11 + console.log('initializing firehose connection'); 12 + startFirehose(); 13 + readFromFirehose(); 14 + 15 + Bun.serve({ 16 + port: config.get("port"), 17 + hostname: config.get("hostname"), 18 + fetch: app.fetch, 19 + }); 20 + 21 + console.log(`server started at http://${config.get("hostname")}:${config.get("port")}`); 22 + } 23 + 24 + main();
+28
backend/src/jetstream.ts
··· 1 + import {Jetstream} from "@skyware/jetstream"; 2 + import {Config} from "./config"; 3 + 4 + const config = Config.getInstance(); 5 + const hostname = config.get("network.firehose"); 6 + 7 + const jetstream = new Jetstream({ 8 + endpoint: `wss://${hostname}/subscribe`, 9 + wantedCollections: ["social.clippr.*"], 10 + }); 11 + 12 + export function startFirehose() { 13 + jetstream.start(); 14 + } 15 + 16 + export function stopFirehose() { 17 + jetstream.close(); 18 + } 19 + 20 + export async function readFromFirehose() { 21 + jetstream.on("account", (e) => { 22 + console.log("account update", e.account.status); 23 + }); 24 + 25 + jetstream.on("identity", (e) => { 26 + console.log("identity update", e.identity.did); 27 + }); 28 + }
+12
backend/src/routes/misc.ts
··· 1 + import {Hono} from 'hono' 2 + import {serveStatic} from "hono/bun"; 3 + 4 + const app = new Hono(); 5 + 6 + app.use('/static/*', serveStatic({root: './'})); 7 + app.get('/', serveStatic({path: './static/index.html'})); 8 + app.notFound((c) => { 9 + return c.text('404 Not Found', 404); 10 + }) 11 + 12 + export default app;
+9
backend/src/server.ts
··· 1 + import {Hono} from "hono"; 2 + import misc from "./routes/misc"; 3 + 4 + const app = new Hono(); 5 + 6 + // Link all routes up 7 + app.route('/', misc); 8 + 9 + export default app;
+25
backend/static/index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <meta charset="UTF-8"> 5 + <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 + <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 + <link rel="stylesheet" href="/static/main.css"> 8 + <title>clippr appview</title> 9 + </head> 10 + <body> 11 + <div id="container"> 12 + <header> 13 + <p>clippr</p> 14 + </header> 15 + <main> 16 + <p>welcome to the <b>clippr</b> appview!</p> 17 + <p>the API routes live under <code>/xrpc</code></p> 18 + <a href="http://tangled.sh/@hexmani.ac/clippr-ts">source code</a> 19 + </main> 20 + <footer> 21 + <p>copyright © clippr contributors 2025</p> 22 + </footer> 23 + </div> 24 + </body> 25 + </html>
+52
backend/static/main.css
··· 1 + body { 2 + text-align: center; 3 + font-family: Arial, sans-serif; 4 + background-color: #24262d; 5 + } 6 + 7 + #container { 8 + background-color: #ddd; 9 + padding: 1rem; 10 + border-radius: 0.5rem; 11 + width: fit-content; 12 + position: absolute; 13 + top: 25%; 14 + left: 50%; 15 + margin-right: -50%; 16 + transform: translate(-50%, -50%); 17 + } 18 + 19 + header { 20 + border-bottom: 1px dotted black; 21 + text-align: left; 22 + 23 + p { 24 + margin-top: 0; 25 + font-weight: bold; 26 + } 27 + } 28 + 29 + main { 30 + margin: 1rem; 31 + 32 + a { 33 + text-decoration: none; 34 + } 35 + 36 + a:hover { 37 + font-style: italic; 38 + font-weight: bold; 39 + } 40 + } 41 + 42 + code { 43 + background-color: #111; 44 + color: #eee; 45 + padding: 0.2rem; 46 + border-radius: 0.2rem; 47 + font-family: monospace; 48 + } 49 + 50 + footer { 51 + border-top: 1px dotted black; 52 + }
-96
backend/test/clip_id_test.dart
··· 1 - /* 2 - * clippr: a social bookmarking service for the AT Protocol 3 - * Copyright (c) 2025 clippr contributors. 4 - * SPDX-License-Identifier: AGPL-3.0-only 5 - */ 6 - 7 - import 'package:test/test.dart'; 8 - import 'package:clippr/clip_id/clip_id.dart'; 9 - 10 - void main() { 11 - late Uri urlWithEmptyPath; 12 - late Uri urlWithPath; 13 - late Uri urlWithTildePath; 14 - setUp(() { 15 - urlWithEmptyPath = Uri.parse("https://example.com/"); 16 - urlWithPath = Uri.parse("http://testers.org/example/path.html"); 17 - urlWithTildePath = Uri.parse("gemini://bell.labs/~dmr/unix.html"); 18 - }); 19 - 20 - group('URL with empty path', () { 21 - test('Example URL with empty path: scheme is correct', () { 22 - var id = ClipID(urlWithEmptyPath); 23 - expect(id.scheme, equals("https")); 24 - }); 25 - test('Example URL with empty path: hostname is correct', () { 26 - var id = ClipID(urlWithEmptyPath); 27 - expect(id.hostname, equals("example.com")); 28 - }); 29 - test('Example URL with empty path: path is correct', () { 30 - var id = ClipID(urlWithEmptyPath); 31 - expect(id.path, equals("~")); 32 - }); 33 - test('Example URL with empty path: path segments are correct', () { 34 - var id = ClipID(urlWithEmptyPath); 35 - expect(id.pathSegments, equals(["~"])); 36 - }); 37 - test('Example URL with empty path: complete ID is correct', () { 38 - var id = ClipID(urlWithEmptyPath); 39 - expect(id.toString(), equals("https:example.com:~")); 40 - }); 41 - }); 42 - 43 - group('Example URL with path', () { 44 - test('Example URL with path: scheme is correct', () { 45 - var id = ClipID(urlWithPath); 46 - expect(id.scheme, equals("http")); 47 - }); 48 - 49 - test('Example URL with path: hostname is correct', () { 50 - var id = ClipID(urlWithPath); 51 - expect(id.hostname, equals("testers.org")); 52 - }); 53 - 54 - test('Example URL with path: path is correct', () { 55 - var id = ClipID(urlWithPath); 56 - expect(id.path, equals("example~path.html")); 57 - }); 58 - 59 - test('Example URL with path: path segments are correct', () { 60 - var id = ClipID(urlWithPath); 61 - expect(id.pathSegments, equals(["example", "path.html"])); 62 - }); 63 - 64 - test('Example URL with path: complete ID is correct', () { 65 - var id = ClipID(urlWithPath); 66 - expect(id.toString(), equals("http:testers.org:example~path.html")); 67 - }); 68 - }); 69 - 70 - group('Example URL with tilde-included path', () { 71 - test('Example URL with tilde path: scheme is correct', () { 72 - var id = ClipID(urlWithTildePath); 73 - expect(id.scheme, equals("gemini")); 74 - }); 75 - 76 - test('Example URL with tilde path: hostname is correct', () { 77 - var id = ClipID(urlWithTildePath); 78 - expect(id.hostname, equals("bell.labs")); 79 - }); 80 - 81 - test('Example URL with tilde path: path is correct', () { 82 - var id = ClipID(urlWithTildePath); 83 - expect(id.path, equals("_~dmr~unix.html")); 84 - }); 85 - 86 - test('Example URL with tilde path: path segments are correct', () { 87 - var id = ClipID(urlWithTildePath); 88 - expect(id.pathSegments, equals(["_~dmr", "unix.html"])); 89 - }); 90 - 91 - test('Example URL with tilde path: complete ID is correct', () { 92 - var id = ClipID(urlWithTildePath); 93 - expect(id.toString(), equals("gemini:bell.labs:_~dmr~unix.html")); 94 - }); 95 - }); 96 - }
-8
backend/tools/build_and_run.sh
··· 1 - #!/bin/sh 2 - 3 - # clippr: a social bookmarking service for the AT Protocol 4 - # Copyright (c) 2025 clippr contributors. 5 - # SPDX-License-Identifier: AGPL-3.0-only 6 - 7 - dart run build_runner build 8 - dart run bin/clippr.dart
+24
backend/tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "esModuleInterop": true, 4 + "skipLibCheck": true, 5 + "target": "es2022", 6 + "allowJs": true, 7 + "resolveJsonModule": true, 8 + "moduleDetection": "force", 9 + "isolatedModules": true, 10 + "verbatimModuleSyntax": true, 11 + 12 + "strict": true, 13 + "noUncheckedIndexedAccess": true, 14 + "noImplicitOverride": true, 15 + 16 + "module": "preserve", 17 + "noEmit": true, 18 + 19 + "jsx": "react-jsx", 20 + "jsxImportSource": "hono/jsx", 21 + 22 + "lib": ["es2022"] 23 + } 24 + }