diff --git a/packages/houdini-react/src/plugin/codegen/entries.test.ts b/packages/houdini-react/src/plugin/codegen/entries.test.ts
index b40ef8d8b..43d6fbde7 100644
--- a/packages/houdini-react/src/plugin/codegen/entries.test.ts
+++ b/packages/houdini-react/src/plugin/codegen/entries.test.ts
@@ -41,11 +41,11 @@ test('composes layouts and pages', async function () {
{ plugins: ['jsx'] }
)
expect(page_entry).toMatchInlineSnapshot(`
- import Layout___ from "../layouts/__.jsx";
- import Layout___subRoute from "../layouts/__subRoute.jsx";
- import Page___subRoute__nested from "../pages/__subRoute__nested.jsx";
- import PageFallback___subRoute__nested from "../fallbacks/page/__subRoute__nested.jsx";
- import LayoutFallback___subRoute__nested from "../../fallbacks/layout";
+ import Layout__0 from "../layouts/_0.jsx";
+ import Layout__0subRoute from "../layouts/_0subRoute.jsx";
+ import Page__0subRoute_0nested from "../pages/_0subRoute_0nested.jsx";
+ import PageFallback__0subRoute_0nested from "../fallbacks/page/_0subRoute_0nested.jsx";
+ import LayoutFallback__0subRoute_0nested from "../../fallbacks/layout";
export default (
{
@@ -53,15 +53,15 @@ test('composes layouts and pages', async function () {
}
) => {
return (
- (
-
-
-
-
-
-
-
- )
+ (
+
+
+
+
+
+
+
+ )
);
};
`)
@@ -74,7 +74,7 @@ test('composes layouts and pages', async function () {
)
expect(page_unit).toMatchInlineSnapshot(`
import { useQueryResult } from "$houdini/plugins/houdini-react/runtime/routing/components/Router";
- import Component___subRoute__nested from "../../../../../src/routes/subRoute/nested/+page";
+ import Component__0subRoute_0nested from "../../../../../src/routes/subRoute/nested/+page";
export default (
{
@@ -84,9 +84,9 @@ test('composes layouts and pages', async function () {
const [FinalQuery$data, FinalQuery$handle] = useQueryResult("FinalQuery");
return (
- (
+ (
{children}
- )
+ )
);
};
`)
@@ -99,7 +99,7 @@ test('composes layouts and pages', async function () {
)
expect(root_layout_unit).toMatchInlineSnapshot(`
import { useQueryResult } from "$houdini/plugins/houdini-react/runtime/routing/components/Router";
- import Component___ from "../../../../../src/routes/+layout";
+ import Component__0 from "../../../../../src/routes/+layout";
export default (
{
@@ -107,9 +107,9 @@ test('composes layouts and pages', async function () {
}
) => {
return (
- (
+ (
{children}
- )
+ )
);
};
`)
@@ -122,7 +122,7 @@ test('composes layouts and pages', async function () {
)
expect(deep_layout_unit).toMatchInlineSnapshot(`
import { useQueryResult } from "$houdini/plugins/houdini-react/runtime/routing/components/Router";
- import Component___subRoute from "../../../../../src/routes/subRoute/+layout";
+ import Component__0subRoute from "../../../../../src/routes/subRoute/+layout";
export default (
{
@@ -133,13 +133,13 @@ test('composes layouts and pages', async function () {
const [SubQuery$data, SubQuery$handle] = useQueryResult("SubQuery");
return (
- (
{children}
- )
+ )
);
};
`)
diff --git a/packages/houdini-react/src/plugin/codegen/manifest.test.ts b/packages/houdini-react/src/plugin/codegen/manifest.test.ts
index 67f3168e8..3a5e43af6 100644
--- a/packages/houdini-react/src/plugin/codegen/manifest.test.ts
+++ b/packages/houdini-react/src/plugin/codegen/manifest.test.ts
@@ -25,6 +25,84 @@ test('empty routes dir generates empty manifest', async function () {
`)
})
+test('route groups', async function () {
+ const config = await test_config()
+
+ // create the mock filesystem
+ await fs.mock({
+ [config.routesDir]: {
+ '+layout.tsx': mockView([]),
+ '(subRoute)': {
+ '+layout.tsx': mockView(['RootQuery']),
+ '+layout.gql': mockQuery('RootQuery'),
+ nested: {
+ '+page.gql': mockQuery('FinalQuery', true),
+ '+page.tsx': mockView(['FinalQuery']),
+ },
+ },
+ },
+ })
+
+ expect(
+ await load_manifest({
+ config,
+ })
+ ).toMatchInlineSnapshot(`
+ {
+ "pages": {
+ "_0_3subRoute_4_0nested": {
+ "id": "_0_3subRoute_4_0nested",
+ "queries": [
+ "FinalQuery"
+ ],
+ "url": "/(subRoute)/nested",
+ "layouts": [
+ "_0",
+ "_0_3subRoute_4"
+ ],
+ "path": "(subRoute)/nested/+page.tsx"
+ }
+ },
+ "layouts": {
+ "_0": {
+ "id": "_0",
+ "queries": [],
+ "url": "/",
+ "layouts": [],
+ "path": "+layout.tsx"
+ },
+ "_0_3subRoute_4": {
+ "id": "_0_3subRoute_4",
+ "queries": [
+ "RootQuery"
+ ],
+ "url": "/(subRoute)/",
+ "layouts": [
+ "_0"
+ ],
+ "path": "(subRoute)/+layout.tsx"
+ }
+ },
+ "page_queries": {
+ "_0_3subRoute_4_0nested": {
+ "path": "(subRoute)/nested/+page.gql",
+ "name": "FinalQuery",
+ "url": "/(subRoute)/nested/",
+ "loading": true
+ }
+ },
+ "layout_queries": {
+ "_0_3subRoute_4": {
+ "path": "(subRoute)/+layout.gql",
+ "name": "RootQuery",
+ "url": "/(subRoute)/",
+ "loading": false
+ }
+ }
+ }
+ `)
+})
+
test('nested route structure happy path', async function () {
const config = await test_config()
@@ -59,95 +137,95 @@ test('nested route structure happy path', async function () {
).resolves.toMatchInlineSnapshot(`
{
"pages": {
- "__": {
- "id": "__",
+ "_0": {
+ "id": "_0",
"queries": [
"RootQuery"
],
"url": "/",
"layouts": [
- "__"
+ "_0"
],
"path": "+page.tsx"
},
- "__subRoute": {
- "id": "__subRoute",
+ "_0subRoute": {
+ "id": "_0subRoute",
"queries": [
"SubQuery",
"RootQuery"
],
"url": "/subRoute",
"layouts": [
- "__",
- "__subRoute"
+ "_0",
+ "_0subRoute"
],
"path": "subRoute/+page.jsx"
},
- "__another": {
- "id": "__another",
+ "_0another": {
+ "id": "_0another",
"queries": [
"MyQuery",
"MyLayoutQuery"
],
"url": "/another",
"layouts": [
- "__",
- "__another"
+ "_0",
+ "_0another"
],
"path": "another/+page.tsx"
},
- "__subRoute__nested": {
- "id": "__subRoute__nested",
+ "_0subRoute_0nested": {
+ "id": "_0subRoute_0nested",
"queries": [
"FinalQuery"
],
"url": "/subRoute/nested",
"layouts": [
- "__",
- "__subRoute"
+ "_0",
+ "_0subRoute"
],
"path": "subRoute/nested/+page.tsx"
}
},
"layouts": {
- "__": {
- "id": "__",
+ "_0": {
+ "id": "_0",
"queries": [],
"url": "/",
"layouts": [],
"path": "+layout.tsx"
},
- "__another": {
- "id": "__another",
+ "_0another": {
+ "id": "_0another",
"queries": [
"RootQuery"
],
"url": "/another/",
"layouts": [
- "__"
+ "_0"
],
"path": "another/+layout.tsx"
},
- "__subRoute": {
- "id": "__subRoute",
+ "_0subRoute": {
+ "id": "_0subRoute",
"queries": [
"RootQuery"
],
"url": "/subRoute/",
"layouts": [
- "__"
+ "_0"
],
"path": "subRoute/+layout.tsx"
}
},
"page_queries": {
- "__another": {
+ "_0another": {
"path": "another/+page.gql",
"name": "MyQuery",
"url": "/another/",
"loading": false
},
- "__subRoute__nested": {
+ "_0subRoute_0nested": {
"path": "subRoute/nested/+page.gql",
"name": "FinalQuery",
"url": "/subRoute/nested/",
@@ -155,19 +233,19 @@ test('nested route structure happy path', async function () {
}
},
"layout_queries": {
- "__": {
+ "_0": {
"path": "+layout.gql",
"name": "RootQuery",
"url": "/",
"loading": true
},
- "__another": {
+ "_0another": {
"path": "another/+layout.gql",
"name": "MyLayoutQuery",
"url": "/another/",
"loading": false
},
- "__subRoute": {
+ "_0subRoute": {
"path": "subRoute/+layout.gql",
"name": "SubQuery",
"url": "/subRoute/",
diff --git a/packages/houdini-react/src/plugin/codegen/manifest.ts b/packages/houdini-react/src/plugin/codegen/manifest.ts
index df2cae145..54739d17c 100644
--- a/packages/houdini-react/src/plugin/codegen/manifest.ts
+++ b/packages/houdini-react/src/plugin/codegen/manifest.ts
@@ -296,7 +296,7 @@ export async function extractQueries(source: string): Promise {
throw new Error('Props should be specified as an object pattern.')
}
} else {
- throw new Error('Default export function has no arguments.')
+ return []
}
return props.filter((p) => p !== 'children')
diff --git a/packages/houdini-react/src/plugin/codegen/router.test.ts b/packages/houdini-react/src/plugin/codegen/router.test.ts
index 2a99a8391..51ab039ea 100644
--- a/packages/houdini-react/src/plugin/codegen/router.test.ts
+++ b/packages/houdini-react/src/plugin/codegen/router.test.ts
@@ -44,8 +44,8 @@ test('happy path', async function () {
.toMatchInlineSnapshot(`
"export default {
pages: {
- \\"__\\": {
- id: \\"__\\",
+ \\"_0\\": {
+ id: \\"_0\\",
pattern: /^\\\\/$/,
params: [],
@@ -57,11 +57,11 @@ test('happy path', async function () {
}
},
- component: () => import(\\"../units/entries/__\\")
+ component: () => import(\\"../units/entries/_0\\")
},
- \\"____id__\\": {
- id: \\"____id__\\",
+ \\"_0_2id_1\\": {
+ id: \\"_0_2id_1\\",
pattern: /^\\\\/([^/]+?)\\\\/?$/,
params: [{\\"name\\":\\"id\\",\\"optional\\":false,\\"rest\\":false,\\"chained\\":false}],
@@ -77,11 +77,11 @@ test('happy path', async function () {
}
},
- component: () => import(\\"../units/entries/____id__\\")
+ component: () => import(\\"../units/entries/_0_2id_1\\")
},
- \\"__another\\": {
- id: \\"__another\\",
+ \\"_0another\\": {
+ id: \\"_0another\\",
pattern: /^\\\\/another\\\\/?$/,
params: [],
@@ -101,11 +101,11 @@ test('happy path', async function () {
}
},
- component: () => import(\\"../units/entries/__another\\")
+ component: () => import(\\"../units/entries/_0another\\")
},
- \\"____id____nested\\": {
- id: \\"____id____nested\\",
+ \\"_0_2id_1_0nested\\": {
+ id: \\"_0_2id_1_0nested\\",
pattern: /^\\\\/([^/]+?)\\\\/nested\\\\/?$/,
params: [{\\"name\\":\\"id\\",\\"optional\\":false,\\"rest\\":false,\\"chained\\":false}],
@@ -121,23 +121,23 @@ test('happy path', async function () {
}
},
- component: () => import(\\"../units/entries/____id____nested\\")
+ component: () => import(\\"../units/entries/_0_2id_1_0nested\\")
},
},
layouts: {
- \\"__\\": {
- id: \\"__\\",
+ \\"_0\\": {
+ id: \\"_0\\",
queries: [],
},
- \\"____id__\\": {
- id: \\"____id__\\",
+ \\"_0_2id_1\\": {
+ id: \\"_0_2id_1\\",
queries: [\\"RootQuery\\"],
},
- \\"__another\\": {
- id: \\"__another\\",
+ \\"_0another\\": {
+ id: \\"_0another\\",
queries: [\\"RootQuery\\"],
}
@@ -181,8 +181,8 @@ test('loading state at root', async function () {
.toMatchInlineSnapshot(`
"export default {
pages: {
- \\"__\\": {
- id: \\"__\\",
+ \\"_0\\": {
+ id: \\"_0\\",
pattern: /^\\\\/$/,
params: [],
@@ -194,11 +194,11 @@ test('loading state at root', async function () {
}
},
- component: () => import(\\"../units/entries/__\\")
+ component: () => import(\\"../units/entries/_0\\")
},
- \\"____id__\\": {
- id: \\"____id__\\",
+ \\"_0_2id_1\\": {
+ id: \\"_0_2id_1\\",
pattern: /^\\\\/([^/]+?)\\\\/?$/,
params: [{\\"name\\":\\"id\\",\\"optional\\":false,\\"rest\\":false,\\"chained\\":false}],
@@ -214,11 +214,11 @@ test('loading state at root', async function () {
}
},
- component: () => import(\\"../units/entries/____id__\\")
+ component: () => import(\\"../units/entries/_0_2id_1\\")
},
- \\"__another\\": {
- id: \\"__another\\",
+ \\"_0another\\": {
+ id: \\"_0another\\",
pattern: /^\\\\/another\\\\/?$/,
params: [],
@@ -238,11 +238,11 @@ test('loading state at root', async function () {
}
},
- component: () => import(\\"../units/entries/__another\\")
+ component: () => import(\\"../units/entries/_0another\\")
},
- \\"____id____nested\\": {
- id: \\"____id____nested\\",
+ \\"_0_2id_1_0nested\\": {
+ id: \\"_0_2id_1_0nested\\",
pattern: /^\\\\/([^/]+?)\\\\/nested\\\\/?$/,
params: [{\\"name\\":\\"id\\",\\"optional\\":false,\\"rest\\":false,\\"chained\\":false}],
@@ -258,23 +258,23 @@ test('loading state at root', async function () {
}
},
- component: () => import(\\"../units/entries/____id____nested\\")
+ component: () => import(\\"../units/entries/_0_2id_1_0nested\\")
},
},
layouts: {
- \\"__\\": {
- id: \\"__\\",
+ \\"_0\\": {
+ id: \\"_0\\",
queries: [],
},
- \\"____id__\\": {
- id: \\"____id__\\",
+ \\"_0_2id_1\\": {
+ id: \\"_0_2id_1\\",
queries: [\\"RootQuery\\"],
},
- \\"__another\\": {
- id: \\"__another\\",
+ \\"_0another\\": {
+ id: \\"_0another\\",
queries: [\\"RootQuery\\"],
}
diff --git a/packages/houdini-react/src/plugin/conventions.ts b/packages/houdini-react/src/plugin/conventions.ts
index 51af0f205..66d65d0ad 100644
--- a/packages/houdini-react/src/plugin/conventions.ts
+++ b/packages/houdini-react/src/plugin/conventions.ts
@@ -90,13 +90,14 @@ export function normalize_path(path: string) {
if (path.endsWith('/') && path.length > 1) {
path = path.substring(0, path.length - 1)
}
- const special_chars = ['/', ']', '[']
- const mask = '__'
+ const special_chars = ['/', ']', '[', '(', ')']
+ const mask = '_'
let copy = ''
for (const char of path) {
- if (special_chars.includes(char)) {
- copy += mask
+ const match = special_chars.indexOf(char)
+ if (match !== -1) {
+ copy += mask + match.toString()
} else {
copy += char
}