sv-router 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/package.json +69 -74
  2. package/{dist → src}/RecursiveComponentTree.svelte +4 -4
  3. package/{dist → src}/Router.svelte +2 -2
  4. package/src/cli/index.js +13 -0
  5. package/src/create-router.svelte.js +67 -0
  6. package/src/gen/config.js +16 -0
  7. package/src/gen/generate-router-code.js +102 -0
  8. package/src/gen/write-router-code.js +52 -0
  9. package/src/helpers/match-route.js +112 -0
  10. package/src/helpers/utils.js +46 -0
  11. package/src/helpers/validate-routes.js +46 -0
  12. package/src/index.d.ts +77 -0
  13. package/src/index.js +2 -0
  14. package/src/vite-plugin/index.d.ts +12 -0
  15. package/src/vite-plugin/index.js +1 -0
  16. package/src/vite-plugin/plugin.js +42 -0
  17. package/dist/RecursiveComponentTree.svelte.d.ts +0 -8
  18. package/dist/cli/index.d.ts +0 -2
  19. package/dist/cli/index.js +0 -3
  20. package/dist/common.d.ts +0 -5
  21. package/dist/common.js +0 -6
  22. package/dist/gen/generate-router-code.d.ts +0 -12
  23. package/dist/gen/generate-router-code.js +0 -67
  24. package/dist/gen/generate-router-code.test.d.ts +0 -1
  25. package/dist/gen/generate-router-code.test.js +0 -103
  26. package/dist/gen/write-router-code.d.ts +0 -1
  27. package/dist/gen/write-router-code.js +0 -36
  28. package/dist/helpers/match-route.d.ts +0 -7
  29. package/dist/helpers/match-route.js +0 -66
  30. package/dist/helpers/match-route.test.d.ts +0 -1
  31. package/dist/helpers/match-route.test.js +0 -146
  32. package/dist/helpers/utils.d.ts +0 -8
  33. package/dist/helpers/utils.js +0 -28
  34. package/dist/helpers/validate-routes.d.ts +0 -3
  35. package/dist/helpers/validate-routes.js +0 -34
  36. package/dist/helpers/validate-routes.test.d.ts +0 -1
  37. package/dist/helpers/validate-routes.test.js +0 -67
  38. package/dist/index.d.ts +0 -2
  39. package/dist/index.js +0 -2
  40. package/dist/router.svelte.d.ts +0 -13
  41. package/dist/router.svelte.js +0 -49
  42. package/dist/types/test-types.d.ts +0 -1
  43. package/dist/types/test-types.js +0 -1
  44. package/dist/types/types.d.ts +0 -26
  45. package/dist/types/types.js +0 -1
  46. package/dist/vite-plugin/index.d.ts +0 -1
  47. package/dist/vite-plugin/index.js +0 -1
  48. package/dist/vite-plugin/plugin.d.ts +0 -2
  49. package/dist/vite-plugin/plugin.js +0 -31
@@ -1,34 +0,0 @@
1
- export function validateRoutes(routes) {
2
- const paths = getRoutePaths(routes);
3
- const wildcardPaths = paths.filter((path) => path.endsWith('*'));
4
- for (const wildcardPath of wildcardPaths) {
5
- const parentPath = wildcardPath.slice(0, -1);
6
- const dynamicPath = paths.find((p) => p !== '/' &&
7
- !p.endsWith('*') &&
8
- p.startsWith(parentPath === '' ? '/:' : parentPath) &&
9
- p.match(/:[^/]*$/g));
10
- if (dynamicPath) {
11
- console.warn(`Router warning: Wildcard route \`${wildcardPath}\` should not be at the same level as dynamic route \`${dynamicPath}\`.`);
12
- }
13
- }
14
- }
15
- export function getRoutePaths(routes) {
16
- const paths = [];
17
- for (const [key, value] of Object.entries(routes)) {
18
- if (typeof value === 'object') {
19
- paths.push(...getRoutePaths(value).map((path) => {
20
- if (path === '*') {
21
- return key + '/*';
22
- }
23
- if (path === '/') {
24
- return key;
25
- }
26
- return key + path;
27
- }));
28
- }
29
- else {
30
- paths.push(key);
31
- }
32
- }
33
- return paths;
34
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,67 +0,0 @@
1
- import { getRoutePaths, validateRoutes } from "./validate-routes.js";
2
- const component = (() => ({}));
3
- const consoleSpy = vi.spyOn(console, 'warn').mockImplementation(vi.fn());
4
- beforeEach(() => {
5
- vi.clearAllMocks();
6
- });
7
- describe('validateRoutes', () => {
8
- it('should validate routes', () => {
9
- validateRoutes({
10
- '/': component,
11
- '/about': component,
12
- '/posts': {
13
- '/': component,
14
- '/:id': component,
15
- },
16
- '*': component,
17
- });
18
- expect(consoleSpy).not.toHaveBeenCalled();
19
- });
20
- it('should raise a warning if a wildcard route is at the same level as a dynamic route', () => {
21
- validateRoutes({
22
- '/': component,
23
- '/:id': component,
24
- '*': component,
25
- });
26
- expect(consoleSpy).toHaveBeenCalledWith('Router warning: Wildcard route `*` should not be at the same level as dynamic route `/:id`.');
27
- });
28
- it.each([
29
- {
30
- '/': component,
31
- '/posts/*': component,
32
- '/posts/:id': component,
33
- '/:id': component,
34
- '*': component,
35
- },
36
- {
37
- '/': component,
38
- '/posts': {
39
- '*': component,
40
- '/:id': component,
41
- },
42
- '/:id': component,
43
- '*': component,
44
- },
45
- ])('should raise multiple warnings if wildcard routes are at the same level as dynamic routes', (routes) => {
46
- validateRoutes(routes);
47
- expect(consoleSpy).toHaveBeenCalledTimes(2);
48
- expect(consoleSpy).toHaveBeenCalledWith('Router warning: Wildcard route `*` should not be at the same level as dynamic route `/:id`.');
49
- expect(consoleSpy).toHaveBeenCalledWith('Router warning: Wildcard route `/posts/*` should not be at the same level as dynamic route `/posts/:id`.');
50
- });
51
- });
52
- describe('getRoutePaths', () => {
53
- it('should return all paths in an array', () => {
54
- const result = getRoutePaths({
55
- '/': component,
56
- '/about': component,
57
- '/posts': {
58
- '/': component,
59
- '/:id': component,
60
- '*': component,
61
- },
62
- '/foo/bar': component,
63
- '*': component,
64
- });
65
- expect(result).toEqual(['/', '/about', '/posts', '/posts/:id', '/posts/*', '/foo/bar', '*']);
66
- });
67
- });
package/dist/index.d.ts DELETED
@@ -1,2 +0,0 @@
1
- export { default as Router } from './Router.svelte';
2
- export { createRouter } from './router.svelte.ts';
package/dist/index.js DELETED
@@ -1,2 +0,0 @@
1
- export { default as Router } from './Router.svelte';
2
- export { createRouter } from "./router.svelte.js";
@@ -1,13 +0,0 @@
1
- import type { Component } from 'svelte';
2
- import { type ConstructPathArgs } from './helpers/utils.ts';
3
- import type { AllParams, Path, Routes } from './types/types.ts';
4
- export declare let routes: Routes;
5
- export declare const componentTree: Component<{}, {}, string>[];
6
- export declare const paramsStore: Record<string, string>;
7
- export declare function createRouter<T extends Routes>(r: T): {
8
- path<U extends Path<T>>(...args: ConstructPathArgs<U>): string;
9
- goto<U extends Path<T>>(...args: ConstructPathArgs<U>): void;
10
- params(): AllParams<T>;
11
- };
12
- export declare function onNavigate(): void;
13
- export declare function onGlobalClick(event: Event): void;
@@ -1,49 +0,0 @@
1
- import { BROWSER, DEV } from 'esm-env';
2
- import { matchRoute } from "./helpers/match-route.js";
3
- import { constructPath, resolveRouteComponents } from "./helpers/utils.js";
4
- export let routes;
5
- export const componentTree = $state([]);
6
- export const paramsStore = $state({});
7
- export function createRouter(r) {
8
- routes = r;
9
- if (DEV && BROWSER) {
10
- import('./helpers/validate-routes.js').then(({ validateRoutes }) => {
11
- validateRoutes(routes);
12
- });
13
- }
14
- return {
15
- path(...args) {
16
- return constructPath(...args);
17
- },
18
- goto(...args) {
19
- const path = constructPath(...args);
20
- globalThis.history.pushState({}, '', path);
21
- onNavigate();
22
- },
23
- params() {
24
- const readonly = $derived(paramsStore);
25
- return readonly;
26
- },
27
- };
28
- }
29
- export function onNavigate() {
30
- const { match, layouts, params } = matchRoute(globalThis.location.pathname, routes);
31
- resolveRouteComponents(match ? [...layouts, match] : layouts).then((components) => {
32
- Object.assign(componentTree, components);
33
- });
34
- Object.assign(paramsStore, params);
35
- }
36
- export function onGlobalClick(event) {
37
- const anchor = event.target.closest('a');
38
- if (!anchor)
39
- return;
40
- if (anchor.hasAttribute('target') || anchor.hasAttribute('download'))
41
- return;
42
- const url = new URL(anchor.href);
43
- const currentOrigin = globalThis.location.origin;
44
- if (url.origin !== currentOrigin)
45
- return;
46
- event.preventDefault();
47
- globalThis.history.pushState({}, '', anchor.href);
48
- onNavigate();
49
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1,26 +0,0 @@
1
- import type { Component, Snippet } from 'svelte';
2
- type BaseProps = Record<string, any>;
3
- export type LazyRouteComponent<Props extends BaseProps = BaseProps> = () => Promise<{
4
- default: Component<Props>;
5
- }>;
6
- export type RouteComponent<Props extends BaseProps = BaseProps> = Component<Props> | LazyRouteComponent<Props>;
7
- export type LayoutComponent = RouteComponent<{
8
- children: Snippet;
9
- }>;
10
- export type Routes = {
11
- [_: `/${string}`]: RouteComponent | Routes;
12
- '*'?: RouteComponent;
13
- layout?: LayoutComponent;
14
- };
15
- export type Path<T extends Routes> = RemoveLastSlash<RecursiveKeys<StripNonRoutes<T>>>;
16
- export type PathParams<T extends string> = ExtractParams<T> extends never ? never : Record<ExtractParams<T>, string>;
17
- export type AllParams<T extends Routes> = Partial<Record<ExtractParams<RecursiveKeys<T>>, string>>;
18
- type StripNonRoutes<T extends Routes> = {
19
- [K in keyof T as K extends '*' ? never : K extends 'layout' ? never : K]: T[K] extends Routes ? StripNonRoutes<T[K]> : T[K];
20
- };
21
- type RecursiveKeys<T extends Routes, Prefix extends string = ''> = {
22
- [K in keyof T]: K extends string ? T[K] extends Routes ? RecursiveKeys<T[K], `${Prefix}${K}`> : `${Prefix}${K}` : never;
23
- }[keyof T];
24
- type RemoveLastSlash<T extends string> = T extends '/' ? T : T extends `${infer R}/` ? R : T;
25
- type ExtractParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}` ? Param | ExtractParams<`/${Rest}`> : T extends `${string}:${infer Param}` ? Param : never;
26
- export {};
@@ -1 +0,0 @@
1
- export {};
@@ -1 +0,0 @@
1
- export { router } from './plugin.ts';
@@ -1 +0,0 @@
1
- export { router } from "./plugin.js";
@@ -1,2 +0,0 @@
1
- import type { Plugin } from 'vite';
2
- export declare function router(): Plugin;
@@ -1,31 +0,0 @@
1
- import path from 'node:path';
2
- import { GEN_CODE_ALIAS, ROUTER_PATH, ROUTES_PATH } from "../common.js";
3
- import { writeRouterCode } from "../gen/write-router-code.js";
4
- export function router() {
5
- return {
6
- name: 'sv-router',
7
- config(config) {
8
- if (!config.resolve) {
9
- config.resolve = {};
10
- }
11
- if (!config.resolve.alias) {
12
- config.resolve.alias = {};
13
- }
14
- const replacement = path.resolve(process.cwd(), ROUTER_PATH);
15
- if (Array.isArray(config.resolve.alias)) {
16
- config.resolve.alias.push({ find: GEN_CODE_ALIAS, replacement });
17
- }
18
- else {
19
- config.resolve.alias[GEN_CODE_ALIAS] = replacement;
20
- }
21
- },
22
- buildStart() {
23
- writeRouterCode();
24
- },
25
- watchChange(file) {
26
- if (file.includes(ROUTES_PATH)) {
27
- writeRouterCode();
28
- }
29
- },
30
- };
31
- }