@pylonsync/sdk 0.3.245 → 0.3.247
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/package.json +1 -1
- package/src/index.ts +27 -6
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -781,14 +781,27 @@ export async function discoverAppRoutes(opts?: {
|
|
|
781
781
|
}
|
|
782
782
|
walk(appDir, [], []);
|
|
783
783
|
|
|
784
|
+
// Segment kinds, least-to-most greedy:
|
|
785
|
+
// static "blog" rank 0 (most specific)
|
|
786
|
+
// dynamic param "[slug]" rank 1 → :slug
|
|
787
|
+
// catch-all "[...slug]" rank 2 → *slug (matches ≥1 segment)
|
|
788
|
+
// optional catch-all"[[...slug]]" rank 3 → *?slug (matches ≥0 segments)
|
|
789
|
+
// A catch-all is only valid as the LAST segment of a route (it consumes
|
|
790
|
+
// the rest of the path); Next.js enforces the same.
|
|
791
|
+
const isOptionalCatchAll = (s: string): boolean =>
|
|
792
|
+
s.startsWith("[[...") && s.endsWith("]]");
|
|
793
|
+
const isCatchAll = (s: string): boolean =>
|
|
794
|
+
s.startsWith("[...") && s.endsWith("]") && !isOptionalCatchAll(s);
|
|
784
795
|
const isParam = (s: string): boolean =>
|
|
785
|
-
s.startsWith("[") && s.endsWith("]");
|
|
796
|
+
s.startsWith("[") && s.endsWith("]") && !isCatchAll(s) && !isOptionalCatchAll(s);
|
|
797
|
+
const segRank = (s: string): number =>
|
|
798
|
+
isOptionalCatchAll(s) ? 3 : isCatchAll(s) ? 2 : isParam(s) ? 1 : 0;
|
|
786
799
|
pages.sort((a, b) => {
|
|
787
800
|
const minLen = Math.min(a.segments.length, b.segments.length);
|
|
788
801
|
for (let i = 0; i < minLen; i++) {
|
|
789
|
-
const
|
|
790
|
-
const
|
|
791
|
-
if (
|
|
802
|
+
const ar = segRank(a.segments[i]);
|
|
803
|
+
const br = segRank(b.segments[i]);
|
|
804
|
+
if (ar !== br) return ar - br; // more specific (lower rank) first
|
|
792
805
|
if (a.segments[i] !== b.segments[i]) {
|
|
793
806
|
return a.segments[i] < b.segments[i] ? -1 : 1;
|
|
794
807
|
}
|
|
@@ -796,9 +809,17 @@ export async function discoverAppRoutes(opts?: {
|
|
|
796
809
|
return a.segments.length - b.segments.length;
|
|
797
810
|
});
|
|
798
811
|
|
|
812
|
+
// Convert a discovered file segment to its route-pattern token. The Rust
|
|
813
|
+
// matcher (frontend.rs `match_ssr_route`) reads these markers back:
|
|
814
|
+
// :name dynamic param *name catch-all *?name optional catch-all
|
|
815
|
+
const segmentToToken = (s: string): string => {
|
|
816
|
+
if (isOptionalCatchAll(s)) return `*?${s.slice(5, -2)}`; // [[...x]] → *?x
|
|
817
|
+
if (isCatchAll(s)) return `*${s.slice(4, -1)}`; // [...x] → *x
|
|
818
|
+
if (isParam(s)) return `:${s.slice(1, -1)}`; // [x] → :x
|
|
819
|
+
return s;
|
|
820
|
+
};
|
|
799
821
|
const segmentsToPath = (segments: string[]): string =>
|
|
800
|
-
"/" +
|
|
801
|
-
segments.map((s) => (isParam(s) ? `:${s.slice(1, -1)}` : s)).join("/");
|
|
822
|
+
"/" + segments.map(segmentToToken).join("/");
|
|
802
823
|
|
|
803
824
|
const pageRoutes: RouteDefinition[] = pages.map((p) => ({
|
|
804
825
|
path: segmentsToPath(p.segments),
|