Type-safe Router for Vue and Svelte, powered by Navigation API. Inspired by SvelteKit, TanStack Router, Vue Router.
ruta view-transition ruta-vue ruta-svelte router vue svelte navigation-api
0
fork

Configure Feed

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

chore: setup typechecking & linting

jeffydc.xyz 69e53aff 2ce39bd0

verified
+103 -48
+13
.oxlintrc.json
··· 1 + { 2 + "$schema": "./node_modules/oxlint/configuration_schema.json", 3 + "plugins": ["eslint", "typescript", "unicorn", "oxc", "vue"], 4 + "env": { 5 + "browser": true 6 + }, 7 + "categories": { 8 + "correctness": "error" 9 + }, 10 + "rules": { 11 + "no-unused-expressions": "warn" 12 + } 13 + }
+4
.tangled/workflows/test.yml
··· 11 11 command: nix develop -c pnpm t 12 12 - name: nix develop -c pnpm fmt-check 13 13 command: nix develop -c pnpm fmt-check 14 + - name: nix develop -c pnpm lint 15 + command: nix develop -c pnpm lint packages 16 + - name: nix develop -c pnpm typecheck 17 + command: nix develop -c pnpm typecheck
+4 -1
package.json
··· 12 12 "preview-svelte": "pnpm run --filter play-svelte preview", 13 13 "fmt": "oxfmt", 14 14 "fmt-check": "oxfmt --check", 15 - "lint": "oxlint --type-aware --type-check --fix --vue-plugin", 15 + "lint": "oxlint --type-check", 16 + "lint-fix": "oxlint --type-check --fix", 16 17 "typecheck": "pnpm run -r --parallel typecheck", 17 18 "test": "pnpm run -r --parallel test" 18 19 }, 19 20 "devDependencies": { 20 21 "@sveltejs/vite-plugin-svelte": "6.2.4", 22 + "@tsconfig/node-lts": "24.0.0", 21 23 "@types/node": "25.0.10", 22 24 "@vitejs/plugin-vue": "6.0.3", 23 25 "@vitest/coverage-v8": "4.0.18", 24 26 "@vitest/ui": "4.0.18", 27 + "@vue/tsconfig": "0.8.1", 25 28 "oxfmt": "0.27.0", 26 29 "oxlint": "1.42.0", 27 30 "typescript": "5.9.3",
+2 -2
packages/ruta-core/internal.test.ts
··· 190 190 const after1 = vi.fn(); 191 191 const after2 = vi.fn(); 192 192 const b1 = ruta.before(before1); 193 - const b2 = ruta.after(after1); 194 - const a1 = ruta.before(before2); 193 + ruta.after(after1); 194 + ruta.before(before2); 195 195 const a2 = ruta.after(after2); 196 196 197 197 b1();
+6 -3
packages/ruta-core/internal.ts
··· 178 178 // call navigate hooks if available 179 179 if (hooks.length) { 180 180 const hookArgs = this.#makeHookArgs(); 181 - const results = await Promise.all( 181 + await Promise.all( 182 182 hooks.map((hook) => 183 183 // wrap in async IIFE to catch all sync/async errors 184 184 (async () => hook(hookArgs))(), ··· 333 333 334 334 let index = 0; 335 335 let found = true; // true first to add root node data 336 - while (1) { 336 + while (true) { 337 337 // root route is always matched, so need to add its data 338 338 // first, and continue the lookup. 339 339 if (found) { ··· 411 411 dynNode.data.parseParams ? dynNode.data.parseParams(filtered) : filtered, 412 412 ); 413 413 } catch (e) { 414 + this.#capturedError = e; 414 415 // `parseParams` function can throw error to not match the params 415 416 return null; 416 417 } ··· 425 426 // components are simply functions 426 427 // @ts-expect-error __ruta is added in node insertion to Trie 427 428 if (comp && comp.__ruta && typeof comp === 'function') { 428 - const promise = comp() 429 + // Without typecasting here, typechecking in 430 + // ruta-vue, ruta-svelte fails. 431 + const promise = (comp as RouteComponentLazy)() 429 432 .then((c) => { 430 433 // replace with the resolved component 431 434 return (route.comps[i] = c.default);
+3
packages/ruta-core/mod.ts
··· 1 + /// <reference types="@types/dom-navigation" /> 2 + /// <reference types="urlpattern-polyfill" /> 3 + 1 4 export { Ruta, createRouteBuilder, createEmptyRoute, warn } from './internal.ts'; 2 5 export type { RutaOptions, Route, Register } from './internal.ts';
+3 -1
packages/ruta-core/package.json
··· 8 8 "./vite": "./vite-plugin.ts" 9 9 }, 10 10 "scripts": { 11 + "typecheck": "tsc -b", 11 12 "test": "vitest --typecheck" 12 13 }, 13 14 "dependencies": { ··· 15 16 "esm-env": "1.2.2" 16 17 }, 17 18 "devDependencies": { 18 - "@types/dom-navigation": "1.0.6" 19 + "@types/dom-navigation": "1.0.6", 20 + "urlpattern-polyfill": "10.1.0" 19 21 }, 20 22 "peerDependencies": { 21 23 "vite": "^7"
+9
packages/ruta-core/tsconfig.dom.json
··· 1 + { 2 + "extends": "@vue/tsconfig/tsconfig.dom.json", 3 + "include": ["*.ts"], 4 + "exclude": ["vite-plugin*.ts"], 5 + "compilerOptions": { 6 + "lib": ["ESNext", "DOM", "DOM.Iterable"], 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.dom.tsbuildinfo" 8 + } 9 + }
+2 -3
packages/ruta-core/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json", 3 - "include": ["."], 4 - "exclude": ["node_modules"] 2 + "files": [], 3 + "references": [{ "path": "./tsconfig.dom.json" }, { "path": "./tsconfig.node.json" }] 5 4 }
+8
packages/ruta-core/tsconfig.node.json
··· 1 + { 2 + "extends": ["@tsconfig/node-lts/tsconfig.json", "@vue/tsconfig/tsconfig.json"], 3 + "include": ["vite-plugin*.ts"], 4 + "compilerOptions": { 5 + "lib": ["ESNext"], 6 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" 7 + } 8 + }
+2 -1
packages/ruta-core/vite-plugin.test.ts
··· 1 + import type { VitePluginRutaOptions } from './vite-plugin.ts'; 1 2 import { test, expect } from 'vitest'; 2 3 3 - import { VPR, VitePluginRutaOptions } from './vite-plugin.ts'; 4 + import { VPR } from './vite-plugin.ts'; 4 5 5 6 function makeOptions(options?: VitePluginRutaOptions) { 6 7 return {
+1
packages/ruta-svelte/components.ts
··· 1 + export default '';
+3
packages/ruta-svelte/package.json
··· 8 8 "./vite": "./vite-plugin.ts", 9 9 "./components": "./components.ts" 10 10 }, 11 + "scripts": { 12 + "typecheck": "tsc -b" 13 + }, 11 14 "dependencies": { 12 15 "@jeffydc/ruta-core": "workspace:*" 13 16 },
+9
packages/ruta-svelte/tsconfig.dom.json
··· 1 + { 2 + "extends": "@vue/tsconfig/tsconfig.dom.json", 3 + "include": ["*.ts"], 4 + "exclude": ["vite-plugin*.ts", "../ruta-vue", "../ruta-core"], 5 + "compilerOptions": { 6 + "lib": ["ESNext", "DOM", "DOM.Iterable"], 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.dom.tsbuildinfo" 8 + } 9 + }
+2 -3
packages/ruta-svelte/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json", 3 - "include": ["."], 4 - "exclude": ["node_modules", "../ruta-vue"] 2 + "files": [], 3 + "references": [{ "path": "./tsconfig.dom.json" }, { "path": "./tsconfig.node.json" }] 5 4 }
+9
packages/ruta-svelte/tsconfig.node.json
··· 1 + { 2 + "extends": ["@tsconfig/node-lts/tsconfig.json", "@vue/tsconfig/tsconfig.json"], 3 + "include": ["vite-plugin*.ts"], 4 + "exclude": ["../ruta-vue", "../ruta-core"], 5 + "compilerOptions": { 6 + "lib": ["ESNext"], 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" 8 + } 9 + }
packages/ruta-vue/components.ts

This is a binary file and will not be displayed.

+3
packages/ruta-vue/package.json
··· 7 7 ".": "./mod.ts", 8 8 "./vite": "./vite-plugin.ts" 9 9 }, 10 + "scripts": { 11 + "typecheck": "tsc -b" 12 + }, 10 13 "dependencies": { 11 14 "@jeffydc/ruta-core": "workspace:*" 12 15 },
+9
packages/ruta-vue/tsconfig.dom.json
··· 1 + { 2 + "extends": "@vue/tsconfig/tsconfig.dom.json", 3 + "include": ["*.ts"], 4 + "exclude": ["vite-plugin*.ts", "../ruta-svelte"], 5 + "compilerOptions": { 6 + "lib": ["ESNext", "DOM", "DOM.Iterable"], 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.dom.tsbuildinfo" 8 + } 9 + }
+2 -3
packages/ruta-vue/tsconfig.json
··· 1 1 { 2 - "extends": "../../tsconfig.json", 3 - "include": ["."], 4 - "exclude": ["node_modules", "../ruta-svelte"] 2 + "files": [], 3 + "references": [{ "path": "./tsconfig.dom.json" }, { "path": "./tsconfig.node.json" }] 5 4 }
+9
packages/ruta-vue/tsconfig.node.json
··· 1 + { 2 + "extends": ["@tsconfig/node-lts/tsconfig.json", "@vue/tsconfig/tsconfig.json"], 3 + "include": ["vite-plugin*.ts"], 4 + "exclude": ["../ruta-svelte"], 5 + "compilerOptions": { 6 + "lib": ["ESNext"], 7 + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" 8 + } 9 + }
-1
playgrounds/play-vue/package.json
··· 11 11 "devDependencies": { 12 12 "@jeffydc/ruta-vue": "workspace:*", 13 13 "@tanstack/vue-query": "5.92.9", 14 - "@vue/tsconfig": "0.8.1", 15 14 "vue": "3.5.27", 16 15 "vue-tsc": "3.2.4" 17 16 }
-30
tsconfig.json
··· 1 - { 2 - "exclude": ["dist"], 3 - "compilerOptions": { 4 - // https://www.totaltypescript.com/tsconfig-cheat-sheet 5 - /* Base Options: */ 6 - "esModuleInterop": true, 7 - "skipLibCheck": false, 8 - "target": "ESNext", 9 - "allowJs": true, 10 - "allowImportingTsExtensions": true, 11 - "resolveJsonModule": true, 12 - "moduleDetection": "force", 13 - "isolatedModules": true, 14 - 15 - /* Strictness */ 16 - "strict": true, 17 - "noUncheckedIndexedAccess": true, 18 - 19 - /* If NOT transpiling with TypeScript: */ 20 - "moduleResolution": "Bundler", 21 - "module": "ESNext", 22 - "noEmit": true, 23 - "lib": ["ESNext", "DOM", "DOM.Iterable"], 24 - 25 - /* Extra */ 26 - "checkJs": true, 27 - "jsx": "preserve", 28 - "jsxImportSource": "solid-js" 29 - } 30 - }