@hyeonqyu/typed-router-core 1.4.2 → 1.5.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.d.mts +5 -6
- package/dist/index.d.ts +5 -6
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +23 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{routes.types-BOeBykBW.d.mts → routes.types-C0cWyXOZ.d.mts} +4 -1
- package/dist/{routes.types-BOeBykBW.d.ts → routes.types-C0cWyXOZ.d.ts} +4 -1
- package/dist/routes.utils.d.mts +4 -1
- package/dist/routes.utils.d.ts +4 -1
- package/dist/routes.utils.js +50 -2
- package/dist/routes.utils.js.map +1 -1
- package/dist/routes.utils.mjs +50 -2
- package/dist/routes.utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { P as Paths, a as PathValue } from './routes.types-
|
|
2
|
-
export { A as AnyZodSchema, B as BaseMetadata, E as ExtractSearchParams, G as GetRouteNode,
|
|
3
|
-
|
|
4
|
-
type SearchParamsValue = string | number | boolean | readonly (string | number | boolean)[];
|
|
5
|
-
type SearchParams = Record<string, SearchParamsValue>;
|
|
1
|
+
import { P as Paths, a as PathValue, S as SearchParams } from './routes.types-C0cWyXOZ.mjs';
|
|
2
|
+
export { A as AnyZodSchema, B as BaseMetadata, E as ExtractSearchParams, G as GetRouteNode, d as PartialRouteTree, h as ResolvedRouteTree, R as RouteNode, c as RouteNodeMetadata, f as RoutePathname, e as RouteTree, i as SearchParamsForPath, b as SearchParamsValue, g as SimplifyPathname } from './routes.types-C0cWyXOZ.mjs';
|
|
6
3
|
|
|
7
4
|
declare const getSafely: <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(splitter: TSplitter, obj: TObject, path: TPath) => PathValue<TObject, TPath, TSplitter>;
|
|
8
5
|
type SearchParamsStringOptions = {
|
|
9
6
|
includeQuestionMark?: boolean;
|
|
10
7
|
};
|
|
11
8
|
declare const toSearchParamsString: (searchParams: SearchParams, options?: SearchParamsStringOptions) => string;
|
|
9
|
+
declare const findObjectPath: <T>(root: Record<string, unknown>, target: T, splitter?: string, path?: string) => string | undefined;
|
|
10
|
+
declare const replaceDynamicSegments: (pathname: string, params?: SearchParams) => string;
|
|
12
11
|
|
|
13
|
-
export { PathValue, Paths,
|
|
12
|
+
export { PathValue, Paths, SearchParams, type SearchParamsStringOptions, findObjectPath, getSafely, replaceDynamicSegments, toSearchParamsString };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import { P as Paths, a as PathValue } from './routes.types-
|
|
2
|
-
export { A as AnyZodSchema, B as BaseMetadata, E as ExtractSearchParams, G as GetRouteNode,
|
|
3
|
-
|
|
4
|
-
type SearchParamsValue = string | number | boolean | readonly (string | number | boolean)[];
|
|
5
|
-
type SearchParams = Record<string, SearchParamsValue>;
|
|
1
|
+
import { P as Paths, a as PathValue, S as SearchParams } from './routes.types-C0cWyXOZ.js';
|
|
2
|
+
export { A as AnyZodSchema, B as BaseMetadata, E as ExtractSearchParams, G as GetRouteNode, d as PartialRouteTree, h as ResolvedRouteTree, R as RouteNode, c as RouteNodeMetadata, f as RoutePathname, e as RouteTree, i as SearchParamsForPath, b as SearchParamsValue, g as SimplifyPathname } from './routes.types-C0cWyXOZ.js';
|
|
6
3
|
|
|
7
4
|
declare const getSafely: <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(splitter: TSplitter, obj: TObject, path: TPath) => PathValue<TObject, TPath, TSplitter>;
|
|
8
5
|
type SearchParamsStringOptions = {
|
|
9
6
|
includeQuestionMark?: boolean;
|
|
10
7
|
};
|
|
11
8
|
declare const toSearchParamsString: (searchParams: SearchParams, options?: SearchParamsStringOptions) => string;
|
|
9
|
+
declare const findObjectPath: <T>(root: Record<string, unknown>, target: T, splitter?: string, path?: string) => string | undefined;
|
|
10
|
+
declare const replaceDynamicSegments: (pathname: string, params?: SearchParams) => string;
|
|
12
11
|
|
|
13
|
-
export { PathValue, Paths,
|
|
12
|
+
export { PathValue, Paths, SearchParams, type SearchParamsStringOptions, findObjectPath, getSafely, replaceDynamicSegments, toSearchParamsString };
|
package/dist/index.js
CHANGED
|
@@ -40,8 +40,32 @@ var toSearchParamsString = /* @__PURE__ */ __name((searchParams, options = { inc
|
|
|
40
40
|
const searchParamsString = params.join("&");
|
|
41
41
|
return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;
|
|
42
42
|
}, "toSearchParamsString");
|
|
43
|
+
var findObjectPath = /* @__PURE__ */ __name((root, target, splitter = "/", path = splitter) => {
|
|
44
|
+
for (const key in root) {
|
|
45
|
+
if (key === "_metadata") {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const current = root[key];
|
|
49
|
+
if (current === target) return path + key;
|
|
50
|
+
if (typeof current === "object" && current !== null) {
|
|
51
|
+
const result = findObjectPath(current, target, splitter, path + key + splitter);
|
|
52
|
+
if (result) return result;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return void 0;
|
|
56
|
+
}, "findObjectPath");
|
|
57
|
+
var replaceDynamicSegments = /* @__PURE__ */ __name((pathname, params) => {
|
|
58
|
+
if (!params) return pathname;
|
|
59
|
+
return pathname.replace(/\[([^\]]+)\]/g, (_, key) => {
|
|
60
|
+
const value = params[key.toString()];
|
|
61
|
+
if (value === void 0 || value === null) return `[${key}]`;
|
|
62
|
+
return Array.isArray(value) ? value.join(",") : value.toString();
|
|
63
|
+
});
|
|
64
|
+
}, "replaceDynamicSegments");
|
|
43
65
|
|
|
66
|
+
exports.findObjectPath = findObjectPath;
|
|
44
67
|
exports.getSafely = getSafely;
|
|
68
|
+
exports.replaceDynamicSegments = replaceDynamicSegments;
|
|
45
69
|
exports.toSearchParamsString = toSearchParamsString;
|
|
46
70
|
//# sourceMappingURL=index.js.map
|
|
47
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/object.utils.ts"],"names":[],"mappings":";;;;;;AAGO,IAAM,SAAA,mBAAY,MAAA,CAAA,CACvB,QAAA,EACA,GAAA,EACA,IAAA,KACyC;AACzC,EAAA,IAAI,IAAA,KAAS,EAAA,IAAM,IAAA,KAAS,QAAA,EAAU,OAAO,GAAA;AAE7C,EAAA,MAAM,IAAA,GAAQ,KAAgB,KAAA,CAAM,QAAQ,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAG,CAAA;AACjE,EAAA,IAAI,KAAA,GAAiB,GAAA;AAErB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/D,MAAA,KAAA,GAAS,MAAkC,GAAG,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT,CAAA,EAnByB,WAAA;AAyBlB,IAAM,uCAAuB,MAAA,CAAA,CAClC,YAAA,EACA,UAAqC,EAAE,mBAAA,EAAqB,MAAK,KACtD;AACX,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AACrD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,mBAAmB,GAAG,CAAA;AAEzC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,QAAA,IAAI,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,IAAA,EAAM;AACvC,UAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA,CAAA,EAAI,mBAAmB,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACjE;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA,CAAA,EAAI,mBAAmB,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IAClE;AAAA,EACF,CAAC,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAC1C,EAAA,OAAO,OAAA,CAAQ,mBAAA,GAAsB,CAAA,CAAA,EAAI,kBAAkB,CAAA,CAAA,GAAK,kBAAA;AAClE,CAAA,EA9BoC,sBAAA","file":"index.js","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/object.utils.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n\nexport const findObjectPath = <T>(\n root: Record<string, unknown>,\n target: T,\n splitter = '/',\n path = splitter,\n): string | undefined => {\n for (const key in root) {\n // Skip _metadata keys during traversal\n if (key === '_metadata') {\n continue;\n }\n\n const current = root[key];\n\n if (current === target) return path + key;\n\n if (typeof current === 'object' && current !== null) {\n const result = findObjectPath(current as Record<string, unknown>, target, splitter, path + key + splitter);\n if (result) return result;\n }\n }\n\n return undefined;\n};\n\nexport const replaceDynamicSegments = (\n pathname: string,\n params?: SearchParams,\n): string => {\n if (!params) return pathname;\n\n return pathname.replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const value = params[key.toString()];\n if (value === undefined || value === null) return `[${key}]`;\n return Array.isArray(value) ? value.join(',') : value.toString();\n });\n};\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -38,7 +38,29 @@ var toSearchParamsString = /* @__PURE__ */ __name((searchParams, options = { inc
|
|
|
38
38
|
const searchParamsString = params.join("&");
|
|
39
39
|
return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;
|
|
40
40
|
}, "toSearchParamsString");
|
|
41
|
+
var findObjectPath = /* @__PURE__ */ __name((root, target, splitter = "/", path = splitter) => {
|
|
42
|
+
for (const key in root) {
|
|
43
|
+
if (key === "_metadata") {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const current = root[key];
|
|
47
|
+
if (current === target) return path + key;
|
|
48
|
+
if (typeof current === "object" && current !== null) {
|
|
49
|
+
const result = findObjectPath(current, target, splitter, path + key + splitter);
|
|
50
|
+
if (result) return result;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return void 0;
|
|
54
|
+
}, "findObjectPath");
|
|
55
|
+
var replaceDynamicSegments = /* @__PURE__ */ __name((pathname, params) => {
|
|
56
|
+
if (!params) return pathname;
|
|
57
|
+
return pathname.replace(/\[([^\]]+)\]/g, (_, key) => {
|
|
58
|
+
const value = params[key.toString()];
|
|
59
|
+
if (value === void 0 || value === null) return `[${key}]`;
|
|
60
|
+
return Array.isArray(value) ? value.join(",") : value.toString();
|
|
61
|
+
});
|
|
62
|
+
}, "replaceDynamicSegments");
|
|
41
63
|
|
|
42
|
-
export { getSafely, toSearchParamsString };
|
|
64
|
+
export { findObjectPath, getSafely, replaceDynamicSegments, toSearchParamsString };
|
|
43
65
|
//# sourceMappingURL=index.mjs.map
|
|
44
66
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/object.utils.ts"],"names":[],"mappings":";;;;AAGO,IAAM,SAAA,mBAAY,MAAA,CAAA,CACvB,QAAA,EACA,GAAA,EACA,IAAA,KACyC;AACzC,EAAA,IAAI,IAAA,KAAS,EAAA,IAAM,IAAA,KAAS,QAAA,EAAU,OAAO,GAAA;AAE7C,EAAA,MAAM,IAAA,GAAQ,KAAgB,KAAA,CAAM,QAAQ,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAG,CAAA;AACjE,EAAA,IAAI,KAAA,GAAiB,GAAA;AAErB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/D,MAAA,KAAA,GAAS,MAAkC,GAAG,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT,CAAA,EAnByB,WAAA;AAyBlB,IAAM,uCAAuB,MAAA,CAAA,CAClC,YAAA,EACA,UAAqC,EAAE,mBAAA,EAAqB,MAAK,KACtD;AACX,EAAA,MAAM,SAAmB,EAAC;AAE1B,EAAA,MAAA,CAAO,OAAA,CAAQ,YAAY,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAC,GAAA,EAAK,KAAK,CAAA,KAAM;AACrD,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,UAAA,GAAa,mBAAmB,GAAG,CAAA;AAEzC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACxB,MAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,KAAS;AACtB,QAAA,IAAI,IAAA,KAAS,MAAA,IAAa,IAAA,KAAS,IAAA,EAAM;AACvC,UAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA,CAAA,EAAI,mBAAmB,MAAA,CAAO,IAAI,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,QACjE;AAAA,MACF,CAAC,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,UAAU,CAAA,CAAA,EAAI,mBAAmB,MAAA,CAAO,KAAK,CAAC,CAAC,CAAA,CAAE,CAAA;AAAA,IAClE;AAAA,EACF,CAAC,CAAA;AAED,EAAA,IAAI,MAAA,CAAO,WAAW,CAAA,EAAG;AACvB,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,kBAAA,GAAqB,MAAA,CAAO,IAAA,CAAK,GAAG,CAAA;AAC1C,EAAA,OAAO,OAAA,CAAQ,mBAAA,GAAsB,CAAA,CAAA,EAAI,kBAAkB,CAAA,CAAA,GAAK,kBAAA;AAClE,CAAA,EA9BoC,sBAAA","file":"index.mjs","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/object.utils.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n\nexport const findObjectPath = <T>(\n root: Record<string, unknown>,\n target: T,\n splitter = '/',\n path = splitter,\n): string | undefined => {\n for (const key in root) {\n // Skip _metadata keys during traversal\n if (key === '_metadata') {\n continue;\n }\n\n const current = root[key];\n\n if (current === target) return path + key;\n\n if (typeof current === 'object' && current !== null) {\n const result = findObjectPath(current as Record<string, unknown>, target, splitter, path + key + splitter);\n if (result) return result;\n }\n }\n\n return undefined;\n};\n\nexport const replaceDynamicSegments = (\n pathname: string,\n params?: SearchParams,\n): string => {\n if (!params) return pathname;\n\n return pathname.replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const value = params[key.toString()];\n if (value === undefined || value === null) return `[${key}]`;\n return Array.isArray(value) ? value.join(',') : value.toString();\n });\n};\n"]}
|
|
@@ -3,6 +3,9 @@ type Paths<TObject, TSplitter extends string, TPrev extends string = '', TMaxDep
|
|
|
3
3
|
}[keyof TObject & string];
|
|
4
4
|
type PathValue<T, P extends string, S extends string, TMaxDepth extends number = 10, TDepth extends unknown[] = []> = TDepth['length'] extends TMaxDepth ? never : P extends S ? T : P extends `${S}${infer Rest}` ? Rest extends `${infer K}${S}${infer R}` ? K extends keyof T ? PathValue<T[K], `${S}${R}`, S, TMaxDepth, [...TDepth, 1]> : never : Rest extends keyof T ? T[Rest] : never : never;
|
|
5
5
|
|
|
6
|
+
type SearchParamsValue = string | number | boolean | readonly (string | number | boolean)[];
|
|
7
|
+
type SearchParams = Record<string, SearchParamsValue>;
|
|
8
|
+
|
|
6
9
|
type BaseMetadata = NonNullable<unknown>;
|
|
7
10
|
type AnyZodSchema = {
|
|
8
11
|
_input: any;
|
|
@@ -43,4 +46,4 @@ type ExtractSearchParams<TNode> = TNode extends {
|
|
|
43
46
|
type GetRouteNode<TRouteTree, TPath extends string> = TPath extends `/${infer First}/${infer Rest}` ? First extends keyof TRouteTree ? GetRouteNode<TRouteTree[First], `/${Rest}`> : never : TPath extends `/${infer Key}` ? Key extends keyof TRouteTree ? TRouteTree[Key] : never : TRouteTree;
|
|
44
47
|
type SearchParamsForPath<TRouteTree, TPath extends string> = ExtractSearchParams<GetRouteNode<TRouteTree, TPath>>;
|
|
45
48
|
|
|
46
|
-
export type { AnyZodSchema as A, BaseMetadata as B, ExtractSearchParams as E, GetRouteNode as G, Paths as P, RouteNode as R,
|
|
49
|
+
export type { AnyZodSchema as A, BaseMetadata as B, ExtractSearchParams as E, GetRouteNode as G, Paths as P, RouteNode as R, SearchParams as S, PathValue as a, SearchParamsValue as b, RouteNodeMetadata as c, PartialRouteTree as d, RouteTree as e, RoutePathname as f, SimplifyPathname as g, ResolvedRouteTree as h, SearchParamsForPath as i };
|
|
@@ -3,6 +3,9 @@ type Paths<TObject, TSplitter extends string, TPrev extends string = '', TMaxDep
|
|
|
3
3
|
}[keyof TObject & string];
|
|
4
4
|
type PathValue<T, P extends string, S extends string, TMaxDepth extends number = 10, TDepth extends unknown[] = []> = TDepth['length'] extends TMaxDepth ? never : P extends S ? T : P extends `${S}${infer Rest}` ? Rest extends `${infer K}${S}${infer R}` ? K extends keyof T ? PathValue<T[K], `${S}${R}`, S, TMaxDepth, [...TDepth, 1]> : never : Rest extends keyof T ? T[Rest] : never : never;
|
|
5
5
|
|
|
6
|
+
type SearchParamsValue = string | number | boolean | readonly (string | number | boolean)[];
|
|
7
|
+
type SearchParams = Record<string, SearchParamsValue>;
|
|
8
|
+
|
|
6
9
|
type BaseMetadata = NonNullable<unknown>;
|
|
7
10
|
type AnyZodSchema = {
|
|
8
11
|
_input: any;
|
|
@@ -43,4 +46,4 @@ type ExtractSearchParams<TNode> = TNode extends {
|
|
|
43
46
|
type GetRouteNode<TRouteTree, TPath extends string> = TPath extends `/${infer First}/${infer Rest}` ? First extends keyof TRouteTree ? GetRouteNode<TRouteTree[First], `/${Rest}`> : never : TPath extends `/${infer Key}` ? Key extends keyof TRouteTree ? TRouteTree[Key] : never : TRouteTree;
|
|
44
47
|
type SearchParamsForPath<TRouteTree, TPath extends string> = ExtractSearchParams<GetRouteNode<TRouteTree, TPath>>;
|
|
45
48
|
|
|
46
|
-
export type { AnyZodSchema as A, BaseMetadata as B, ExtractSearchParams as E, GetRouteNode as G, Paths as P, RouteNode as R,
|
|
49
|
+
export type { AnyZodSchema as A, BaseMetadata as B, ExtractSearchParams as E, GetRouteNode as G, Paths as P, RouteNode as R, SearchParams as S, PathValue as a, SearchParamsValue as b, RouteNodeMetadata as c, PartialRouteTree as d, RouteTree as e, RoutePathname as f, SimplifyPathname as g, ResolvedRouteTree as h, SearchParamsForPath as i };
|
package/dist/routes.utils.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { B as BaseMetadata,
|
|
3
|
+
import { B as BaseMetadata, d as PartialRouteTree, e as RouteTree, h as ResolvedRouteTree, f as RoutePathname, R as RouteNode, S as SearchParams } from './routes.types-C0cWyXOZ.mjs';
|
|
4
4
|
|
|
5
5
|
declare const createAppRoutes: <TMetadata extends BaseMetadata, TContext>() => <TRouteTree extends PartialRouteTree<TMetadata, TContext>>(appRoutes: TRouteTree & RouteTree<TMetadata, TContext, TRouteTree>) => {
|
|
6
6
|
AppRoutesProvider: ({ children }: {
|
|
@@ -8,10 +8,13 @@ declare const createAppRoutes: <TMetadata extends BaseMetadata, TContext>() => <
|
|
|
8
8
|
}) => react_jsx_runtime.JSX.Element;
|
|
9
9
|
useAppRoutes: () => ResolvedRouteTree<TMetadata, TContext, TRouteTree>;
|
|
10
10
|
useCurrentRouteNode: <TPath extends RoutePathname<TMetadata, TContext, TRouteTree>>(pathname: TPath) => RouteNode<TMetadata, TContext>;
|
|
11
|
+
getPathnameFromNode: (targetNode: RouteNode<TMetadata, TContext>, params?: SearchParams) => string | undefined;
|
|
12
|
+
freezeAppRoutes: () => ResolvedRouteTree<TMetadata, TContext, TRouteTree>;
|
|
11
13
|
_types: {
|
|
12
14
|
AppRoutesMetadata: TMetadata;
|
|
13
15
|
AppRoutesContext: TContext;
|
|
14
16
|
AppRoutesPathname: RoutePathname<TMetadata, TContext, TRouteTree>;
|
|
17
|
+
AppRouteNode: RouteNode<TMetadata, TContext>;
|
|
15
18
|
};
|
|
16
19
|
};
|
|
17
20
|
|
package/dist/routes.utils.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { B as BaseMetadata,
|
|
3
|
+
import { B as BaseMetadata, d as PartialRouteTree, e as RouteTree, h as ResolvedRouteTree, f as RoutePathname, R as RouteNode, S as SearchParams } from './routes.types-C0cWyXOZ.js';
|
|
4
4
|
|
|
5
5
|
declare const createAppRoutes: <TMetadata extends BaseMetadata, TContext>() => <TRouteTree extends PartialRouteTree<TMetadata, TContext>>(appRoutes: TRouteTree & RouteTree<TMetadata, TContext, TRouteTree>) => {
|
|
6
6
|
AppRoutesProvider: ({ children }: {
|
|
@@ -8,10 +8,13 @@ declare const createAppRoutes: <TMetadata extends BaseMetadata, TContext>() => <
|
|
|
8
8
|
}) => react_jsx_runtime.JSX.Element;
|
|
9
9
|
useAppRoutes: () => ResolvedRouteTree<TMetadata, TContext, TRouteTree>;
|
|
10
10
|
useCurrentRouteNode: <TPath extends RoutePathname<TMetadata, TContext, TRouteTree>>(pathname: TPath) => RouteNode<TMetadata, TContext>;
|
|
11
|
+
getPathnameFromNode: (targetNode: RouteNode<TMetadata, TContext>, params?: SearchParams) => string | undefined;
|
|
12
|
+
freezeAppRoutes: () => ResolvedRouteTree<TMetadata, TContext, TRouteTree>;
|
|
11
13
|
_types: {
|
|
12
14
|
AppRoutesMetadata: TMetadata;
|
|
13
15
|
AppRoutesContext: TContext;
|
|
14
16
|
AppRoutesPathname: RoutePathname<TMetadata, TContext, TRouteTree>;
|
|
17
|
+
AppRouteNode: RouteNode<TMetadata, TContext>;
|
|
15
18
|
};
|
|
16
19
|
};
|
|
17
20
|
|
package/dist/routes.utils.js
CHANGED
|
@@ -20,8 +20,49 @@ var getSafely = /* @__PURE__ */ __name((splitter, obj, path) => {
|
|
|
20
20
|
}
|
|
21
21
|
return value;
|
|
22
22
|
}, "getSafely");
|
|
23
|
+
var findObjectPath = /* @__PURE__ */ __name((root, target, splitter = "/", path = splitter) => {
|
|
24
|
+
for (const key in root) {
|
|
25
|
+
if (key === "_metadata") {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
const current = root[key];
|
|
29
|
+
if (current === target) return path + key;
|
|
30
|
+
if (typeof current === "object" && current !== null) {
|
|
31
|
+
const result = findObjectPath(current, target, splitter, path + key + splitter);
|
|
32
|
+
if (result) return result;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return void 0;
|
|
36
|
+
}, "findObjectPath");
|
|
37
|
+
var replaceDynamicSegments = /* @__PURE__ */ __name((pathname, params) => {
|
|
38
|
+
if (!params) return pathname;
|
|
39
|
+
return pathname.replace(/\[([^\]]+)\]/g, (_, key) => {
|
|
40
|
+
const value = params[key.toString()];
|
|
41
|
+
if (value === void 0 || value === null) return `[${key}]`;
|
|
42
|
+
return Array.isArray(value) ? value.join(",") : value.toString();
|
|
43
|
+
});
|
|
44
|
+
}, "replaceDynamicSegments");
|
|
23
45
|
var createAppRoutes = /* @__PURE__ */ __name(() => (appRoutes) => {
|
|
24
|
-
const
|
|
46
|
+
const ROUTE_NODE_COMMON_KEY = "_metadata";
|
|
47
|
+
const freezeAppRoutes = /* @__PURE__ */ __name(() => {
|
|
48
|
+
const copiedAppRoutes = { ...appRoutes };
|
|
49
|
+
const freeze = /* @__PURE__ */ __name((obj) => {
|
|
50
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
51
|
+
Object.defineProperty(obj, key, {
|
|
52
|
+
writable: false,
|
|
53
|
+
enumerable: key !== ROUTE_NODE_COMMON_KEY,
|
|
54
|
+
configurable: false
|
|
55
|
+
});
|
|
56
|
+
if (typeof value === "object" && value !== null) {
|
|
57
|
+
freeze(value);
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}, "freeze");
|
|
61
|
+
freeze(copiedAppRoutes);
|
|
62
|
+
return copiedAppRoutes;
|
|
63
|
+
}, "freezeAppRoutes");
|
|
64
|
+
const frozenAppRoutes = freezeAppRoutes();
|
|
65
|
+
const Context = react.createContext(frozenAppRoutes);
|
|
25
66
|
const useAppRoutes = /* @__PURE__ */ __name(() => {
|
|
26
67
|
return react.useContext(Context);
|
|
27
68
|
}, "useAppRoutes");
|
|
@@ -30,12 +71,19 @@ var createAppRoutes = /* @__PURE__ */ __name(() => (appRoutes) => {
|
|
|
30
71
|
return getSafely("/", routes, pathname);
|
|
31
72
|
}, "useCurrentRouteNode");
|
|
32
73
|
const AppRoutesProvider = /* @__PURE__ */ __name(({ children }) => {
|
|
33
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value:
|
|
74
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value: frozenAppRoutes, children });
|
|
34
75
|
}, "AppRoutesProvider");
|
|
76
|
+
const getPathnameFromNode = /* @__PURE__ */ __name((targetNode, params) => {
|
|
77
|
+
const pathname = findObjectPath(appRoutes, targetNode);
|
|
78
|
+
if (!pathname) return void 0;
|
|
79
|
+
return replaceDynamicSegments(pathname, params);
|
|
80
|
+
}, "getPathnameFromNode");
|
|
35
81
|
return {
|
|
36
82
|
AppRoutesProvider,
|
|
37
83
|
useAppRoutes,
|
|
38
84
|
useCurrentRouteNode,
|
|
85
|
+
getPathnameFromNode,
|
|
86
|
+
freezeAppRoutes,
|
|
39
87
|
_types: {}
|
|
40
88
|
};
|
|
41
89
|
}, "createAppRoutes");
|
package/dist/routes.utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/object.utils.ts","../src/routes.utils.tsx"],"names":["createContext","useContext"],"mappings":";;;;;;;;;AAGO,IAAM,SAAA,mBAAY,MAAA,CAAA,CACvB,QAAA,EACA,GAAA,EACA,IAAA,KACyC;AACzC,EAAA,IAAI,IAAA,KAAS,EAAA,IAAM,IAAA,KAAS,QAAA,EAAU,OAAO,GAAA;AAE7C,EAAA,MAAM,IAAA,GAAQ,KAAgB,KAAA,CAAM,QAAQ,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAG,CAAA;AACjE,EAAA,IAAI,KAAA,GAAiB,GAAA;AAErB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/D,MAAA,KAAA,GAAS,MAAkC,GAAG,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT,CAAA,EAnByB,WAAA,CAAA;
|
|
1
|
+
{"version":3,"sources":["../src/object.utils.ts","../src/routes.utils.tsx"],"names":["createContext","useContext"],"mappings":"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","file":"routes.utils.js","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n\nexport const findObjectPath = <T>(\n root: Record<string, unknown>,\n target: T,\n splitter = '/',\n path = splitter,\n): string | undefined => {\n for (const key in root) {\n // Skip _metadata keys during traversal\n if (key === '_metadata') {\n continue;\n }\n\n const current = root[key];\n\n if (current === target) return path + key;\n\n if (typeof current === 'object' && current !== null) {\n const result = findObjectPath(current as Record<string, unknown>, target, splitter, path + key + splitter);\n if (result) return result;\n }\n }\n\n return undefined;\n};\n\nexport const replaceDynamicSegments = (\n pathname: string,\n params?: SearchParams,\n): string => {\n if (!params) return pathname;\n\n return pathname.replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const value = params[key.toString()];\n if (value === undefined || value === null) return `[${key}]`;\n return Array.isArray(value) ? value.join(',') : value.toString();\n });\n};\n","import { createContext, ReactNode, useContext } from 'react';\nimport { findObjectPath, getSafely, replaceDynamicSegments } from './object.utils';\nimport { SearchParams } from './query.types';\nimport { BaseMetadata, PartialRouteTree, ResolvedRouteTree, RouteNode, RoutePathname, RouteTree } from './routes.types';\n\nexport const createAppRoutes =\n <TMetadata extends BaseMetadata, TContext>() =>\n <TRouteTree extends PartialRouteTree<TMetadata, TContext>>(appRoutes: TRouteTree & RouteTree<TMetadata, TContext, TRouteTree>) => {\n type Routes = ResolvedRouteTree<TMetadata, TContext, TRouteTree>;\n type Pathname = RoutePathname<TMetadata, TContext, TRouteTree>;\n type AppRouteNode = RouteNode<TMetadata, TContext>;\n\n const ROUTE_NODE_COMMON_KEY: keyof AppRouteNode = '_metadata';\n\n const freezeAppRoutes = () => {\n const copiedAppRoutes = { ...appRoutes };\n\n const freeze = (obj: Record<string, unknown>) => {\n Object.entries(obj).forEach(([key, value]) => {\n Object.defineProperty(obj, key, {\n writable: false,\n enumerable: key !== ROUTE_NODE_COMMON_KEY,\n configurable: false,\n });\n\n if (typeof value === 'object' && value !== null) {\n freeze(value as Record<string, unknown>);\n }\n });\n };\n\n freeze(copiedAppRoutes as Record<string, unknown>);\n return copiedAppRoutes as Routes;\n };\n\n const frozenAppRoutes = freezeAppRoutes();\n\n const Context = createContext<Routes>(frozenAppRoutes);\n\n const useAppRoutes = (): Routes => {\n return useContext(Context);\n };\n\n const useCurrentRouteNode = <TPath extends Pathname>(pathname: TPath) => {\n const routes = useContext(Context);\n return getSafely('/', routes, pathname) as RouteNode<TMetadata, TContext>;\n };\n\n const AppRoutesProvider = ({ children }: { children: ReactNode }) => {\n return <Context.Provider value={frozenAppRoutes}>{children}</Context.Provider>;\n };\n\n const getPathnameFromNode = (targetNode: AppRouteNode, params?: SearchParams): string | undefined => {\n const pathname = findObjectPath(appRoutes, targetNode);\n if (!pathname) return undefined;\n return replaceDynamicSegments(pathname, params);\n };\n\n return {\n AppRoutesProvider,\n useAppRoutes,\n useCurrentRouteNode,\n getPathnameFromNode,\n freezeAppRoutes,\n _types: {} as {\n AppRoutesMetadata: TMetadata;\n AppRoutesContext: TContext;\n AppRoutesPathname: Pathname;\n AppRouteNode: AppRouteNode;\n },\n };\n };\n"]}
|
package/dist/routes.utils.mjs
CHANGED
|
@@ -18,8 +18,49 @@ var getSafely = /* @__PURE__ */ __name((splitter, obj, path) => {
|
|
|
18
18
|
}
|
|
19
19
|
return value;
|
|
20
20
|
}, "getSafely");
|
|
21
|
+
var findObjectPath = /* @__PURE__ */ __name((root, target, splitter = "/", path = splitter) => {
|
|
22
|
+
for (const key in root) {
|
|
23
|
+
if (key === "_metadata") {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const current = root[key];
|
|
27
|
+
if (current === target) return path + key;
|
|
28
|
+
if (typeof current === "object" && current !== null) {
|
|
29
|
+
const result = findObjectPath(current, target, splitter, path + key + splitter);
|
|
30
|
+
if (result) return result;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
}, "findObjectPath");
|
|
35
|
+
var replaceDynamicSegments = /* @__PURE__ */ __name((pathname, params) => {
|
|
36
|
+
if (!params) return pathname;
|
|
37
|
+
return pathname.replace(/\[([^\]]+)\]/g, (_, key) => {
|
|
38
|
+
const value = params[key.toString()];
|
|
39
|
+
if (value === void 0 || value === null) return `[${key}]`;
|
|
40
|
+
return Array.isArray(value) ? value.join(",") : value.toString();
|
|
41
|
+
});
|
|
42
|
+
}, "replaceDynamicSegments");
|
|
21
43
|
var createAppRoutes = /* @__PURE__ */ __name(() => (appRoutes) => {
|
|
22
|
-
const
|
|
44
|
+
const ROUTE_NODE_COMMON_KEY = "_metadata";
|
|
45
|
+
const freezeAppRoutes = /* @__PURE__ */ __name(() => {
|
|
46
|
+
const copiedAppRoutes = { ...appRoutes };
|
|
47
|
+
const freeze = /* @__PURE__ */ __name((obj) => {
|
|
48
|
+
Object.entries(obj).forEach(([key, value]) => {
|
|
49
|
+
Object.defineProperty(obj, key, {
|
|
50
|
+
writable: false,
|
|
51
|
+
enumerable: key !== ROUTE_NODE_COMMON_KEY,
|
|
52
|
+
configurable: false
|
|
53
|
+
});
|
|
54
|
+
if (typeof value === "object" && value !== null) {
|
|
55
|
+
freeze(value);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}, "freeze");
|
|
59
|
+
freeze(copiedAppRoutes);
|
|
60
|
+
return copiedAppRoutes;
|
|
61
|
+
}, "freezeAppRoutes");
|
|
62
|
+
const frozenAppRoutes = freezeAppRoutes();
|
|
63
|
+
const Context = createContext(frozenAppRoutes);
|
|
23
64
|
const useAppRoutes = /* @__PURE__ */ __name(() => {
|
|
24
65
|
return useContext(Context);
|
|
25
66
|
}, "useAppRoutes");
|
|
@@ -28,12 +69,19 @@ var createAppRoutes = /* @__PURE__ */ __name(() => (appRoutes) => {
|
|
|
28
69
|
return getSafely("/", routes, pathname);
|
|
29
70
|
}, "useCurrentRouteNode");
|
|
30
71
|
const AppRoutesProvider = /* @__PURE__ */ __name(({ children }) => {
|
|
31
|
-
return /* @__PURE__ */ jsx(Context.Provider, { value:
|
|
72
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value: frozenAppRoutes, children });
|
|
32
73
|
}, "AppRoutesProvider");
|
|
74
|
+
const getPathnameFromNode = /* @__PURE__ */ __name((targetNode, params) => {
|
|
75
|
+
const pathname = findObjectPath(appRoutes, targetNode);
|
|
76
|
+
if (!pathname) return void 0;
|
|
77
|
+
return replaceDynamicSegments(pathname, params);
|
|
78
|
+
}, "getPathnameFromNode");
|
|
33
79
|
return {
|
|
34
80
|
AppRoutesProvider,
|
|
35
81
|
useAppRoutes,
|
|
36
82
|
useCurrentRouteNode,
|
|
83
|
+
getPathnameFromNode,
|
|
84
|
+
freezeAppRoutes,
|
|
37
85
|
_types: {}
|
|
38
86
|
};
|
|
39
87
|
}, "createAppRoutes");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/object.utils.ts","../src/routes.utils.tsx"],"names":[],"mappings":";;;;;;;AAGO,IAAM,SAAA,mBAAY,MAAA,CAAA,CACvB,QAAA,EACA,GAAA,EACA,IAAA,KACyC;AACzC,EAAA,IAAI,IAAA,KAAS,EAAA,IAAM,IAAA,KAAS,QAAA,EAAU,OAAO,GAAA;AAE7C,EAAA,MAAM,IAAA,GAAQ,KAAgB,KAAA,CAAM,QAAQ,EAAE,MAAA,CAAO,CAAC,QAAQ,GAAG,CAAA;AACjE,EAAA,IAAI,KAAA,GAAiB,GAAA;AAErB,EAAA,KAAA,MAAW,OAAO,IAAA,EAAM;AACtB,IAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,IAAA,IAAQ,OAAO,KAAA,EAAO;AAC/D,MAAA,KAAA,GAAS,MAAkC,GAAG,CAAA;AAAA,IAChD,CAAA,MAAO;AACL,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT,CAAA,EAnByB,WAAA,CAAA;
|
|
1
|
+
{"version":3,"sources":["../src/object.utils.ts","../src/routes.utils.tsx"],"names":[],"mappings":"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","file":"routes.utils.mjs","sourcesContent":["import { Paths, PathValue } from './path.types';\nimport { SearchParams } from './query.types';\n\nexport const getSafely = <TObject, TSplitter extends string, TPath extends string & Paths<TObject, TSplitter>>(\n splitter: TSplitter,\n obj: TObject,\n path: TPath,\n): PathValue<TObject, TPath, TSplitter> => {\n if (path === '' || path === splitter) return obj as PathValue<TObject, TPath, TSplitter>;\n\n const keys = (path as string).split(splitter).filter((key) => key);\n let value: unknown = obj;\n\n for (const key of keys) {\n if (typeof value === 'object' && value !== null && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return undefined as PathValue<TObject, TPath, TSplitter>;\n }\n }\n\n return value as PathValue<TObject, TPath, TSplitter>;\n};\n\nexport type SearchParamsStringOptions = {\n includeQuestionMark?: boolean;\n};\n\nexport const toSearchParamsString = (\n searchParams: SearchParams,\n options: SearchParamsStringOptions = { includeQuestionMark: true },\n): string => {\n const params: string[] = [];\n\n Object.entries(searchParams).forEach(([key, value]) => {\n if (value === undefined || value === null) {\n return;\n }\n\n const encodedKey = encodeURIComponent(key);\n\n if (Array.isArray(value)) {\n value.forEach((item) => {\n if (item !== undefined && item !== null) {\n params.push(`${encodedKey}=${encodeURIComponent(String(item))}`);\n }\n });\n } else {\n params.push(`${encodedKey}=${encodeURIComponent(String(value))}`);\n }\n });\n\n if (params.length === 0) {\n return '';\n }\n\n const searchParamsString = params.join('&');\n return options.includeQuestionMark ? `?${searchParamsString}` : searchParamsString;\n};\n\nexport const findObjectPath = <T>(\n root: Record<string, unknown>,\n target: T,\n splitter = '/',\n path = splitter,\n): string | undefined => {\n for (const key in root) {\n // Skip _metadata keys during traversal\n if (key === '_metadata') {\n continue;\n }\n\n const current = root[key];\n\n if (current === target) return path + key;\n\n if (typeof current === 'object' && current !== null) {\n const result = findObjectPath(current as Record<string, unknown>, target, splitter, path + key + splitter);\n if (result) return result;\n }\n }\n\n return undefined;\n};\n\nexport const replaceDynamicSegments = (\n pathname: string,\n params?: SearchParams,\n): string => {\n if (!params) return pathname;\n\n return pathname.replace(/\\[([^\\]]+)\\]/g, (_, key) => {\n const value = params[key.toString()];\n if (value === undefined || value === null) return `[${key}]`;\n return Array.isArray(value) ? value.join(',') : value.toString();\n });\n};\n","import { createContext, ReactNode, useContext } from 'react';\nimport { findObjectPath, getSafely, replaceDynamicSegments } from './object.utils';\nimport { SearchParams } from './query.types';\nimport { BaseMetadata, PartialRouteTree, ResolvedRouteTree, RouteNode, RoutePathname, RouteTree } from './routes.types';\n\nexport const createAppRoutes =\n <TMetadata extends BaseMetadata, TContext>() =>\n <TRouteTree extends PartialRouteTree<TMetadata, TContext>>(appRoutes: TRouteTree & RouteTree<TMetadata, TContext, TRouteTree>) => {\n type Routes = ResolvedRouteTree<TMetadata, TContext, TRouteTree>;\n type Pathname = RoutePathname<TMetadata, TContext, TRouteTree>;\n type AppRouteNode = RouteNode<TMetadata, TContext>;\n\n const ROUTE_NODE_COMMON_KEY: keyof AppRouteNode = '_metadata';\n\n const freezeAppRoutes = () => {\n const copiedAppRoutes = { ...appRoutes };\n\n const freeze = (obj: Record<string, unknown>) => {\n Object.entries(obj).forEach(([key, value]) => {\n Object.defineProperty(obj, key, {\n writable: false,\n enumerable: key !== ROUTE_NODE_COMMON_KEY,\n configurable: false,\n });\n\n if (typeof value === 'object' && value !== null) {\n freeze(value as Record<string, unknown>);\n }\n });\n };\n\n freeze(copiedAppRoutes as Record<string, unknown>);\n return copiedAppRoutes as Routes;\n };\n\n const frozenAppRoutes = freezeAppRoutes();\n\n const Context = createContext<Routes>(frozenAppRoutes);\n\n const useAppRoutes = (): Routes => {\n return useContext(Context);\n };\n\n const useCurrentRouteNode = <TPath extends Pathname>(pathname: TPath) => {\n const routes = useContext(Context);\n return getSafely('/', routes, pathname) as RouteNode<TMetadata, TContext>;\n };\n\n const AppRoutesProvider = ({ children }: { children: ReactNode }) => {\n return <Context.Provider value={frozenAppRoutes}>{children}</Context.Provider>;\n };\n\n const getPathnameFromNode = (targetNode: AppRouteNode, params?: SearchParams): string | undefined => {\n const pathname = findObjectPath(appRoutes, targetNode);\n if (!pathname) return undefined;\n return replaceDynamicSegments(pathname, params);\n };\n\n return {\n AppRoutesProvider,\n useAppRoutes,\n useCurrentRouteNode,\n getPathnameFromNode,\n freezeAppRoutes,\n _types: {} as {\n AppRoutesMetadata: TMetadata;\n AppRoutesContext: TContext;\n AppRoutesPathname: Pathname;\n AppRouteNode: AppRouteNode;\n },\n };\n };\n"]}
|