[READ-ONLY] Mirror of https://github.com/probablykasper/starchart. GitHub star history graph starchart.kasper.space
chart github github-api github-star graph history star star-history stargazers stars
0

Configure Feed

Select the types of activity you want to include in your feed.

Add throttling and retries

Kasper (May 13, 2025, 9:42 PM +0200) 4d436cd6 54eeda90

+145 -14
+11 -7
eslint.config.js
··· 1 - import prettier from 'eslint-config-prettier' 2 1 import js from '@eslint/js' 2 + import ts from 'typescript-eslint' 3 3 import svelte from 'eslint-plugin-svelte' 4 + import prettier from 'eslint-config-prettier' 4 5 import globals from 'globals' 5 - import ts from 'typescript-eslint' 6 6 7 7 /** @type {import('eslint').Linter.Config[]} */ 8 8 export default [ ··· 24 24 languageOptions: { 25 25 parserOptions: { 26 26 parser: ts.parser, 27 - svelteFeatures: { 28 - experimentalGenerics: true, 29 - }, 30 27 }, 31 28 }, 32 29 }, ··· 39 36 'error', 40 37 { 41 38 selector: 'variableLike', 42 - format: ['snake_case', 'UPPER_CASE'], 39 + format: ['snake_case', 'UPPER_CASE', 'PascalCase'], 43 40 leadingUnderscore: 'allow', 44 41 }, 45 42 { ··· 56 53 '@typescript-eslint/no-unused-expressions': 'off', 57 54 '@typescript-eslint/no-unused-vars': [ 58 55 'error', 59 - { caughtErrorsIgnorePattern: '^_', argsIgnorePattern: '^_', varsIgnorePattern: '^_' }, 56 + { 57 + caughtErrorsIgnorePattern: '^_', 58 + argsIgnorePattern: '^_', 59 + varsIgnorePattern: '^_', 60 + }, 60 61 ], 62 + eqeqeq: ['error', 'always'], 61 63 'svelte/button-has-type': 'error', 64 + 'svelte/require-each-key': 'off', 65 + 'svelte/no-reactive-reassign': 'off', 62 66 }, 63 67 }, 64 68 ]
+99 -4
package-lock.json
··· 7 7 "devDependencies": { 8 8 "@ctrl/tinycolor": "^4.1.0", 9 9 "@octokit/core": "^6.1.4", 10 + "@octokit/plugin-retry": "^7.2.1", 11 + "@octokit/plugin-throttling": "^10.0.0", 10 12 "@sveltejs/adapter-cloudflare": "^5.0.3", 11 13 "@sveltejs/kit": "^2.19.0", 12 14 "@sveltejs/vite-plugin-svelte": "^5.0.3", ··· 1438 1440 "dev": true, 1439 1441 "license": "MIT" 1440 1442 }, 1443 + "node_modules/@octokit/plugin-retry": { 1444 + "version": "7.2.1", 1445 + "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-7.2.1.tgz", 1446 + "integrity": "sha512-wUc3gv0D6vNHpGxSaR3FlqJpTXGWgqmk607N9L3LvPL4QjaxDgX/1nY2mGpT37Khn+nlIXdljczkRnNdTTV3/A==", 1447 + "dev": true, 1448 + "license": "MIT", 1449 + "dependencies": { 1450 + "@octokit/request-error": "^6.1.8", 1451 + "@octokit/types": "^14.0.0", 1452 + "bottleneck": "^2.15.3" 1453 + }, 1454 + "engines": { 1455 + "node": ">= 18" 1456 + }, 1457 + "peerDependencies": { 1458 + "@octokit/core": ">=6" 1459 + } 1460 + }, 1461 + "node_modules/@octokit/plugin-retry/node_modules/@octokit/openapi-types": { 1462 + "version": "25.0.0", 1463 + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz", 1464 + "integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==", 1465 + "dev": true, 1466 + "license": "MIT" 1467 + }, 1468 + "node_modules/@octokit/plugin-retry/node_modules/@octokit/types": { 1469 + "version": "14.0.0", 1470 + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz", 1471 + "integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==", 1472 + "dev": true, 1473 + "license": "MIT", 1474 + "dependencies": { 1475 + "@octokit/openapi-types": "^25.0.0" 1476 + } 1477 + }, 1478 + "node_modules/@octokit/plugin-throttling": { 1479 + "version": "10.0.0", 1480 + "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-10.0.0.tgz", 1481 + "integrity": "sha512-Kuq5/qs0DVYTHZuBAzCZStCzo2nKvVRo/TDNhCcpC2TKiOGz/DisXMCvjt3/b5kr6SCI1Y8eeeJTHBxxpFvZEg==", 1482 + "dev": true, 1483 + "license": "MIT", 1484 + "dependencies": { 1485 + "@octokit/types": "^14.0.0", 1486 + "bottleneck": "^2.15.3" 1487 + }, 1488 + "engines": { 1489 + "node": ">= 18" 1490 + }, 1491 + "peerDependencies": { 1492 + "@octokit/core": "^6.1.3" 1493 + } 1494 + }, 1495 + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/openapi-types": { 1496 + "version": "25.0.0", 1497 + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz", 1498 + "integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==", 1499 + "dev": true, 1500 + "license": "MIT" 1501 + }, 1502 + "node_modules/@octokit/plugin-throttling/node_modules/@octokit/types": { 1503 + "version": "14.0.0", 1504 + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz", 1505 + "integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==", 1506 + "dev": true, 1507 + "license": "MIT", 1508 + "dependencies": { 1509 + "@octokit/openapi-types": "^25.0.0" 1510 + } 1511 + }, 1441 1512 "node_modules/@octokit/request": { 1442 1513 "version": "9.2.2", 1443 1514 "resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.2.tgz", ··· 1456 1527 } 1457 1528 }, 1458 1529 "node_modules/@octokit/request-error": { 1459 - "version": "6.1.7", 1460 - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.7.tgz", 1461 - "integrity": "sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==", 1530 + "version": "6.1.8", 1531 + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz", 1532 + "integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==", 1462 1533 "dev": true, 1463 1534 "license": "MIT", 1464 1535 "dependencies": { 1465 - "@octokit/types": "^13.6.2" 1536 + "@octokit/types": "^14.0.0" 1466 1537 }, 1467 1538 "engines": { 1468 1539 "node": ">= 18" 1540 + } 1541 + }, 1542 + "node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": { 1543 + "version": "25.0.0", 1544 + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.0.0.tgz", 1545 + "integrity": "sha512-FZvktFu7HfOIJf2BScLKIEYjDsw6RKc7rBJCdvCTfKsVnx2GEB/Nbzjr29DUdb7vQhlzS/j8qDzdditP0OC6aw==", 1546 + "dev": true, 1547 + "license": "MIT" 1548 + }, 1549 + "node_modules/@octokit/request-error/node_modules/@octokit/types": { 1550 + "version": "14.0.0", 1551 + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.0.0.tgz", 1552 + "integrity": "sha512-VVmZP0lEhbo2O1pdq63gZFiGCKkm8PPp8AUOijlwPO6hojEVjspA0MWKP7E4hbvGxzFKNqKr6p0IYtOH/Wf/zA==", 1553 + "dev": true, 1554 + "license": "MIT", 1555 + "dependencies": { 1556 + "@octokit/openapi-types": "^25.0.0" 1469 1557 } 1470 1558 }, 1471 1559 "node_modules/@octokit/types": { ··· 2521 2609 "dev": true, 2522 2610 "license": "MIT", 2523 2611 "peer": true 2612 + }, 2613 + "node_modules/bottleneck": { 2614 + "version": "2.19.5", 2615 + "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", 2616 + "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==", 2617 + "dev": true, 2618 + "license": "MIT" 2524 2619 }, 2525 2620 "node_modules/brace-expansion": { 2526 2621 "version": "1.1.11",
+2
package.json
··· 11 11 "devDependencies": { 12 12 "@ctrl/tinycolor": "^4.1.0", 13 13 "@octokit/core": "^6.1.4", 14 + "@octokit/plugin-retry": "^7.2.1", 15 + "@octokit/plugin-throttling": "^10.0.0", 14 16 "@sveltejs/adapter-cloudflare": "^5.0.3", 15 17 "@sveltejs/kit": "^2.19.0", 16 18 "@sveltejs/vite-plugin-svelte": "^5.0.3",
+32 -2
src/routes/github.ts
··· 3 3 import { PUBLIC_PAT } from '$env/static/public' 4 4 import { get, writable } from 'svelte/store' 5 5 import { browser } from '$app/environment' 6 + import { throttling } from '@octokit/plugin-throttling' 7 + import { retry } from '@octokit/plugin-retry' 6 8 7 9 const loaded_token = browser ? localStorage.getItem('starchart-token') : undefined 8 10 export const token = writable(loaded_token || '') ··· 16 18 }) 17 19 } 18 20 19 - const octokit = new Octokit({ 21 + export const errors = writable<string[]>([]) 22 + 23 + const MyOctokit = Octokit.plugin(throttling, retry) 24 + const octokit = new MyOctokit({ 20 25 auth: get(token) || PUBLIC_PAT, 21 - throttle: { enabled: false }, 26 + throttle: { 27 + onRateLimit(retry_after, options, octokit, retry_count) { 28 + console.log('onRateLimi', retry_after, options, octokit, retry_count) 29 + const retry_message = ` Retrying in ${retry_after} seconds.` 30 + const max_retries = 3 31 + if (retry_count < max_retries) { 32 + errors.update((errors) => { 33 + errors.push(`Rate limit reached.${retry_message}`) 34 + return errors 35 + }) 36 + return true 37 + } 38 + errors.update((errors) => { 39 + errors.push(`Rate limit reached ${max_retries} times.`) 40 + return errors 41 + }) 42 + }, 43 + onSecondaryRateLimit(retry_after, options, octokit, retry_count) { 44 + console.log('onSecondaryRateLimi', retry_after, options, octokit, retry_count) 45 + const retry_message = `Retrying in ${retry_after} seconds.` 46 + errors.update((errors) => { 47 + errors.push(`Rate limit reached.${retry_message}`) 48 + return errors 49 + }) 50 + }, 51 + }, 22 52 }) 23 53 24 54 export async function fetch_stargazers_page(
+1 -1
src/routes/shortcuts.ts
··· 7 7 8 8 export function check_modifiers(e: KeyboardEvent | MouseEvent, options: ShortcutOptions = {}) { 9 9 if (is_mac === undefined) { 10 - is_mac = navigator.userAgent.indexOf('Mac') != -1 10 + is_mac = navigator.userAgent.indexOf('Mac') !== -1 11 11 } 12 12 13 13 const target = {