{"id":15769877,"url":"https://github.com/adrien2p/archipelago","last_synced_at":"2025-03-31T11:24:07.969Z","repository":{"id":176506255,"uuid":"654515809","full_name":"adrien2p/archipelago","owner":"adrien2p","description":null,"archived":false,"fork":false,"pushed_at":"2023-06-29T08:41:26.000Z","size":133,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-10-11T14:53:46.436Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adrien2p.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-16T09:48:09.000Z","updated_at":"2023-09-19T23:34:55.000Z","dependencies_parsed_at":null,"dependency_job_id":"8b92d206-df4c-4ab0-8ae0-c9ec08dab0b0","html_url":"https://github.com/adrien2p/archipelago","commit_stats":null,"previous_names":["adrien2p/archipelago"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrien2p%2Farchipelago","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrien2p%2Farchipelago/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrien2p%2Farchipelago/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adrien2p%2Farchipelago/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adrien2p","download_url":"https://codeload.github.com/adrien2p/archipelago/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246459272,"owners_count":20780912,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-04T14:20:29.459Z","updated_at":"2025-03-31T11:24:07.952Z","avatar_url":"https://github.com/adrien2p.png","language":"TypeScript","funding_links":["https://github.com/sponsors/adrien2p"],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003earchipelago\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/adrien2p/archipelago/graphs/contributors\"\u003e\u003cimg alt=\"Contributors\" src=\"https://img.shields.io/github/contributors/adrien2p/archipelago.svg\" height=\"20\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/adrien2p/archipelago/commits/main\"\u003e\u003cimg alt=\"Activity\" src=\"https://img.shields.io/github/commit-activity/m/adrien2p/archipelago?style=flat\" height=\"20\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/adrien2p/archipelago/issues\"\u003e\u003cimg alt=\"Issues\" src=\"https://img.shields.io/github/issues/adrien2p/archipelago?style=flat\" height=\"20\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/adrien2p/archipelago/blob/main/LICENSE\"\u003e\u003cimg alt=\"Licence\" src=\"https://img.shields.io/github/license/adrien2p/archipelago?style=flat\" height=\"20\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/adrien2p/archipelago/blob/main/CONTRIBUTING.md\"\u003e\u003cimg alt=\"Contributing\" src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat\" height=\"20\"/\u003e\u003c/a\u003e\n    \u003ca href=\"https://github.com/sponsors/adrien2p\"\u003e\u003cimg alt=\"sponsor\" src=\"https://img.shields.io/static/v1?label=Sponsor\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23fe8e86\" height=\"20\"/\u003e\u003c/a\u003e\n\u003c/p\u003e    \n\n\u003cp align=\"center\"\u003e\n  \u003cb\u003eFile base routing system for express.js :bullettrain_side:\u003c/b\u003e\u003c/br\u003e\n\u003c/p\u003e\n\n\u003cbr /\u003e\n\n- [Installation](#installation)\n- [Documentation](#documentation)\n\n## Installation\n\n```bash\nnpm install archipelago\n```\n\nor if you use yarn\n    \n```bash\nyarn add archipelago\n```\n\n### Basic usage\n\n```ts\nimport express from 'express';\nimport archipelago from 'archipelago';\n\n(async () =\u003e {\n  const app = express();\n  await archipelago(app, {\n    rootDir: './routes',\n    // onRouteLoading?: (descriptor) =\u003e Promise\u003cvoid\u003e\n    // strict?: boolean\n  });\n})();\n```\n\nor using top level await\n\n```ts\nimport express from 'express';\nimport archipelago from 'archipelago';\n\nconst app = express();\nawait archipelago(app, {\n   rootDir: './routes'\n  // onRouteLoading?: (descriptor) =\u003e Promise\u003cvoid\u003e\n  // strict?: boolean\n});\n```\n\nHere are the options you can pass to the `archipelago` function:\n- **[required]** `rootDir`: The directory from which to load the routes\n- **[optional]** `onRouteLoading`: A function that will be called before a route is loaded\n- **[optional]** `strict`: A boolean to indicate if the router should throw an error if a config is not exported by a route file\n\n## Documentation\n\n### Defining global place for middlewares\n\nthe special directory `_middlewares` allow you to define middlewares that will be applied to the specified routes.\n\nFor example, if you want to apply a middleware to all routes in the `./routes/users` directory, you can create a file\n`./routes/_middlewares/users.ts` with the following content:\n\n```ts\nexport function userMiddleware(req, res, next) {\n  console.log('before reaching users');\n  next();\n}\n\nexport const config = {\n  routes: [{\n    method: 'all',\n    path: \"/users\",\n    middlewares: [userMiddleware],\n  }],\n}\n```\n\n\n### Defining routes\n\nThe routes will be built based on the path of the file.\nFor example, if you have a file in `./routes/users.js`, the route will be `/users`.\n\nEach route file contains a config object that is exported to be loaded in the router.\nThis config object contains the following properties:\n- **[optional]** `routes`: an array of route descriptors. (here)[./src/types.ts#L14]\n- **[optional]** `ignore`: a boolean to ignore the file in case you want to use it to store other functions or utils. (here)[./src/types.ts#L19]\n\n**PRIORITY:**\n\nThe routes are loaded depending on their priority. The routes with the lower number (highest priority) are loaded first.\nA wilcard route has a priority of Infinity. The smaller number, the higher is the priority.\n\n#### define a simple route\n\n```ts\n// ./routes/users/index.ts\nexport function list(req, res) {\n  res.send('Hello world');\n}\n\nexport const config = {\n  routes: [{\n    method: 'get',\n    handlers: [list],\n  }],\n}\n```\n\nthis route will be accessible at `/users` with the `GET` method.\n\n#### define a route with a parameter\n\n```ts\n// ./routes/users/[id].ts\nexport function get(req, res) {\n  res.send('Hello user ' + req.params.id);\n}\n\nexport const config = {\n  routes: [{\n    method: 'get',\n    handlers: [get],\n  }],\n}\n```\n\nthis route will be accessible at `/users/:id` with the `GET` method.\n\n#### define a route on all sub routes\n\n```ts\n// ./routes/users/[id].ts\nexport function beforeGetAndList(req, res) {\n  res.send(`Hello user${req.params.id ? ' ' + req.params.id : ''}`);\n}\n\nexport const config: Config = {\n  routes: [{\n    method: 'get',\n    handlers: [beforeGetAndList],\n  }],\n}\n```\n\nthis route will be applied to `/users/*` with the `GET` method and therefore will be fired before\nany subsequent route handler.\n\n### Hook yourself before a route is loading\n\nIn some circumstances, you may want to hook yourself before a route is loading.\nFor example if you want to apply some extra middlewares to a route, or if you want to check\nand consume the configuration for other purposes.\n\nTo do so, you can use the `onRouteLoading` hook (the type of the descriptor is available [here](./src/types.ts))\n\n```ts\nimport express from 'express';\nimport archipelago from 'archipelago';\n\nasync function onRouteLoading(descriptor) {\n  // do something with the descriptor\n  // ...\n  // You have access to everything the descriptor contains\n  // You can find the full types here https://github.com/adrien2p/archipelago/blob/main/src/types.ts\n  \n  return;\n}\n\nconst app = express();\nawait archipelago(app, {\n  rootDir: './routes',\n  onRouteLoading,\n});\n```\n\n# Contribute\n\nContributions are welcome! You can look at the contribution [guidelines](./CONTRIBUTING.md)\n\n[![-----------------------------------------------------](https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/cloudy.png)](#like-my-work-heartbeat)\n\n# Like my work? :heartbeat:\n\nThis project needs a :star: from you.\nIf you really like our projects, do not hesitate to back us \u003ca href=\"https://github.com/sponsors/adrien2p\"\u003e\u003cimg alt=\"sponsor\" src=\"https://img.shields.io/static/v1?label=Sponsor\u0026message=%E2%9D%A4\u0026logo=GitHub\u0026color=%23fe8e86\" height=\"20\"/\u003e\u003c/a\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrien2p%2Farchipelago","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadrien2p%2Farchipelago","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadrien2p%2Farchipelago/lists"}