diff --git a/adonisrc.ts b/adonisrc.ts
index a2d8852..edd4ac4 100644
--- a/adonisrc.ts
+++ b/adonisrc.ts
@@ -1,4 +1,4 @@
-import { defineConfig } from '@adonisjs/core/app';
+import { defineConfig } from '@adonisjs/core/app'
export default defineConfig({
/*
@@ -13,6 +13,7 @@ export default defineConfig({
commands: [
() => import('@adonisjs/core/commands'),
() => import('@adonisjs/lucid/commands'),
+ () => import('@izzyjs/route/commands'),
],
/*
@@ -42,6 +43,8 @@ export default defineConfig({
() => import('@adonisjs/auth/auth_provider'),
() => import('@adonisjs/inertia/inertia_provider'),
() => import('@adonisjs/ally/ally_provider'),
+ () => import('@izzyjs/route/izzy_provider'),
+ () => import('#providers/route_provider')
],
/*
@@ -102,5 +105,6 @@ export default defineConfig({
assetsBundler: false,
unstable_assembler: {
onBuildStarting: [() => import('@adonisjs/vite/build_hook')],
+ onDevServerStarted: [() => import('@izzyjs/route/dev_hook')],
},
-});
+})
diff --git a/package-lock.json b/package-lock.json
index 7435d0f..895d8aa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,7 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@inertiajs/react": "^1.0.16",
+ "@izzyjs/route": "^1.1.0-0",
"@vinejs/vine": "^2.0.0",
"edge.js": "^6.0.2",
"i18next": "^23.11.3",
@@ -1905,6 +1906,18 @@
"react": "^16.9.0 || ^17.0.0 || ^18.0.0"
}
},
+ "node_modules/@izzyjs/route": {
+ "version": "1.1.0-0",
+ "resolved": "https://registry.npmjs.org/@izzyjs/route/-/route-1.1.0-0.tgz",
+ "integrity": "sha512-+I9gMZlQANIdIPPa1Pys2tUtzSGKSOKpGBM+Womhwi1rlMp03jsuAGCL1NvZ76M0RKWwrI9lRE7q5qyvZIOXYg==",
+ "engines": {
+ "node": ">=20.6.0"
+ },
+ "peerDependencies": {
+ "@adonisjs/core": "^6.2.0",
+ "edge.js": "^6.0.2"
+ }
+ },
"node_modules/@japa/assert": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@japa/assert/-/assert-3.0.0.tgz",
diff --git a/package.json b/package.json
index 7fcf36c..d059111 100644
--- a/package.json
+++ b/package.json
@@ -73,6 +73,7 @@
"@emotion/react": "^11.11.4",
"@emotion/styled": "^11.11.5",
"@inertiajs/react": "^1.0.16",
+ "@izzyjs/route": "^1.1.0-0",
"@vinejs/vine": "^2.0.0",
"edge.js": "^6.0.2",
"i18next": "^23.11.3",
diff --git a/providers/route_provider.ts b/providers/route_provider.ts
new file mode 100644
index 0000000..9efdca6
--- /dev/null
+++ b/providers/route_provider.ts
@@ -0,0 +1,5 @@
+export default class RouteProvider {
+ async boot() {
+ await import('../src/extensions.js');
+ }
+}
diff --git a/resources/views/inertia_layout.edge b/resources/views/inertia_layout.edge
index c4c812b..b32ea50 100644
--- a/resources/views/inertia_layout.edge
+++ b/resources/views/inertia_layout.edge
@@ -11,6 +11,7 @@
MyLinks
+ @routes()
@inertiaHead()
@viteReactRefresh()
@vite(['inertia/app/app.tsx', `inertia/pages/${page.component}.tsx`])
diff --git a/src/extensions.ts b/src/extensions.ts
new file mode 100644
index 0000000..2cfabce
--- /dev/null
+++ b/src/extensions.ts
@@ -0,0 +1,29 @@
+import { Response } from '@adonisjs/core/http';
+import { route } from '@izzyjs/route/client';
+import { RouteName } from '@izzyjs/route/types';
+
+type IzzyRouteOptions = {
+ params?: Record; //Params;
+ qs?: Record;
+ prefix?: string;
+};
+
+declare module '@adonisjs/core/http' {
+ export interface Response {
+ redirectToNamedRoute: (
+ routeName: RouteName,
+ options?: IzzyRouteOptions
+ ) => void;
+ }
+}
+
+Response.macro(
+ 'redirectToNamedRoute',
+ function (this: Response, routeName, options) {
+ const current = route(routeName, options);
+ this.redirect().toRoute(current.url, current.params, {
+ qs: current.qs,
+ disableRouteLookup: true,
+ });
+ }
+);
diff --git a/start/kernel.ts b/start/kernel.ts
index 609dec0..6f08863 100644
--- a/start/kernel.ts
+++ b/start/kernel.ts
@@ -29,6 +29,7 @@ server.use([
() => import('@adonisjs/cors/cors_middleware'),
() => import('@adonisjs/vite/vite_middleware'),
() => import('@adonisjs/inertia/inertia_middleware'),
+ () => import('@izzyjs/route/izzy_middleware'),
]);
/**
diff --git a/start/routes.ts b/start/routes.ts
index 4ed8908..12bc1da 100644
--- a/start/routes.ts
+++ b/start/routes.ts
@@ -1,36 +1,5 @@
-import PATHS from '#constants/paths';
-import { middleware } from '#start/kernel';
-import router from '@adonisjs/core/services/router';
-
-const LinksController = () => import('#controllers/links_controller');
-const CollectionsController = () =>
- import('#controllers/collections_controller');
-const UsersController = () => import('#controllers/users_controller');
-const AppsController = () => import('#controllers/apps_controller');
-const FaviconsController = () => import('#controllers/favicons_controller');
-
-router.get(PATHS.HOME, [AppsController, 'index']);
-router.post('/user/theme', [AppsController, 'updateUserTheme']);
-router.get(PATHS.AUTH.LOGIN, [UsersController, 'login']);
-router.get(PATHS.AUTH.GOOGLE, [UsersController, 'google']);
-router.get('/auth/callback', [UsersController, 'callbackAuth']);
-router.get('/favicon', [FaviconsController, 'index']);
-
-router
- .group(() => {
- router.get(PATHS.AUTH.LOGOUT, [UsersController, 'logout']);
- router.get(PATHS.DASHBOARD, [CollectionsController, 'index']);
-
- router.get(PATHS.COLLECTION.CREATE, [
- CollectionsController,
- 'showCreatePage',
- ]);
- router.post('/collections', [CollectionsController, 'store']);
-
- router.get(PATHS.COLLECTION.EDIT, [CollectionsController, 'showEditPage']);
- router.put('/collections/:id', [CollectionsController, 'update']);
-
- router.get(PATHS.LINK.CREATE, [LinksController, 'showCreatePage']);
- router.post('/links', [LinksController, 'store']);
- })
- .middleware([middleware.auth()]);
+import './routes/app.js';
+import './routes/auth.js';
+import './routes/collection.js';
+import './routes/favicon.js';
+import './routes/link.js';
diff --git a/start/routes/app.ts b/start/routes/app.ts
new file mode 100644
index 0000000..8af44d2
--- /dev/null
+++ b/start/routes/app.ts
@@ -0,0 +1,12 @@
+import router from '@adonisjs/core/services/router';
+const AppsController = () => import('#controllers/apps_controller');
+
+/**
+ * All routes for both logged and guest users
+ */
+router.group(() => {
+ router.get('/', [AppsController, 'index']).as('home');
+ router
+ .post('/user/theme', [AppsController, 'updateUserTheme'])
+ .as('user.theme');
+});
diff --git a/start/routes/auth.ts b/start/routes/auth.ts
new file mode 100644
index 0000000..4bd2186
--- /dev/null
+++ b/start/routes/auth.ts
@@ -0,0 +1,28 @@
+import { middleware } from '#start/kernel';
+import router from '@adonisjs/core/services/router';
+const UsersController = () => import('#controllers/users_controller');
+
+const ROUTES_PREFIX = '/auth';
+
+/**
+ * Auth routes for unauthicated users
+ */
+router
+ .group(() => {
+ router.get('/login', [UsersController, 'login']).as('auth.login');
+ router.get('/google', [UsersController, 'google']).as('auth.google');
+ router
+ .get('/callback', [UsersController, 'callbackAuth'])
+ .as('auth.callback');
+ })
+ .prefix(ROUTES_PREFIX);
+
+/**
+ * Routes for authenticated users
+ */
+router
+ .group(() => {
+ router.get('/logout', [UsersController, 'logout']).as('auth.logout');
+ })
+ .middleware([middleware.auth()])
+ .prefix(ROUTES_PREFIX);
diff --git a/start/routes/collection.ts b/start/routes/collection.ts
new file mode 100644
index 0000000..7f52d73
--- /dev/null
+++ b/start/routes/collection.ts
@@ -0,0 +1,31 @@
+import { middleware } from '#start/kernel';
+import router from '@adonisjs/core/services/router';
+const CollectionsController = () =>
+ import('#controllers/collections_controller');
+
+/**
+ * Routes for authenticated users
+ */
+router
+ .group(() => {
+ router.get('/dashboard', [CollectionsController, 'index']).as('dashboard');
+
+ router
+ .group(() => {
+ router
+ .get('/create', [CollectionsController, 'showCreatePage'])
+ .as('collection.create-form');
+ router
+ .post('/', [CollectionsController, 'store'])
+ .as('collection.create');
+
+ router
+ .get('/edit', [CollectionsController, 'showEditPage'])
+ .as('collection.edit-form');
+ router
+ .put('/:id', [CollectionsController, 'update'])
+ .as('collection.edit');
+ })
+ .prefix('/collections');
+ })
+ .middleware([middleware.auth()]);
diff --git a/start/routes/favicon.ts b/start/routes/favicon.ts
new file mode 100644
index 0000000..809feff
--- /dev/null
+++ b/start/routes/favicon.ts
@@ -0,0 +1,9 @@
+import router from '@adonisjs/core/services/router';
+const FaviconsController = () => import('#controllers/favicons_controller');
+
+/**
+ * Favicon routes
+ */
+router.group(() => {
+ router.get('/favicon', [FaviconsController, 'index']).as('favicon');
+});
diff --git a/start/routes/link.ts b/start/routes/link.ts
new file mode 100644
index 0000000..dae866d
--- /dev/null
+++ b/start/routes/link.ts
@@ -0,0 +1,16 @@
+import { middleware } from '#start/kernel';
+import router from '@adonisjs/core/services/router';
+const LinksController = () => import('#controllers/links_controller');
+
+/**
+ * Routes for authenticated users
+ */
+router
+ .group(() => {
+ router
+ .get('/create', [LinksController, 'showCreatePage'])
+ .as('link.create-form');
+ router.post('/', [LinksController, 'store']).as('link.create');
+ })
+ .middleware([middleware.auth()])
+ .prefix('/links');
diff --git a/tests/bootstrap.ts b/tests/bootstrap.ts
index 637ad68..6d62aab 100644
--- a/tests/bootstrap.ts
+++ b/tests/bootstrap.ts
@@ -3,6 +3,7 @@ import app from '@adonisjs/core/services/app';
import type { Config } from '@japa/runner/types';
import { pluginAdonisJS } from '@japa/plugin-adonisjs';
import testUtils from '@adonisjs/core/services/test_utils';
+import { izzyRoutePlugin } from '@izzyjs/route/plugins/japa';
/**
* This file is imported by the "bin/test.ts" entrypoint file
@@ -12,7 +13,11 @@ import testUtils from '@adonisjs/core/services/test_utils';
* Configure Japa plugins in the plugins array.
* Learn more - https://japa.dev/docs/runner-config#plugins-optional
*/
-export const plugins: Config['plugins'] = [assert(), pluginAdonisJS(app)];
+export const plugins: Config['plugins'] = [
+ assert(),
+ pluginAdonisJS(app),
+ izzyRoutePlugin(),
+];
/**
* Configure lifecycle function to run before and after all the