typed-next-router 0.0.1
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.
- package/dist/index.cjs +113 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.tsx
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
Link: () => Link,
|
|
34
|
+
buildHref: () => buildHref,
|
|
35
|
+
useTypedRouter: () => useTypedRouter,
|
|
36
|
+
useTypedSearchParams: () => useTypedSearchParams
|
|
37
|
+
});
|
|
38
|
+
module.exports = __toCommonJS(index_exports);
|
|
39
|
+
|
|
40
|
+
// src/Link.tsx
|
|
41
|
+
var import_link = __toESM(require("next/link"), 1);
|
|
42
|
+
|
|
43
|
+
// src/utils.ts
|
|
44
|
+
function buildHref(href) {
|
|
45
|
+
let url = href.path;
|
|
46
|
+
if (href.pathParams) {
|
|
47
|
+
Object.entries(href.pathParams).forEach(([key, value]) => {
|
|
48
|
+
url = url.replace(`[${key}]`, value);
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (href.queryParams && Object.keys(href.queryParams).length > 0) {
|
|
52
|
+
const params = new URLSearchParams(href.queryParams);
|
|
53
|
+
url = `${url}?${params.toString()}`;
|
|
54
|
+
}
|
|
55
|
+
return url;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/Link.tsx
|
|
59
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
60
|
+
function Link(props) {
|
|
61
|
+
const { href, children, ...rest } = props;
|
|
62
|
+
const builtHref = buildHref(href);
|
|
63
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_link.default, { href: builtHref, ...rest, children });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// src/useTypedRouter.ts
|
|
67
|
+
var import_navigation = require("next/navigation");
|
|
68
|
+
var import_react = require("react");
|
|
69
|
+
var useTypedRouter = () => {
|
|
70
|
+
const router = (0, import_navigation.useRouter)();
|
|
71
|
+
const push = (0, import_react.useCallback)(
|
|
72
|
+
(href, options) => {
|
|
73
|
+
const builtHref = buildHref(href);
|
|
74
|
+
router.push(builtHref, options);
|
|
75
|
+
},
|
|
76
|
+
[router.push]
|
|
77
|
+
);
|
|
78
|
+
const replace = (0, import_react.useCallback)(
|
|
79
|
+
(href, options) => {
|
|
80
|
+
const builtHref = buildHref(href);
|
|
81
|
+
router.replace(builtHref, options);
|
|
82
|
+
},
|
|
83
|
+
[router.replace]
|
|
84
|
+
);
|
|
85
|
+
const prefetch = (0, import_react.useCallback)(
|
|
86
|
+
(href, options) => {
|
|
87
|
+
const builtHref = buildHref(href);
|
|
88
|
+
router.prefetch(builtHref, options);
|
|
89
|
+
},
|
|
90
|
+
[router.prefetch]
|
|
91
|
+
);
|
|
92
|
+
return {
|
|
93
|
+
...router,
|
|
94
|
+
push,
|
|
95
|
+
replace,
|
|
96
|
+
prefetch
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// src/useTypedSearchParams.ts
|
|
101
|
+
var import_navigation2 = require("next/navigation");
|
|
102
|
+
var useTypedSearchParams = (path) => {
|
|
103
|
+
const searchParams = (0, import_navigation2.useSearchParams)();
|
|
104
|
+
return searchParams;
|
|
105
|
+
};
|
|
106
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
107
|
+
0 && (module.exports = {
|
|
108
|
+
Link,
|
|
109
|
+
buildHref,
|
|
110
|
+
useTypedRouter,
|
|
111
|
+
useTypedSearchParams
|
|
112
|
+
});
|
|
113
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.tsx","../src/Link.tsx","../src/utils.ts","../src/useTypedRouter.ts","../src/useTypedSearchParams.ts"],"sourcesContent":["export { Link } from './Link';\n\nexport type { RouteMapShape, RouteRegistry } from './route-registry';\nexport type {\n\tExtractParams,\n\tPathParams,\n\tPathType,\n\tQueryParamName,\n\tQueryParams,\n\tQueryParamValue,\n\tTypedHref,\n} from './types';\n\nexport { useTypedRouter } from './useTypedRouter';\nexport { useTypedSearchParams } from './useTypedSearchParams';\nexport { buildHref } from './utils';\n","import type { LinkProps as NextLinkProps } from 'next/link';\nimport NextLink from 'next/link';\nimport type { ComponentProps } from 'react';\nimport type { PathType, TypedHref } from './types';\nimport { buildHref } from './utils';\n\ntype LinkProps<P extends PathType> = Omit<NextLinkProps, 'href'> &\n\tOmit<ComponentProps<'a'>, 'href'> & {\n\t\thref: TypedHref<P>;\n\t};\n\nfunction Link<P extends PathType>(props: LinkProps<P>) {\n\tconst { href, children, ...rest } = props;\n\n\tconst builtHref = buildHref(href);\n\n\treturn (\n\t\t<NextLink href={builtHref} {...rest}>\n\t\t\t{children}\n\t\t</NextLink>\n\t);\n}\n\nexport { Link };\n","interface Href {\n path: string;\n pathParams?: Record<string, string>;\n queryParams?: Record<string, string>;\n}\n\nexport function buildHref(href: Href): string {\n let url: string = href.path;\n\n if (href.pathParams) {\n Object.entries(href.pathParams).forEach(([key, value]) => {\n url = url.replace(`[${key}]`, value);\n });\n }\n\n if (href.queryParams && Object.keys(href.queryParams).length > 0) {\n const params = new URLSearchParams(href.queryParams);\n url = `${url}?${params.toString()}`;\n }\n\n return url;\n}\n","import type {\n\tAppRouterInstance,\n\tNavigateOptions,\n\tPrefetchOptions,\n} from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport { useRouter } from 'next/navigation';\nimport { useCallback } from 'react';\nimport type { PathType, TypedHref } from './types';\nimport { buildHref } from './utils';\n\ntype InternalHref = {\n\tpath: string;\n\tpathParams?: Record<string, string>;\n\tqueryParams?: Record<string, string>;\n};\n\ninterface TypedAppRouterInstance\n\textends Omit<AppRouterInstance, 'push' | 'replace' | 'prefetch'> {\n\tpush: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: NavigateOptions,\n\t) => void;\n\treplace: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: NavigateOptions,\n\t) => void;\n\tprefetch: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: PrefetchOptions,\n\t) => void;\n}\n\nexport const useTypedRouter = (): TypedAppRouterInstance => {\n\tconst router = useRouter();\n\n\tconst push: TypedAppRouterInstance['push'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.push(builtHref, options);\n\t\t},\n\t\t[router.push],\n\t);\n\n\tconst replace: TypedAppRouterInstance['replace'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.replace(builtHref, options);\n\t\t},\n\t\t[router.replace],\n\t);\n\n\tconst prefetch: TypedAppRouterInstance['prefetch'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.prefetch(builtHref, options);\n\t\t},\n\t\t[router.prefetch],\n\t);\n\n\treturn {\n\t\t...router,\n\t\tpush,\n\t\treplace,\n\t\tprefetch,\n\t};\n};\n","import { useSearchParams } from 'next/navigation';\nimport type { PathType, QueryParamName, QueryParamValue } from './types';\n\ninterface ReadonlyURLSearchParams<P extends PathType> extends URLSearchParams {\n\tappend<K extends QueryParamName<P>>(\n\t\tname: QueryParamName<P>,\n\t\tvalue: QueryParamValue<P, K>,\n\t): void;\n\tdelete<K extends QueryParamName<P>>(\n\t\tname: K,\n\t\tvalue?: QueryParamValue<P, K>,\n\t): void;\n\tget(name: QueryParamName<P>): string | null;\n\thas<K extends QueryParamName<P>>(\n\t\tname: K,\n\t\tvalue?: QueryParamValue<P, K>,\n\t): boolean;\n\tset<K extends QueryParamName<P>>(name: K, value: QueryParamValue<P, K>): void;\n}\n\nexport const useTypedSearchParams = <P extends PathType>(\n\tpath: P,\n): ReadonlyURLSearchParams<P> => {\n\tconst searchParams = useSearchParams();\n\n\treturn searchParams as ReadonlyURLSearchParams<P>;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,kBAAqB;;;ACKd,SAAS,UAAU,MAAoB;AAC1C,MAAI,MAAc,KAAK;AAEvB,MAAI,KAAK,YAAY;AACjB,WAAO,QAAQ,KAAK,UAAU,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACtD,YAAM,IAAI,QAAQ,IAAI,GAAG,KAAK,KAAK;AAAA,IACvC,CAAC;AAAA,EACL;AAEA,MAAI,KAAK,eAAe,OAAO,KAAK,KAAK,WAAW,EAAE,SAAS,GAAG;AAC9D,UAAM,SAAS,IAAI,gBAAgB,KAAK,WAAW;AACnD,UAAM,GAAG,GAAG,IAAI,OAAO,SAAS,CAAC;AAAA,EACrC;AAEA,SAAO;AACX;;;ADJE;AANF,SAAS,KAAyB,OAAqB;AACtD,QAAM,EAAE,MAAM,UAAU,GAAG,KAAK,IAAI;AAEpC,QAAM,YAAY,UAAU,IAAI;AAEhC,SACC,4CAAC,YAAAA,SAAA,EAAS,MAAM,WAAY,GAAG,MAC7B,UACF;AAEF;;;AEhBA,wBAA0B;AAC1B,mBAA4B;AA0BrB,IAAM,iBAAiB,MAA8B;AAC3D,QAAM,aAAS,6BAAU;AAEzB,QAAM,WAAuC;AAAA,IAC5C,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,KAAK,WAAW,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,OAAO,IAAI;AAAA,EACb;AAEA,QAAM,cAA6C;AAAA,IAClD,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,QAAQ,WAAW,OAAO;AAAA,IAClC;AAAA,IACA,CAAC,OAAO,OAAO;AAAA,EAChB;AAEA,QAAM,eAA+C;AAAA,IACpD,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,SAAS,WAAW,OAAO;AAAA,IACnC;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EACjB;AAEA,SAAO;AAAA,IACN,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;ACpEA,IAAAC,qBAAgC;AAoBzB,IAAM,uBAAuB,CACnC,SACgC;AAChC,QAAM,mBAAe,oCAAgB;AAErC,SAAO;AACR;","names":["NextLink","import_navigation"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { LinkProps as LinkProps$1 } from 'next/link';
|
|
3
|
+
import { ComponentProps } from 'react';
|
|
4
|
+
import { AppRouterInstance, NavigateOptions, PrefetchOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
5
|
+
|
|
6
|
+
interface RouteDefinition {
|
|
7
|
+
pathParams?: readonly string[];
|
|
8
|
+
queryParams?: Record<string, readonly string[]>;
|
|
9
|
+
}
|
|
10
|
+
type RouteMapShape = Record<string, RouteDefinition>;
|
|
11
|
+
interface RouteRegistry {
|
|
12
|
+
}
|
|
13
|
+
type RegisteredRouteMap = RouteRegistry extends {
|
|
14
|
+
map: infer M;
|
|
15
|
+
} ? M : never;
|
|
16
|
+
type AppRouteMap = [RegisteredRouteMap] extends [never] ? RouteMapShape : RegisteredRouteMap extends RouteMapShape ? RegisteredRouteMap : RouteMapShape;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extracts path types from the registered route map.
|
|
20
|
+
*/
|
|
21
|
+
type PathType = keyof AppRouteMap & string;
|
|
22
|
+
/**
|
|
23
|
+
* Extracts route-specific parameter types from the registered route map.
|
|
24
|
+
*/
|
|
25
|
+
type ExtractParams<P extends PathType> = P extends keyof AppRouteMap ? AppRouteMap[P] : never;
|
|
26
|
+
/**
|
|
27
|
+
* Maps path parameter types.
|
|
28
|
+
*/
|
|
29
|
+
type PathParams<P extends PathType> = ExtractParams<P> extends {
|
|
30
|
+
pathParams: infer PP;
|
|
31
|
+
} ? PP extends readonly string[] ? {
|
|
32
|
+
pathParams: {
|
|
33
|
+
[K in PP[number]]: string;
|
|
34
|
+
};
|
|
35
|
+
} : object : object;
|
|
36
|
+
/**
|
|
37
|
+
* Maps query parameter types.
|
|
38
|
+
*/
|
|
39
|
+
type QueryParams<P extends PathType> = ExtractParams<P> extends {
|
|
40
|
+
queryParams: infer QP;
|
|
41
|
+
} ? QP extends Record<string, readonly string[]> ? {
|
|
42
|
+
queryParams: Partial<{
|
|
43
|
+
[K in keyof QP]: QP[K] extends readonly (infer U)[] ? [U] extends [never] ? string : U : never;
|
|
44
|
+
}>;
|
|
45
|
+
} : object : object;
|
|
46
|
+
type TypedHref<P extends PathType> = {
|
|
47
|
+
path: P;
|
|
48
|
+
} & PathParams<P> & QueryParams<P>;
|
|
49
|
+
type QueryParamName<P extends PathType> = ExtractParams<P> extends {
|
|
50
|
+
queryParams: infer QP;
|
|
51
|
+
} ? keyof QP & string : string;
|
|
52
|
+
type QueryParamValue<P extends PathType, K extends QueryParamName<P>> = [
|
|
53
|
+
ExtractParams<P>
|
|
54
|
+
] extends [never] ? string : ExtractParams<P> extends {
|
|
55
|
+
queryParams: infer QP;
|
|
56
|
+
} ? K extends keyof QP ? QP[K] extends readonly (infer U)[] ? U | (string & object) : string : string : string;
|
|
57
|
+
|
|
58
|
+
type LinkProps<P extends PathType> = Omit<LinkProps$1, 'href'> & Omit<ComponentProps<'a'>, 'href'> & {
|
|
59
|
+
href: TypedHref<P>;
|
|
60
|
+
};
|
|
61
|
+
declare function Link<P extends PathType>(props: LinkProps<P>): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
interface TypedAppRouterInstance extends Omit<AppRouterInstance, 'push' | 'replace' | 'prefetch'> {
|
|
64
|
+
push: <P extends PathType>(href: TypedHref<P>, options?: NavigateOptions) => void;
|
|
65
|
+
replace: <P extends PathType>(href: TypedHref<P>, options?: NavigateOptions) => void;
|
|
66
|
+
prefetch: <P extends PathType>(href: TypedHref<P>, options?: PrefetchOptions) => void;
|
|
67
|
+
}
|
|
68
|
+
declare const useTypedRouter: () => TypedAppRouterInstance;
|
|
69
|
+
|
|
70
|
+
interface ReadonlyURLSearchParams<P extends PathType> extends URLSearchParams {
|
|
71
|
+
append<K extends QueryParamName<P>>(name: QueryParamName<P>, value: QueryParamValue<P, K>): void;
|
|
72
|
+
delete<K extends QueryParamName<P>>(name: K, value?: QueryParamValue<P, K>): void;
|
|
73
|
+
get(name: QueryParamName<P>): string | null;
|
|
74
|
+
has<K extends QueryParamName<P>>(name: K, value?: QueryParamValue<P, K>): boolean;
|
|
75
|
+
set<K extends QueryParamName<P>>(name: K, value: QueryParamValue<P, K>): void;
|
|
76
|
+
}
|
|
77
|
+
declare const useTypedSearchParams: <P extends PathType>(path: P) => ReadonlyURLSearchParams<P>;
|
|
78
|
+
|
|
79
|
+
interface Href {
|
|
80
|
+
path: string;
|
|
81
|
+
pathParams?: Record<string, string>;
|
|
82
|
+
queryParams?: Record<string, string>;
|
|
83
|
+
}
|
|
84
|
+
declare function buildHref(href: Href): string;
|
|
85
|
+
|
|
86
|
+
export { type ExtractParams, Link, type PathParams, type PathType, type QueryParamName, type QueryParamValue, type QueryParams, type RouteMapShape, type RouteRegistry, type TypedHref, buildHref, useTypedRouter, useTypedSearchParams };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { LinkProps as LinkProps$1 } from 'next/link';
|
|
3
|
+
import { ComponentProps } from 'react';
|
|
4
|
+
import { AppRouterInstance, NavigateOptions, PrefetchOptions } from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
5
|
+
|
|
6
|
+
interface RouteDefinition {
|
|
7
|
+
pathParams?: readonly string[];
|
|
8
|
+
queryParams?: Record<string, readonly string[]>;
|
|
9
|
+
}
|
|
10
|
+
type RouteMapShape = Record<string, RouteDefinition>;
|
|
11
|
+
interface RouteRegistry {
|
|
12
|
+
}
|
|
13
|
+
type RegisteredRouteMap = RouteRegistry extends {
|
|
14
|
+
map: infer M;
|
|
15
|
+
} ? M : never;
|
|
16
|
+
type AppRouteMap = [RegisteredRouteMap] extends [never] ? RouteMapShape : RegisteredRouteMap extends RouteMapShape ? RegisteredRouteMap : RouteMapShape;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Extracts path types from the registered route map.
|
|
20
|
+
*/
|
|
21
|
+
type PathType = keyof AppRouteMap & string;
|
|
22
|
+
/**
|
|
23
|
+
* Extracts route-specific parameter types from the registered route map.
|
|
24
|
+
*/
|
|
25
|
+
type ExtractParams<P extends PathType> = P extends keyof AppRouteMap ? AppRouteMap[P] : never;
|
|
26
|
+
/**
|
|
27
|
+
* Maps path parameter types.
|
|
28
|
+
*/
|
|
29
|
+
type PathParams<P extends PathType> = ExtractParams<P> extends {
|
|
30
|
+
pathParams: infer PP;
|
|
31
|
+
} ? PP extends readonly string[] ? {
|
|
32
|
+
pathParams: {
|
|
33
|
+
[K in PP[number]]: string;
|
|
34
|
+
};
|
|
35
|
+
} : object : object;
|
|
36
|
+
/**
|
|
37
|
+
* Maps query parameter types.
|
|
38
|
+
*/
|
|
39
|
+
type QueryParams<P extends PathType> = ExtractParams<P> extends {
|
|
40
|
+
queryParams: infer QP;
|
|
41
|
+
} ? QP extends Record<string, readonly string[]> ? {
|
|
42
|
+
queryParams: Partial<{
|
|
43
|
+
[K in keyof QP]: QP[K] extends readonly (infer U)[] ? [U] extends [never] ? string : U : never;
|
|
44
|
+
}>;
|
|
45
|
+
} : object : object;
|
|
46
|
+
type TypedHref<P extends PathType> = {
|
|
47
|
+
path: P;
|
|
48
|
+
} & PathParams<P> & QueryParams<P>;
|
|
49
|
+
type QueryParamName<P extends PathType> = ExtractParams<P> extends {
|
|
50
|
+
queryParams: infer QP;
|
|
51
|
+
} ? keyof QP & string : string;
|
|
52
|
+
type QueryParamValue<P extends PathType, K extends QueryParamName<P>> = [
|
|
53
|
+
ExtractParams<P>
|
|
54
|
+
] extends [never] ? string : ExtractParams<P> extends {
|
|
55
|
+
queryParams: infer QP;
|
|
56
|
+
} ? K extends keyof QP ? QP[K] extends readonly (infer U)[] ? U | (string & object) : string : string : string;
|
|
57
|
+
|
|
58
|
+
type LinkProps<P extends PathType> = Omit<LinkProps$1, 'href'> & Omit<ComponentProps<'a'>, 'href'> & {
|
|
59
|
+
href: TypedHref<P>;
|
|
60
|
+
};
|
|
61
|
+
declare function Link<P extends PathType>(props: LinkProps<P>): react_jsx_runtime.JSX.Element;
|
|
62
|
+
|
|
63
|
+
interface TypedAppRouterInstance extends Omit<AppRouterInstance, 'push' | 'replace' | 'prefetch'> {
|
|
64
|
+
push: <P extends PathType>(href: TypedHref<P>, options?: NavigateOptions) => void;
|
|
65
|
+
replace: <P extends PathType>(href: TypedHref<P>, options?: NavigateOptions) => void;
|
|
66
|
+
prefetch: <P extends PathType>(href: TypedHref<P>, options?: PrefetchOptions) => void;
|
|
67
|
+
}
|
|
68
|
+
declare const useTypedRouter: () => TypedAppRouterInstance;
|
|
69
|
+
|
|
70
|
+
interface ReadonlyURLSearchParams<P extends PathType> extends URLSearchParams {
|
|
71
|
+
append<K extends QueryParamName<P>>(name: QueryParamName<P>, value: QueryParamValue<P, K>): void;
|
|
72
|
+
delete<K extends QueryParamName<P>>(name: K, value?: QueryParamValue<P, K>): void;
|
|
73
|
+
get(name: QueryParamName<P>): string | null;
|
|
74
|
+
has<K extends QueryParamName<P>>(name: K, value?: QueryParamValue<P, K>): boolean;
|
|
75
|
+
set<K extends QueryParamName<P>>(name: K, value: QueryParamValue<P, K>): void;
|
|
76
|
+
}
|
|
77
|
+
declare const useTypedSearchParams: <P extends PathType>(path: P) => ReadonlyURLSearchParams<P>;
|
|
78
|
+
|
|
79
|
+
interface Href {
|
|
80
|
+
path: string;
|
|
81
|
+
pathParams?: Record<string, string>;
|
|
82
|
+
queryParams?: Record<string, string>;
|
|
83
|
+
}
|
|
84
|
+
declare function buildHref(href: Href): string;
|
|
85
|
+
|
|
86
|
+
export { type ExtractParams, Link, type PathParams, type PathType, type QueryParamName, type QueryParamValue, type QueryParams, type RouteMapShape, type RouteRegistry, type TypedHref, buildHref, useTypedRouter, useTypedSearchParams };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/Link.tsx
|
|
2
|
+
import NextLink from "next/link";
|
|
3
|
+
|
|
4
|
+
// src/utils.ts
|
|
5
|
+
function buildHref(href) {
|
|
6
|
+
let url = href.path;
|
|
7
|
+
if (href.pathParams) {
|
|
8
|
+
Object.entries(href.pathParams).forEach(([key, value]) => {
|
|
9
|
+
url = url.replace(`[${key}]`, value);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
if (href.queryParams && Object.keys(href.queryParams).length > 0) {
|
|
13
|
+
const params = new URLSearchParams(href.queryParams);
|
|
14
|
+
url = `${url}?${params.toString()}`;
|
|
15
|
+
}
|
|
16
|
+
return url;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/Link.tsx
|
|
20
|
+
import { jsx } from "react/jsx-runtime";
|
|
21
|
+
function Link(props) {
|
|
22
|
+
const { href, children, ...rest } = props;
|
|
23
|
+
const builtHref = buildHref(href);
|
|
24
|
+
return /* @__PURE__ */ jsx(NextLink, { href: builtHref, ...rest, children });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// src/useTypedRouter.ts
|
|
28
|
+
import { useRouter } from "next/navigation";
|
|
29
|
+
import { useCallback } from "react";
|
|
30
|
+
var useTypedRouter = () => {
|
|
31
|
+
const router = useRouter();
|
|
32
|
+
const push = useCallback(
|
|
33
|
+
(href, options) => {
|
|
34
|
+
const builtHref = buildHref(href);
|
|
35
|
+
router.push(builtHref, options);
|
|
36
|
+
},
|
|
37
|
+
[router.push]
|
|
38
|
+
);
|
|
39
|
+
const replace = useCallback(
|
|
40
|
+
(href, options) => {
|
|
41
|
+
const builtHref = buildHref(href);
|
|
42
|
+
router.replace(builtHref, options);
|
|
43
|
+
},
|
|
44
|
+
[router.replace]
|
|
45
|
+
);
|
|
46
|
+
const prefetch = useCallback(
|
|
47
|
+
(href, options) => {
|
|
48
|
+
const builtHref = buildHref(href);
|
|
49
|
+
router.prefetch(builtHref, options);
|
|
50
|
+
},
|
|
51
|
+
[router.prefetch]
|
|
52
|
+
);
|
|
53
|
+
return {
|
|
54
|
+
...router,
|
|
55
|
+
push,
|
|
56
|
+
replace,
|
|
57
|
+
prefetch
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// src/useTypedSearchParams.ts
|
|
62
|
+
import { useSearchParams } from "next/navigation";
|
|
63
|
+
var useTypedSearchParams = (path) => {
|
|
64
|
+
const searchParams = useSearchParams();
|
|
65
|
+
return searchParams;
|
|
66
|
+
};
|
|
67
|
+
export {
|
|
68
|
+
Link,
|
|
69
|
+
buildHref,
|
|
70
|
+
useTypedRouter,
|
|
71
|
+
useTypedSearchParams
|
|
72
|
+
};
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/Link.tsx","../src/utils.ts","../src/useTypedRouter.ts","../src/useTypedSearchParams.ts"],"sourcesContent":["import type { LinkProps as NextLinkProps } from 'next/link';\nimport NextLink from 'next/link';\nimport type { ComponentProps } from 'react';\nimport type { PathType, TypedHref } from './types';\nimport { buildHref } from './utils';\n\ntype LinkProps<P extends PathType> = Omit<NextLinkProps, 'href'> &\n\tOmit<ComponentProps<'a'>, 'href'> & {\n\t\thref: TypedHref<P>;\n\t};\n\nfunction Link<P extends PathType>(props: LinkProps<P>) {\n\tconst { href, children, ...rest } = props;\n\n\tconst builtHref = buildHref(href);\n\n\treturn (\n\t\t<NextLink href={builtHref} {...rest}>\n\t\t\t{children}\n\t\t</NextLink>\n\t);\n}\n\nexport { Link };\n","interface Href {\n path: string;\n pathParams?: Record<string, string>;\n queryParams?: Record<string, string>;\n}\n\nexport function buildHref(href: Href): string {\n let url: string = href.path;\n\n if (href.pathParams) {\n Object.entries(href.pathParams).forEach(([key, value]) => {\n url = url.replace(`[${key}]`, value);\n });\n }\n\n if (href.queryParams && Object.keys(href.queryParams).length > 0) {\n const params = new URLSearchParams(href.queryParams);\n url = `${url}?${params.toString()}`;\n }\n\n return url;\n}\n","import type {\n\tAppRouterInstance,\n\tNavigateOptions,\n\tPrefetchOptions,\n} from 'next/dist/shared/lib/app-router-context.shared-runtime';\nimport { useRouter } from 'next/navigation';\nimport { useCallback } from 'react';\nimport type { PathType, TypedHref } from './types';\nimport { buildHref } from './utils';\n\ntype InternalHref = {\n\tpath: string;\n\tpathParams?: Record<string, string>;\n\tqueryParams?: Record<string, string>;\n};\n\ninterface TypedAppRouterInstance\n\textends Omit<AppRouterInstance, 'push' | 'replace' | 'prefetch'> {\n\tpush: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: NavigateOptions,\n\t) => void;\n\treplace: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: NavigateOptions,\n\t) => void;\n\tprefetch: <P extends PathType>(\n\t\thref: TypedHref<P>,\n\t\toptions?: PrefetchOptions,\n\t) => void;\n}\n\nexport const useTypedRouter = (): TypedAppRouterInstance => {\n\tconst router = useRouter();\n\n\tconst push: TypedAppRouterInstance['push'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.push(builtHref, options);\n\t\t},\n\t\t[router.push],\n\t);\n\n\tconst replace: TypedAppRouterInstance['replace'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.replace(builtHref, options);\n\t\t},\n\t\t[router.replace],\n\t);\n\n\tconst prefetch: TypedAppRouterInstance['prefetch'] = useCallback(\n\t\t(href: InternalHref, options) => {\n\t\t\tconst builtHref = buildHref(href);\n\n\t\t\trouter.prefetch(builtHref, options);\n\t\t},\n\t\t[router.prefetch],\n\t);\n\n\treturn {\n\t\t...router,\n\t\tpush,\n\t\treplace,\n\t\tprefetch,\n\t};\n};\n","import { useSearchParams } from 'next/navigation';\nimport type { PathType, QueryParamName, QueryParamValue } from './types';\n\ninterface ReadonlyURLSearchParams<P extends PathType> extends URLSearchParams {\n\tappend<K extends QueryParamName<P>>(\n\t\tname: QueryParamName<P>,\n\t\tvalue: QueryParamValue<P, K>,\n\t): void;\n\tdelete<K extends QueryParamName<P>>(\n\t\tname: K,\n\t\tvalue?: QueryParamValue<P, K>,\n\t): void;\n\tget(name: QueryParamName<P>): string | null;\n\thas<K extends QueryParamName<P>>(\n\t\tname: K,\n\t\tvalue?: QueryParamValue<P, K>,\n\t): boolean;\n\tset<K extends QueryParamName<P>>(name: K, value: QueryParamValue<P, K>): void;\n}\n\nexport const useTypedSearchParams = <P extends PathType>(\n\tpath: P,\n): ReadonlyURLSearchParams<P> => {\n\tconst searchParams = useSearchParams();\n\n\treturn searchParams as ReadonlyURLSearchParams<P>;\n};\n"],"mappings":";AACA,OAAO,cAAc;;;ACKd,SAAS,UAAU,MAAoB;AAC1C,MAAI,MAAc,KAAK;AAEvB,MAAI,KAAK,YAAY;AACjB,WAAO,QAAQ,KAAK,UAAU,EAAE,QAAQ,CAAC,CAAC,KAAK,KAAK,MAAM;AACtD,YAAM,IAAI,QAAQ,IAAI,GAAG,KAAK,KAAK;AAAA,IACvC,CAAC;AAAA,EACL;AAEA,MAAI,KAAK,eAAe,OAAO,KAAK,KAAK,WAAW,EAAE,SAAS,GAAG;AAC9D,UAAM,SAAS,IAAI,gBAAgB,KAAK,WAAW;AACnD,UAAM,GAAG,GAAG,IAAI,OAAO,SAAS,CAAC;AAAA,EACrC;AAEA,SAAO;AACX;;;ADJE;AANF,SAAS,KAAyB,OAAqB;AACtD,QAAM,EAAE,MAAM,UAAU,GAAG,KAAK,IAAI;AAEpC,QAAM,YAAY,UAAU,IAAI;AAEhC,SACC,oBAAC,YAAS,MAAM,WAAY,GAAG,MAC7B,UACF;AAEF;;;AEhBA,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AA0BrB,IAAM,iBAAiB,MAA8B;AAC3D,QAAM,SAAS,UAAU;AAEzB,QAAM,OAAuC;AAAA,IAC5C,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,KAAK,WAAW,OAAO;AAAA,IAC/B;AAAA,IACA,CAAC,OAAO,IAAI;AAAA,EACb;AAEA,QAAM,UAA6C;AAAA,IAClD,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,QAAQ,WAAW,OAAO;AAAA,IAClC;AAAA,IACA,CAAC,OAAO,OAAO;AAAA,EAChB;AAEA,QAAM,WAA+C;AAAA,IACpD,CAAC,MAAoB,YAAY;AAChC,YAAM,YAAY,UAAU,IAAI;AAEhC,aAAO,SAAS,WAAW,OAAO;AAAA,IACnC;AAAA,IACA,CAAC,OAAO,QAAQ;AAAA,EACjB;AAEA,SAAO;AAAA,IACN,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,EACD;AACD;;;ACpEA,SAAS,uBAAuB;AAoBzB,IAAM,uBAAuB,CACnC,SACgC;AAChC,QAAM,eAAe,gBAAgB;AAErC,SAAO;AACR;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "typed-next-router",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "./dist/index.cjs",
|
|
5
|
+
"module": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"import": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"default": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"require": {
|
|
14
|
+
"types": "./dist/index.d.cts",
|
|
15
|
+
"default": "./dist/index.cjs"
|
|
16
|
+
},
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"author": "SaeWooKKang",
|
|
25
|
+
"keywords": [
|
|
26
|
+
"type",
|
|
27
|
+
"next",
|
|
28
|
+
"router"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"description": "",
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@arethetypeswrong/cli": "^0.18.2",
|
|
34
|
+
"@biomejs/biome": "2.4.2",
|
|
35
|
+
"@changesets/cli": "^2.29.8",
|
|
36
|
+
"@types/react": "^19",
|
|
37
|
+
"@types/react-dom": "^19",
|
|
38
|
+
"tsup": "^8.5.1",
|
|
39
|
+
"typescript": "^5.9.3",
|
|
40
|
+
"vitest": "^4.0.18"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"next": "^14",
|
|
44
|
+
"react": "^18",
|
|
45
|
+
"react-dom": "^18"
|
|
46
|
+
},
|
|
47
|
+
"scripts": {
|
|
48
|
+
"check-exports": "attw --pack .",
|
|
49
|
+
"test": "vitest",
|
|
50
|
+
"build": "tsup src/index.tsx"
|
|
51
|
+
}
|
|
52
|
+
}
|