├── .eslintignore ├── .eslintrc.js ├── .github └── workflows │ ├── main.yml │ └── pr.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── LICENSE.md ├── README.md ├── benchmark ├── dangerfile.js ├── express.js ├── fastify.js ├── koa.js ├── package-lock.json ├── package.json └── routes │ └── index.js ├── examples ├── basic │ ├── package-lock.json │ ├── package.json │ └── routes │ │ ├── __tests__ │ │ └── index.test.js │ │ ├── index.js │ │ └── users │ │ ├── [username].js │ │ └── __tests__ │ │ └── [username].test.js ├── lerna.json ├── netlify │ ├── .gitignore │ ├── index.html │ ├── netlify.toml │ ├── package-lock.json │ ├── package.json │ └── routes │ │ ├── __tests__ │ │ └── index.test.js │ │ └── index.js ├── nextjs │ ├── package-lock.json │ ├── package.json │ └── pages │ │ ├── api │ │ └── index.js │ │ └── index.jsx ├── package-lock.json ├── package.json ├── typescript │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── routes │ │ ├── __tests__ │ │ │ └── index.test.ts │ │ └── index.ts │ └── tsconfig.json └── vercel │ ├── .gitignore │ ├── light.config.js │ ├── now.json │ ├── package-lock.json │ ├── package.json │ └── routes │ ├── __tests__ │ └── index.test.js │ └── index.js ├── jest.config.js ├── lerna.json ├── netlify.toml ├── package-lock.json ├── package.json ├── packages ├── @lightjs │ ├── cli │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── commands │ │ │ │ ├── dev.ts │ │ │ │ └── start.ts │ │ │ ├── index.ts │ │ │ ├── middleware │ │ │ │ └── youch.ts │ │ │ └── types │ │ │ │ └── external │ │ │ │ ├── emojic.d.ts │ │ │ │ └── youch.d.ts │ │ └── tsconfig.json │ ├── config │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── createConfig │ │ │ │ └── index.ts │ │ │ ├── createLoggerConfig │ │ │ │ └── index.ts │ │ │ ├── createMiddlewareConfig │ │ │ │ └── index.ts │ │ │ ├── importConfig │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── isTypescript │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ │ └── importFile.ts │ │ └── tsconfig.json │ ├── core │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ └── index.test.ts │ │ │ ├── createRoute │ │ │ │ ├── __tests__ │ │ │ │ │ └── serverless.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── isServerless.ts │ │ │ ├── index.ts │ │ │ ├── types │ │ │ │ └── aws-server-micro.d.ts │ │ │ └── withConnect │ │ │ │ ├── __tests__ │ │ │ │ ├── cors.test.ts │ │ │ │ └── helmet.test.ts │ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── logger │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── useFrameworkLogger │ │ │ │ └── index.ts │ │ │ └── useLogger │ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── router │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── createRouter │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── utils │ │ │ │ ├── __tests__ │ │ │ │ └── convert-file-name-to-path.test.ts │ │ │ │ ├── convertFileNameToPath.ts │ │ │ │ ├── findRouteFiles.ts │ │ │ │ ├── importRouteFiles.ts │ │ │ │ └── injectRouteIntoRouter.ts │ │ └── tsconfig.json │ ├── server │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── createServer │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── test │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── createRouteTest │ │ │ │ └── index.ts │ │ │ ├── createTest │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── types │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ │ ├── config.ts │ │ │ ├── context.ts │ │ │ ├── createRoute.ts │ │ │ ├── createRouter.ts │ │ │ ├── createServer.ts │ │ │ ├── createTest.ts │ │ │ ├── http.ts │ │ │ ├── index.ts │ │ │ ├── logger.ts │ │ │ └── routeHandler.ts │ │ └── tsconfig.json │ └── utils │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── src │ │ ├── applyMiddleware.ts │ │ ├── convertHandlerFunctionToRequestHandler.ts │ │ └── index.ts │ │ └── tsconfig.json └── light │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── cli │ │ └── index.ts │ └── index.ts │ └── tsconfig.json ├── renovate.json ├── scripts └── update.mjs ├── tsconfig.build.json ├── tsconfig.json └── website ├── .cspell.json ├── .gitignore ├── README.md ├── babel.config.js ├── blog ├── 2019-05-28-hola.md ├── 2019-05-29-hello-world.md └── 2019-05-30-welcome.md ├── dictionary.txt ├── docs ├── api │ ├── context │ │ ├── buffer.md │ │ ├── create-error.md │ │ ├── json.md │ │ ├── req.md │ │ ├── res.md │ │ ├── send-error.md │ │ ├── send.md │ │ ├── text.md │ │ ├── use-params.md │ │ └── use-query.md │ └── exported │ │ ├── create-route.md │ │ ├── create-server.md │ │ ├── create-test.md │ │ └── logger.md ├── core │ ├── body-parsing.mdx │ ├── connect.mdx │ ├── context.md │ ├── error-handling.mdx │ ├── hot-module-reloading.md │ ├── logging.mdx │ ├── middleware.mdx │ ├── params.mdx │ ├── query.mdx │ ├── routes.mdx │ ├── routing.md │ └── testing.md ├── deploy │ ├── aws-lambda.md │ ├── azure-functions.md │ ├── google-cloud-functions.md │ ├── heroku.md │ ├── netlify.md │ ├── runkit.mdx │ ├── server.md │ └── vercel.md ├── introduction │ ├── getting-started.mdx │ └── server-vs-serverless.md └── third-party │ ├── apollo.md │ ├── ava.md │ └── jest.md ├── docusaurus.config.js ├── package-lock.json ├── package.json ├── plugins └── postcss-tailwindcss-loader │ ├── index.js │ └── package.json ├── sidebars.js ├── src ├── css │ └── custom.css ├── pages │ └── index.js └── routes │ └── index │ ├── CTA.tsx │ ├── Features.tsx │ ├── Hero.tsx │ ├── Runkit.tsx │ ├── Stats.tsx │ └── UseAnywhere.tsx ├── static ├── .nojekyll └── img │ ├── favicon.png │ ├── hmr │ └── connection-refused.png │ ├── light.svg │ └── netlify │ ├── env.png │ └── trigger-deploy.png ├── tailwind.config.js └── tsconfig.json /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | coverage 4 | website 5 | benchmark 6 | examples 7 | build 8 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint', 'import'], 5 | extends: ['airbnb-base', 'airbnb-typescript/base', 'prettier', 'plugin:jest/recommended'], 6 | parserOptions: { 7 | project: './tsconfig.json', 8 | }, 9 | rules: { 10 | 'import/prefer-default-export': 'off', 11 | 'jest/expect-expect': [ 12 | 'error', 13 | { 14 | assertFunctionNames: ['expect', 'supertest.**.expect'], 15 | }, 16 | ], 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: main 2 | 3 | on: [push] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | strategy: 9 | matrix: 10 | node-version: [12.x, 14.x, 16.x] 11 | steps: 12 | - uses: actions/checkout@v2 13 | - name: Use Node.js ${{ matrix.node-version }} 14 | uses: actions/setup-node@v2 15 | with: 16 | node-version: ${{ matrix.node-version }} 17 | - run: npm ci 18 | - run: npx lerna bootstrap 19 | - run: npx lerna link --force-local 20 | - run: npx lerna run build 21 | - run: npm run ci 22 | env: 23 | CI: true 24 | - uses: codecov/codecov-action@v1 25 | with: 26 | token: ${{ secrets.CODECOV_TOKEN }} 27 | 28 | prettier: 29 | runs-on: ubuntu-latest 30 | steps: 31 | - uses: actions/checkout@v2 32 | - uses: actions/setup-node@v2 33 | with: 34 | node-version: lts/* 35 | - run: npm ci 36 | - run: npx prettier --check . 37 | 38 | spellcheck-docs: 39 | env: 40 | CI: true 41 | runs-on: ubuntu-latest 42 | defaults: 43 | run: 44 | working-directory: ./website 45 | steps: 46 | - uses: actions/checkout@v2 47 | - uses: actions/setup-node@v2 48 | with: 49 | node-version: lts/* 50 | - run: npm ci 51 | - run: npm run spellcheck 52 | 53 | examples: 54 | env: 55 | CI: true 56 | runs-on: ubuntu-latest 57 | steps: 58 | - uses: actions/checkout@v2 59 | - uses: actions/setup-node@v2 60 | with: 61 | node-version: lts/* 62 | - run: npm ci 63 | - run: npx lerna bootstrap 64 | - run: npm ci 65 | working-directory: ./examples 66 | - run: npx lerna bootstrap 67 | working-directory: ./examples 68 | - run: npm test 69 | working-directory: ./examples 70 | -------------------------------------------------------------------------------- /.github/workflows/pr.yml: -------------------------------------------------------------------------------- 1 | name: pr 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | benchmark: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v2 10 | - uses: actions/setup-node@v2 11 | with: 12 | node-version: lts/* 13 | - run: npm ci 14 | - run: npx lerna bootstrap 15 | - run: npx lerna run compile 16 | - run: npm ci 17 | working-directory: ./benchmark 18 | - run: npm link ../packages/light 19 | working-directory: ./benchmark 20 | - run: npm test 21 | working-directory: ./benchmark 22 | env: 23 | CI: true 24 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | temp 2 | 3 | # Output 4 | lib/ 5 | 6 | # macOS 7 | .DS_Store 8 | 9 | # Logs 10 | logs 11 | *.log 12 | npm-debug.log* 13 | yarn-debug.log* 14 | yarn-error.log* 15 | lerna-debug.log* 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 19 | 20 | # Runtime data 21 | pids 22 | *.pid 23 | *.seed 24 | *.pid.lock 25 | 26 | # Directory for instrumented libs generated by jscoverage/JSCover 27 | lib-cov 28 | 29 | # Coverage directory used by tools like istanbul 30 | coverage 31 | 32 | # nyc test coverage 33 | .nyc_output 34 | 35 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 36 | .grunt 37 | 38 | # Bower dependency directory (https://bower.io/) 39 | bower_components 40 | 41 | # node-waf configuration 42 | .lock-wscript 43 | 44 | # Compiled binary addons (https://nodejs.org/api/addons.html) 45 | build/Release 46 | 47 | # Dependency directories 48 | node_modules/ 49 | jspm_packages/ 50 | 51 | # TypeScript v1 declaration files 52 | typings/ 53 | 54 | # Optional npm cache directory 55 | .npm 56 | 57 | # Optional eslint cache 58 | .eslintcache 59 | 60 | # Optional REPL history 61 | .node_repl_history 62 | 63 | # Output of 'npm pack' 64 | *.tgz 65 | 66 | # Yarn Integrity file 67 | .yarn-integrity 68 | 69 | # dotenv environment variables file 70 | .env 71 | .env.test 72 | 73 | # parcel-bundler cache (https://parceljs.org/) 74 | .cache 75 | 76 | # next.js build output 77 | .next 78 | 79 | # nuxt.js build output 80 | .nuxt 81 | 82 | # vuepress build output 83 | .vuepress/dist 84 | 85 | # Serverless directories 86 | .serverless/ 87 | 88 | # FuseBox cache 89 | .fusebox/ 90 | 91 | # DynamoDB Local files 92 | .dynamodb/ 93 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | lib 3 | coverage 4 | website 5 | benchmark 6 | examples 7 | build 8 | package-lock.json 9 | lerna.json 10 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2020 ludicrous LLC 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # light 2 | 3 | [![ludicrous](https://img.shields.io/badge/-made%20by%20ludicrous-000000?style=for-the-badge&logoWidth=25&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQwAAADvCAYAAAAHK+oLAAAACXBIWXMAAAWJAAAFiQFtaJ36AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAABCESURBVHgB7d3tmRTHEcDxOj3+LuwA7OUCsAQBWMsFICMFYK0UgAAFIFYEIDgHwB0KAFACupW/W6AEYEnA4AQ87rrpPYZ7nd2dl66q/+95hkMYMDC7tdVV0107gvCqqvo0ffk0/+ek8T+9TdebdC13dnZeCsLbEYSTAsQ0ffksXfpVA8W1lr90ka5f0/WcAAI4loLEtXTdSddR1Y1X6fpKAPiS3tj30/W26geBA/AgvZGn6XpdDUMDx0QA2FPVWcXQ/qf/vwLAhqquVTyrxvVU/xwCd+iSOJLfpEfyvkU6phfp2kvdlHcCNwgYThQWLFYIGs58JPDiQMoKFupGuh4LgHJU4xQ426IQ6ghLEuOqupX5WspWSb00WQhMI2AYlwKGBouJlO91Chi7AtOoYRiWgsUdsREs1PX0550LTCPDMCovRbQrMhE7dPfrLl0Tu8gw7JqLrWChtPU7E5hFhmGQkULnRY5ShrEnMIkMw6YDsUs3xE0FJhEwjElvtpnUB99YpVntVGASAcMeDw9B/U1gEgHDkPzE5ETsK+0RdrRE0dOIXOjUzVweto3rk583ORfUHjIMO+biI1iskGUYRMAwIGcXnJuJ0REwbDgSX3QpPBGYQ8AoXG6jTgQoAAGjYFV9ihZnSaAYBIyyWdqNug7tkrABzSACRqFyoXMuflndCxMaAaNcc/HtjcAcHtwqUN6c5a0z0lTt7OzwYWUQN61MlnejtrEQmETAKEyQNuq/BCaxJCmI0WP31sU+EsPIMMoyF//ZxZJgYRcBoxBB9otodvGDwCwCRjnm4p9mF08EZhEwCpALnWQXKB5FzwIYml62DSafOUCGMTJj08s2RXbhBBnGiIK0UdVByi6+EZhHwBhRChiHEqN2oeMRlwLzWJKMJNCxe/sECz8IGON5Jv5pMXdf4AYBYwS5jer91OzjQifZhS/UMEZAGxVWkWEMzNH0sstodvGlwB0yjAHlQmeEo+loozpFhjGsufin2cUDgUsEjIGk7EKLnBHaqA8odPrFkmQgFDrhARnGAIIcu8d+kQDIMHoWaL8I2UUAZBj907rFRHzT7GJP4B4ZRo9oo8IbMox+zcW/t0IbNQwCRk9SdnFbYrRR/0kbNQ6WJD2hjQqPyDB6QBsVXpFhdCxQG/VZyi7YYBYMAaNjHLsHz1iSdCjQsXuHBIuYCBjdeij+aTGXNmpQBIyO5ELnbfGNY/eCo4bREdqoiIAMowOBjt37ThAaAWNLudA5E/+00PlcEBpLki0FaaOq69QuQIaxhUBtVAqdOEbA2E6E6WXLdB0KIASMjQWZXqbmZBdYoYaxoSBt1GUKFtcFyMgwNhCkjaq+EKCBDGNNgY7d0zbq1wI0kGGsby4xcNYFziBgrCHQ9DLaqDgXS5I1UOhEdGQYLQU5dk/NBbgAGUYLgY7de5myixsCXIAMo50I08sUbVRcigzjCrRRgffIMK42F/+WQhsVLRAwLpELnRHaqE9oo6INliSXoI0KfIgM4wK0UYGzyDDOEaiN+jxlF3RG0BoB4xwcuwecjyXJKUwvAy5GwDgrwvSypdBGxQYIGA1Bppcpjt3DRqhhNNBGBS5HhpEFOnbvngAbIsOQk0Lni3RdE9/YL4KtEDCENirQ1h8kOKaX+ZLup37RTFGPU/wkXVqv+Vg+XG6+S9cbqXch/y71OSDvBFcKn2FEKXSm64bXN0UjSGjg1y7Xp7L+8nKRLh02/TNZGM6lbdQqBpcZVPp7HWeI6XqUrrdVd47SNRWcETbDSC8I/QTSQudEfHPXRq3qjOKPUj9k12cw1P1E35BxvBe5rXpHYrRRb4kjOVjovXsl/dee9N/uVVW33CFBM4yKY/fMaWQVP6ZrJsPT18te9GwjasA4FNqoZuRgocuqp1IXNMeiQePL9G/6UoIKtyTJxSzaqEY0gsUvMm6wOPlzVPUEvJDCZRgV+0XMOBUsJlKOt1IvT8JlGqEyjIpj96zRDzRdhkykLFpLeZprYaGECRj55kaodi/SJ98TMS5nF3q/Sk3/VzWVUCJlGFHaqOa7IjlYaEuz9AB/I/1Z5xJIiBoGbVRb0v3S16U+ZzGR8ml0243Sbo2SYczFv6U4OHYvZxczsZMNanB7LEG4DxhVnOll+04+5fQN+L3YMo2y98T9koQ2qh05u9AllcVP7NfpHuyKc64zjPQCjFLonIsP+gH2rdh0PUIB1G2GUcWZXual0KlfNEt6JXbpA127ng/j8ZxhzCVGdmG+0NlgfcSDPtBlrf6yFpcBo4pz7J6XQqfSbPdzse+u5wKo1wzjQPxbpuuR+OJhU5fFLk9r7gJGbqNOxT8308uq92dyehnz4LbN6q7oSRvVnsaj4L+IH/o6vOmtAOoqw6jiTC9zcYrWKd6GSGlAvyvOuAkYudDp7gadQ9uoC/HH49S5b/Nh0254yjDm4n/UofLURvVudQapGy4CRqA2aojpZc7MPBVAvWQYR+LfUvy1UZu8Ph3pqs1qPmBEOnbP+fxPz+djTr1MnzPdVmV6mQ+NmSP/Eb9c7DOxnmEwvcyB9CbSL/pG8pxlaEA038UzGzByoXMu/h0GKnT+Kr59a/2kccsZxlz800/dKG1UXZc8F980yzjISzCTTAaM9A+u26DZjerP7+K3W7LymRje62Sy6Ml+EZ/yaeEPpa5NeaaF+pu5dmOKqQxDUzmml7kWYVmidBv/XYtLE1MhLtCxe0fp02dPAspZhu5anYpvJtusZjKMHI3nEiO7+Ebi0hv9nfinBdD71rIMMxkG08viCFTLMDc1zUTAyFH4UPx3RpbpuhV9g1njyU89Qdz7DuSF1PdcLLCyJJkJbdQw8ptH1/gRnkEx1WYtPqzlT5sIbdQQk7PWYWwo8zb09b1rIcsoOsPIwSLKsXscjHOWvgAi1HP0eZu5hQJo0SGN6WWgzVqWYjOMYG1UsouL6QshQpvZRJu15CWJpmkUOoPL63pd40cIqtpGnkrBilyS5Cirz9t7mIR1GX0j7BEwLkebtRylZhgz8R8sFIf6thCwzXq71KVJcWGMNiouEqgAWuzUtKIyjGCFzi8F69IXSIQs43hqWolZRlEZBvtFcJWcZTxN123xTZdgN0tbshaTYTSyiwhoo25utZvV+8lcRbZZS1qS3BCml+EKjTbrvvin74epFKSIJQmFTqyj0Wb9Tfy/ZhZSUJt19Awj3/yZ8EQnWgrYZv2qlKXJ6GEr0H6RF+mFflPQGfaZDG/UDCNYdkEbtXtR2qzHU9NKyDJGzTBoo2JbOcs4EP8F8yLarKMFDI7dQxfYZzKsMZckUaaXPSFY9KdRAI3QZh39OL9RQhVtVHQpWJt11Klpg2cYtFHRtUaWEaFONOrUtMHDVKA26rP0QqYzMiDarP0bNMMIths1wvSu0jA1rWdDL0miHLt3SKFzeHlp8lJiFED1OL/BD5kabEmSo+Ez8b8tmWP3RkSbtV9DZhgz8R8sFLtRRxRxatqQS5NBQhNtVAwt2NS0wY7z6z3DCDa9jEJnOSJNTRuszdp7hsH0MoyFNmv3es0wmF6Gka2mpnGcX0f6XpJEaaNS6CxQsOP8Bpma1tuShOllKAFt1m71mWHMhOllGBnH+XWrl1BEGxWlYWpaNzrPMJhehkIxNa0DnWcYHLuHUjE1bXudZhhML0PhIk1Ne9hHltH1koTpZShWsDbr36WHek1nSxIKnbCAqWnb6STD4Ng9WNFos94T/7TN2mkBtJPQw/QyWMM+k81snWHk6KWPpU7EP9qofjA1bQNbZxi0UWFVzjIeSv2B55lGi90uCvVbBQyml8Ey9pmsb9slyUyYXgajmJq2vo3DDW1UeBHsOL/dbbKMjTIM2qhwJspxfhPZsgC6Uajh2D14Q5u1nbUzDI7dg1Or4/y82+o4v02WJEwvgzt5Xb8UpqZdaq0lSY5KuhSZim8cuxcQbdarrZthzMR/sFDsRg0o4HF+t9ZdmrQOL7RRfTn1Qun8ICXj9N/j3+L/TNplum6sUwD9Q5ufxPQyP/K91DeEptz6hvhE6k+b1ZtjIohiInWbdd52adLqZ+U2qo4M8L6uc9lGbWQTer+n6fpe6gDh/X7iamu1Wa8MGIH2i6jr3moXjULenXwRJHDaYbq+bpNltAkY2kZ9Jf5poXMuTjSWHrN0/SgEClxMXyzaFVxc9RMvDRiRCp3S4yyHoeX7poH+scToamF7C2nRZr2wrRptv4izYKGHMUd4zBndaTU17cJwkn6hprBa6JyIb27aqI0gfyDA+q7MtM/NMPIL767EyC72xAGCBTpw5dS0czMMjt2zJd/gL6Se6gVs49KpaWcyjEDTyzTt8vII8KrACWxLW/AHF2UZ5y1JbkmMZy72PTxzkW+sFjhpm6IrFx7n98GShP0itjSywfsCdGsh57RZT2cYM+FgHEsmQrBAP86dmnYSPgJlF0cpaprvjAR7ZB/jOLPPpJlhzCRGduHlGLaJECzQr+Opac0fOM4wAmUXntqoh0LAQP80y/jTqpaxChhTqY/e82wpTqaX5adw3wrQvw82pq2WJDPxz0UbNbstwDA0qTh5ve0EWY64OnYv3bNDYTmC4ZwsSzTD0JOXJuKbm0Ndc4D/TIDh6BJ4ot/5SGIUOp+IHyc3DxjQVL9ZZRieuckuMu/3C+XROsZEv+M9w/BU6FyZCDC8P+s3GjD+Ij5pIfeR+DMRYHj6ENdGs1WtYHoZ0J2P9RuvAeO1s0InUAQNGC4Ovz3Fy36R83i8XzBCA8Z/xZfDNvMVDCNgYAxL/eaj1Xcc8dZGPY2AgTG80W+8BYwIhc6FAMPSx4tf6nc0YCzEB69t1A/kw0yWAgyrzjDyJ7KHNNfN9LIWfhVgOMv03jrJMJT1FmS0NupCgOEsVt9ZBYznYpuL6WVr0PtF8RND0PrFT6v/OA4YuQ1p9QV4GO2Jzrz04sE0DGHZfEyh+aTnvtjjaXrZuqxnhSifZhfz5g80xwzoOQuvJG8yMUILnXMJKt0znXh2S4B+nDmp7iTDyGnuA7HjdeRgkX0nQD/OZBfqg81n6Q2ozzFYOT086lLkRG51uX/2BKPQD+SfTv/gzukfSGnuJH35TcpemjxKf5l7gtVSUu/XdQG6oYf+3jyvmXBme3v+SSUvTfSJzvDZxUpeSmpbmTkl6IIuRS7cYnHueRh5aVLim1KDxV6gJzpbyTdXt/RXAmxuFSwu7JheeIBOLiiWFDRWwWIpOCP9u2iblaCBTa2CxaXv+R256nepqnn6cl/GRbBoKd2vWfryWFrcWyBrFSxUqxdVDhrfyzgvwhfp+pJg0V66XzqK4KlQCMXVNFjcu2wZ0tQ6AOTuiT4oNNSLUP8i+3RDNpPvl2aGOlKRbAOn6ftrKfWH8cu2v6j1IcD6CZ+f+vpB+l0n6++tz4LsESw2l+/X11LXNXRJR20DSl8H2lHT9/HNdYKF2uiT59Sn18a/z+nfVupttA+cn8k5ilzb0GXlRMg4ItL3l3YXdemxv2mncasXTg4c03T9I39d5/dcfeKtdl7+TKDoXw4cn6frdv4hgodfq/fYQurNij9t+0hCZy+WHDy02KaTxT+R90ODrzV+2lLqAKFp0O96ESTGk+7ZVOpA/1ep75Ve1wRWvZP37683+evPPLcEYBT/Bz15Uq1zu/kmAAAAAElFTkSuQmCC)](https://www.ludicroushq.com) 4 | [![Github Actions](https://img.shields.io/github/workflow/status/ludicroushq/light/main?label=ci%20status&style=for-the-badge&labelColor=0a0a0a)](https://circleci.com/gh/ludicroushq/light) 5 | [![npm](https://img.shields.io/npm/v/light.svg?label=npm%20version&style=for-the-badge&labelColor=0a0a0a)](https://www.npmjs.com/package/light) 6 | [![Downloads](https://img.shields.io/npm/dm/light.svg?label=downloads&style=for-the-badge&labelColor=0a0a0a)](https://www.npmjs.com/package/light) 7 | [![Stars](https://img.shields.io/github/stars/ludicroushq/light.svg?style=for-the-badge&labelColor=0a0a0a)](https://github.com/ludicroushq/light) 8 | [![Coveralls GitHub](https://img.shields.io/codecov/c/github/ludicroushq/light?label=code%20coverage&style=for-the-badge&labelColor=0a0a0a)](https://codecov.io/gh/ludicroushq/light) 9 | 10 | **NOTICE: Since light is a work in progress, breaking changes will be made every MINOR patch until 2.0** 11 | 12 | light is a **light**ning fast web framework. 13 | -------------------------------------------------------------------------------- /benchmark/dangerfile.js: -------------------------------------------------------------------------------- 1 | const { message, warn } = require('danger'); 2 | const listen = require('test-listen'); 3 | const fetch = require('node-fetch'); 4 | const http = require('http'); 5 | const { createServer } = require('light'); 6 | 7 | const benchmark = async (url) => { 8 | for (let i = 0; i < 10000; i++) { 9 | const req = await fetch(url); 10 | const res = await req.json(); 11 | if (res.hello !== 'world') { 12 | throw new Error('server did not respond properly'); 13 | } 14 | } 15 | }; 16 | 17 | const benchmarkExpress = async () => { 18 | const express = require('./express'); 19 | const server = http.createServer(express); 20 | const url = await listen(server); 21 | 22 | const start = Date.now(); 23 | await benchmark(url); 24 | const end = Date.now(); 25 | 26 | server.close(); 27 | return end - start; 28 | }; 29 | 30 | const benchmarkKoa = async () => { 31 | const koa = require('./koa'); 32 | const server = http.createServer(koa.callback()); 33 | const url = await listen(server); 34 | 35 | const start = Date.now(); 36 | await benchmark(url); 37 | const end = Date.now(); 38 | 39 | server.close(); 40 | return end - start; 41 | }; 42 | 43 | const benchmarkFastify = async () => { 44 | const fastify = require('./fastify'); 45 | await fastify.ready(); 46 | const server = fastify.server; 47 | const url = await listen(server); 48 | 49 | const start = Date.now(); 50 | await benchmark(url); 51 | const end = Date.now(); 52 | 53 | server.close(); 54 | return end - start; 55 | }; 56 | 57 | const benchmarkLight = async () => { 58 | const server = createServer({ youch: false, requestLogger: false }); 59 | const url = await listen(server.server); 60 | 61 | const start = Date.now(); 62 | await benchmark(url); 63 | const end = Date.now(); 64 | 65 | server.server.close(); 66 | return end - start; 67 | }; 68 | 69 | const run = async () => { 70 | console.log('Starting benchmarks'); 71 | console.log('Benchmarking Express'); 72 | const express = await benchmarkExpress(); 73 | console.log('Benchmarking Koa'); 74 | const koa = await benchmarkKoa(); 75 | console.log('Benchmarking Fastify'); 76 | const fastify = await benchmarkFastify(); 77 | console.log('Benchmarking light'); 78 | const light = await benchmarkLight(); 79 | 80 | const getRPS = (ms) => { 81 | return Math.round(10000 / (ms / 1000)); 82 | }; 83 | 84 | const text = ` 85 | ## Benchmark Results 86 | 87 | Makes 10,000 requests to each framework and times the result. 88 | 89 | | Framework | Total Time | Req/Sec | 90 | |-----------|------------|---------| 91 | | Express |${express}ms|${getRPS(express)}| 92 | | Koa |${koa}ms|${getRPS(koa)}| 93 | | Fastify |${fastify}ms|${getRPS(fastify)}| 94 | | **Light** |**${light}ms**|**${getRPS(light)}**| 95 | `; 96 | 97 | if (Math.min(express, koa, fastify, light) === light) { 98 | message(text); 99 | } else { 100 | warn(text); 101 | } 102 | }; 103 | 104 | run(); 105 | -------------------------------------------------------------------------------- /benchmark/express.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const app = express(); 4 | 5 | app.get('/', function (req, res) { 6 | res.status(200).json({ hello: 'world' }); 7 | }); 8 | 9 | module.exports = app; 10 | -------------------------------------------------------------------------------- /benchmark/fastify.js: -------------------------------------------------------------------------------- 1 | const fastify = require('fastify')(); 2 | 3 | fastify.get('/', async (request, reply) => { 4 | reply.type('application/json').code(200); 5 | return { hello: 'world' }; 6 | }); 7 | 8 | module.exports = fastify; 9 | -------------------------------------------------------------------------------- /benchmark/koa.js: -------------------------------------------------------------------------------- 1 | const Koa = require('koa'); 2 | const Router = require('@koa/router'); 3 | 4 | const app = new Koa(); 5 | const router = new Router(); 6 | 7 | router.get('/', (ctx, next) => { 8 | ctx.body = { 9 | hello: 'world', 10 | }; 11 | next(); 12 | }); 13 | 14 | app.use(router.routes()).use(router.allowedMethods()); 15 | 16 | module.exports = app; 17 | -------------------------------------------------------------------------------- /benchmark/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benchmark", 3 | "version": "0.0.0", 4 | "description": "light benchmark", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "danger ci" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ludicroushq/light.git" 12 | }, 13 | "keywords": [ 14 | "light", 15 | "benchmark" 16 | ], 17 | "author": "Manthan Mallikarjun", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/ludicroushq/light/issues" 21 | }, 22 | "homepage": "https://github.com/ludicroushq/light#readme", 23 | "dependencies": { 24 | "@koa/router": "^10.1.1", 25 | "danger": "^11.0.2", 26 | "express": "^4.17.3", 27 | "fastify": "^3.28.0", 28 | "koa": "^2.13.4", 29 | "light": "file://../packages/light", 30 | "node-fetch": "^2.6.6", 31 | "test-listen": "^1.1.0" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /benchmark/routes/index.js: -------------------------------------------------------------------------------- 1 | const { createRoute } = require('light'); 2 | 3 | module.exports = createRoute(() => { 4 | return { 5 | async GET() { 6 | return { hello: 'world' }; 7 | } 8 | } 9 | }); 10 | -------------------------------------------------------------------------------- /examples/basic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "basic", 3 | "scripts": { 4 | "dev": "light dev", 5 | "start": "light start", 6 | "test": "jest" 7 | }, 8 | "dependencies": { 9 | "light": "^2.0.0-alpha.21" 10 | }, 11 | "devDependencies": { 12 | "jest": "^27.4.3", 13 | "supertest": "^6.1.6" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/basic/routes/__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const { createTest } = require('light'); 2 | const request = require('supertest'); 3 | 4 | const { server } = createTest(); 5 | 6 | it('works', async () => { 7 | const response = await request(server).get('/'); 8 | expect(response.status).toBe(200); 9 | expect(response.body).toMatchObject({ 10 | hello: 'world', 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/basic/routes/index.js: -------------------------------------------------------------------------------- 1 | const { createRoute } = require('light'); 2 | 3 | module.exports = createRoute(() => { 4 | return { 5 | async GET() { 6 | return { 7 | hello: 'world', 8 | }; 9 | } 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /examples/basic/routes/users/[username].js: -------------------------------------------------------------------------------- 1 | const { createRoute } = require('light'); 2 | 3 | module.exports = createRoute(() => { 4 | return { 5 | async GET({ req }) { 6 | return { 7 | hello: req.params.username, 8 | }; 9 | } 10 | } 11 | }); 12 | -------------------------------------------------------------------------------- /examples/basic/routes/users/__tests__/[username].test.js: -------------------------------------------------------------------------------- 1 | // const { createTest } = require('light'); 2 | // const request = require('supertest'); 3 | 4 | // const { server } = createTest(); 5 | 6 | it('works', async () => { 7 | // const response = await request(server).get('/users/test'); 8 | // expect(response.status).toBe(200); 9 | // expect(response.body).toMatchObject({ 10 | // hello: 'test', 11 | // }); 12 | expect(true).toBe(true); 13 | }); 14 | -------------------------------------------------------------------------------- /examples/lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": ["basic", "netlify", "nextjs", "typescript", "vercel"], 3 | "version": "0.0.0" 4 | } 5 | -------------------------------------------------------------------------------- /examples/netlify/.gitignore: -------------------------------------------------------------------------------- 1 | # Local Netlify folder 2 | .netlify 3 | -------------------------------------------------------------------------------- /examples/netlify/index.html: -------------------------------------------------------------------------------- 1 | 2 | Hello! Please visit /.netlify/functions/index 3 | 4 | -------------------------------------------------------------------------------- /examples/netlify/netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | command = "npm install" 3 | functions = "routes" 4 | -------------------------------------------------------------------------------- /examples/netlify/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "netlify", 3 | "scripts": { 4 | "dev": "light dev", 5 | "start": "light start", 6 | "test": "jest" 7 | }, 8 | "dependencies": { 9 | "light": "^2.0.0-alpha.21" 10 | }, 11 | "devDependencies": { 12 | "jest": "^27.4.3", 13 | "supertest": "^6.1.6" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /examples/netlify/routes/__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const { createTest } = require('light'); 2 | const request = require('supertest'); 3 | 4 | const { server } = createTest(); 5 | 6 | it('works', async () => { 7 | const response = await request(server).get('/'); 8 | expect(response.status).toBe(200); 9 | expect(response.body).toMatchObject({ 10 | hello: 'netlify!', 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/netlify/routes/index.js: -------------------------------------------------------------------------------- 1 | // IMPORTANT NOTE: You will need to set LIGHT_ENV=netlify in the Netlify Environment Variables settings 2 | const { createRoute } = require('light'); 3 | 4 | module.exports = createRoute(() => { 5 | return { 6 | async GET() { 7 | return { 8 | hello: 'netlify!', 9 | } 10 | } 11 | } 12 | }) 13 | -------------------------------------------------------------------------------- /examples/nextjs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nextjs", 3 | "scripts": { 4 | "dev": "next dev", 5 | "test": "" 6 | }, 7 | "dependencies": { 8 | "light": "^2.0.0-alpha.21", 9 | "next": "^12.0.4", 10 | "react": "^17.0.2", 11 | "react-dom": "^17.0.2" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /examples/nextjs/pages/api/index.js: -------------------------------------------------------------------------------- 1 | const { createRoute } = require('light'); 2 | 3 | const { route, GET } = createRoute('index'); 4 | 5 | GET(() => 'hello world!'); 6 | 7 | export default route; 8 | -------------------------------------------------------------------------------- /examples/nextjs/pages/index.jsx: -------------------------------------------------------------------------------- 1 | export default function Index() { 2 | return
visit /api
; 3 | } 4 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "examples", 3 | "version": "0.0.0", 4 | "description": "lightjs examples", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "lerna exec --parallel -- npm test" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/ludicroushq/light.git" 12 | }, 13 | "keywords": [ 14 | "lightjs", 15 | "examples" 16 | ], 17 | "author": "Manthan Mallikarjun", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/ludicroushq/light/issues" 21 | }, 22 | "homepage": "https://github.com/ludicroushq/light#readme", 23 | "devDependencies": { 24 | "lerna": "^4.0.0" 25 | }, 26 | "dependencies": { 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/typescript/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | }; 5 | -------------------------------------------------------------------------------- /examples/typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "typescript-example", 3 | "scripts": { 4 | "dev": "light dev -t", 5 | "start": "light start -t", 6 | "test": "jest" 7 | }, 8 | "dependencies": { 9 | "light": "^2.0.0-alpha.21" 10 | }, 11 | "devDependencies": { 12 | "@types/jest": "^27.0.3", 13 | "jest": "^27.4.3", 14 | "supertest": "^6.1.6", 15 | "ts-jest": "^27.0.7", 16 | "ts-node": "^10.4.0", 17 | "typescript": "^4.5.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/typescript/routes/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | const { createTest } = require('light'); 2 | const request = require('supertest'); 3 | 4 | const { server } = createTest(); 5 | 6 | it('works', async () => { 7 | const response = await request(server).get('/'); 8 | expect(response.status).toBe(200); 9 | expect(response.body).toMatchObject({ 10 | hello: 'world', 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/typescript/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { createRoute } from 'light'; 2 | 3 | export default createRoute(({ useMiddleware }) => { 4 | useMiddleware((fn) => async (ctx) => { 5 | console.log('before'); 6 | const result = await fn(ctx); 7 | console.log('after'); 8 | return result; 9 | }); 10 | 11 | return { 12 | async GET({ req }) { 13 | console.log(`receiving request at path: ${req.url}`); 14 | return { 15 | hello: 'world', 16 | }; 17 | } 18 | } 19 | }) 20 | -------------------------------------------------------------------------------- /examples/typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "noImplicitAny": true 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /examples/vercel/.gitignore: -------------------------------------------------------------------------------- 1 | .vercel -------------------------------------------------------------------------------- /examples/vercel/light.config.js: -------------------------------------------------------------------------------- 1 | const { createConfig } = require('light'); 2 | const winston = require('winston'); 3 | 4 | const logger = winston.createLogger({ 5 | level: 'info', 6 | format: winston.format.json(), 7 | transports: [ 8 | new winston.transports.Console({ 9 | format: winston.format.simple(), 10 | }), 11 | ], 12 | }); 13 | 14 | function createLogger() { 15 | return logger 16 | } 17 | 18 | 19 | module.exports = createConfig({ 20 | logger: { 21 | createLogger, 22 | createFrameworkLogger: createLogger, 23 | } 24 | }) 25 | -------------------------------------------------------------------------------- /examples/vercel/now.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "public": true, 4 | "builds": [ 5 | { 6 | "src": "routes/**/*.js", 7 | "use": "@now/node", 8 | "config": { 9 | "includeFiles": ["light.config.js"] 10 | } 11 | } 12 | ], 13 | "routes": [ 14 | { 15 | "src": "/", 16 | "dest": "routes/index.js" 17 | }, 18 | { 19 | "src": "/(.*)", 20 | "dest": "routes/$1.js" 21 | } 22 | ], 23 | "env": { 24 | "NODE_ENV": "production", 25 | "LIGHT_ENV": "now" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples/vercel/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vercel", 3 | "scripts": { 4 | "dev": "light dev", 5 | "start": "light start", 6 | "test": "jest" 7 | }, 8 | "dependencies": { 9 | "light": "^2.0.0-alpha.21", 10 | "winston": "^3.4.0" 11 | }, 12 | "devDependencies": { 13 | "jest": "^27.4.3", 14 | "supertest": "^6.1.6" 15 | }, 16 | "pkg": { 17 | "scripts": "light.config.js" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /examples/vercel/routes/__tests__/index.test.js: -------------------------------------------------------------------------------- 1 | const supertest = require('supertest'); 2 | const { createTest } = require('light'); 3 | 4 | const { server } = createTest(); 5 | 6 | it('works', async () => { 7 | const response = await supertest(server).get('/'); 8 | expect(response.status).toBe(200); 9 | expect(response.body).toMatchObject({ 10 | hello: 'vercel with light!', 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /examples/vercel/routes/index.js: -------------------------------------------------------------------------------- 1 | const { createRoute, useLogger } = require('light'); 2 | 3 | const logger = useLogger() 4 | 5 | module.exports = createRoute(() => { 6 | return { 7 | async GET() { 8 | logger.info('hello logs!'); 9 | 10 | return { 11 | hello: 'vercel with light!', 12 | }; 13 | } 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest', 4 | testEnvironment: 'node', 5 | testMatch: ['**/__tests__/**/*.test.ts'], 6 | collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}'], 7 | rootDir: 'packages', 8 | }; 9 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/light", 4 | "packages/@lightjs/*" 5 | ], 6 | "version": "2.0.0-alpha.26", 7 | "command": { 8 | "version": { 9 | "ignoreChanges": [ 10 | "*.md" 11 | ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | base = "website" 3 | command = "npm run build" 4 | publish = "website/build" 5 | ignore = "git diff --quiet HEAD^ HEAD website/" 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "core", 3 | "private": true, 4 | "scripts": { 5 | "ci": "npm run ci:type-check && npm run ci:jest && npm run ci:lint", 6 | "ci:type-check": "lerna exec --parallel -- npx tsc --noEmit", 7 | "ci:lint": "eslint .", 8 | "ci:jest": "jest --verbose --maxWorkers=4 --coverage" 9 | }, 10 | "devDependencies": { 11 | "@types/jest": "^27.4.1", 12 | "@types/node": "^17.0.23", 13 | "@typescript-eslint/eslint-plugin": "^5.18.0", 14 | "@typescript-eslint/parser": "^5.18.0", 15 | "eslint": "^8.13.0", 16 | "eslint-config-airbnb-base": "^15.0.0", 17 | "eslint-config-airbnb-typescript": "^17.0.0", 18 | "eslint-config-prettier": "^8.5.0", 19 | "eslint-plugin-import": "^2.26.0", 20 | "eslint-plugin-jest": "^26.1.4", 21 | "jest": "^27.5.1", 22 | "lerna": "^4.0.0", 23 | "prettier": "^2.6.2", 24 | "ts-jest": "^27.1.4", 25 | "typescript": "^4.6.3" 26 | }, 27 | "license": "MIT" 28 | } 29 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/cli 2 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/cli", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs cli", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "cli" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/node": "^16.11.11", 33 | "@types/yargs": "^17.0.7", 34 | "typescript": "^4.5.2" 35 | }, 36 | "dependencies": { 37 | "@lightjs/config": "^2.0.0-alpha.26", 38 | "@lightjs/logger": "^2.0.0-alpha.26", 39 | "@lightjs/server": "^2.0.0-alpha.26", 40 | "@lightjs/types": "^2.0.0-alpha.24", 41 | "chalk": "^4.1.2", 42 | "chokidar": "^3.5.2", 43 | "decache": "^4.6.1", 44 | "emojic": "^1.1.16", 45 | "ts-node": "^10.4.0", 46 | "yargs": "^17.3.0", 47 | "youch": "^2.2.2", 48 | "youch-terminal": "^1.1.1" 49 | }, 50 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 51 | } 52 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/commands/dev.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { CommandBuilder } from 'yargs'; // eslint-disable-line 3 | import { relative } from 'path'; 4 | import emojic from 'emojic'; 5 | import chalk from 'chalk'; 6 | import decache from 'decache'; 7 | import { isTypescript, importMiddlewareConfig } from '@lightjs/config'; 8 | import { createServer } from '@lightjs/server'; 9 | import { ImportedRoute } from '@lightjs/types'; 10 | import { useFrameworkLogger } from '@lightjs/logger'; 11 | 12 | export const command = 'dev'; 13 | export const desc = 'start a development server'; 14 | 15 | export const builder: CommandBuilder = { 16 | port: { 17 | alias: 'p', 18 | description: 'specify which port the server should run on', 19 | }, 20 | }; 21 | 22 | interface Args { 23 | port?: string; 24 | } 25 | 26 | const handle = async (argv: Args): Promise => { 27 | const ts = isTypescript(); 28 | if (ts) { 29 | require('ts-node').register(); // eslint-disable-line 30 | } 31 | 32 | const logger = useFrameworkLogger(); 33 | const middlewareConfig = importMiddlewareConfig(); 34 | const globalMiddleware = middlewareConfig?.().global || []; 35 | 36 | ((logger as unknown as any)?.info || console.info)( 37 | `[ ${chalk.redBright('start')} ] ${emojic.fire} igniting the server ${emojic.fire}`, 38 | ); 39 | 40 | /** 41 | * NOTE: We import youchMiddleware like this because it contains the use of the logger. 42 | * Using the logger requires the import of the light config which may be in typescript. 43 | * Since we initialize ts-node above, we need to make sure the youch import is after. 44 | */ 45 | // eslint-disable-next-line global-require 46 | const { youchMiddleware } = require('../middleware/youch'); 47 | 48 | const cwd = process.cwd(); 49 | const app = createServer({ 50 | middleware: [youchMiddleware, ...globalMiddleware], 51 | }); 52 | 53 | const { HOST = '0.0.0.0' } = process.env; 54 | 55 | let { PORT = 3000 } = process.env; 56 | if (argv.port) { 57 | PORT = argv.port; 58 | } 59 | 60 | app.server.listen(PORT, HOST as any, (): void => { 61 | logger.info(`[ ${chalk.magentaBright('listening')} ] on port ${PORT}`); 62 | 63 | logger.info(`[ ${chalk.blueBright('hmr')} ] starting the hot reloader`); 64 | const chokidar = require('chokidar'); // eslint-disable-line 65 | const watcher = chokidar.watch(cwd, { 66 | ignored: ['**/node_modules/**/*', '**/node_modules/**/.*', '**/.git/**/*'], 67 | }); 68 | 69 | let { importedRoutes } = app; 70 | 71 | watcher.on('ready', (): void => { 72 | logger.info(`[ ${chalk.blueBright('hmr')} ] watching for changes`); 73 | }); 74 | 75 | watcher.on('change', async (p: string): Promise => { 76 | logger.info(`[ ${chalk.blueBright('hmr')} ] swapping out ${chalk.yellow(relative(cwd, p))}`); 77 | // remove edited file from cache 78 | decache(p); 79 | 80 | // decache all routes 81 | importedRoutes.forEach((x: ImportedRoute) => { 82 | decache(x.file); 83 | }); 84 | 85 | process.removeAllListeners(); 86 | 87 | // reload the server 88 | importedRoutes = app.reload(); 89 | }); 90 | }); 91 | }; 92 | 93 | export const handler = (argv: Args): void => { 94 | handle(argv).catch((err: Error): void => { 95 | console.error(err); 96 | process.exit(1); 97 | }); 98 | }; 99 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/commands/start.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { CommandBuilder } from 'yargs'; // eslint-disable-line 3 | import emojic from 'emojic'; 4 | import chalk from 'chalk'; 5 | import { importMiddlewareConfig, isTypescript } from '@lightjs/config'; 6 | import { createServer } from '@lightjs/server'; 7 | import { useFrameworkLogger } from '@lightjs/logger'; 8 | 9 | export const command = 'start'; 10 | export const desc = 'start a production server'; 11 | 12 | export const builder: CommandBuilder = { 13 | port: { 14 | alias: 'p', 15 | description: 'specify which port the server should run on', 16 | }, 17 | }; 18 | 19 | interface Args { 20 | port?: string; 21 | } 22 | 23 | const handle = async (argv: Args): Promise => { 24 | const ts = isTypescript(); 25 | if (ts) { 26 | require('ts-node').register(); // eslint-disable-line 27 | } 28 | 29 | const logger = useFrameworkLogger(); 30 | const middlewareConfig = importMiddlewareConfig(); 31 | const globalMiddleware = middlewareConfig?.().global || []; 32 | 33 | logger.info(`[ ${chalk.redBright('start')} ] ${emojic.fire} igniting the server ${emojic.fire}`); 34 | 35 | const app = createServer({ 36 | middleware: globalMiddleware, 37 | }); 38 | 39 | const { HOST = '0.0.0.0' } = process.env; 40 | 41 | let { PORT = 3000 } = process.env; 42 | if (argv.port) { 43 | PORT = argv.port; 44 | } 45 | 46 | app.server.listen(PORT, HOST as any, (): void => { 47 | logger.info(`[ ${chalk.magentaBright('listening')} ] on port ${PORT}`); 48 | }); 49 | }; 50 | 51 | export const handler = (argv: Args): void => { 52 | handle(argv).catch((err: Error): void => { 53 | console.error(err); 54 | process.exit(1); 55 | }); 56 | }; 57 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import yargs from 'yargs'; 4 | 5 | async function run() { 6 | let { argv } = yargs.commandDir('commands').demandCommand().recommendCommands().strict().help(); 7 | 8 | if (argv instanceof Promise) { 9 | argv = await argv; 10 | } 11 | 12 | if (!argv._[0]) { 13 | yargs.showHelp(); 14 | } 15 | } 16 | 17 | run(); 18 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/middleware/youch.ts: -------------------------------------------------------------------------------- 1 | import { useFrameworkLogger } from '@lightjs/logger'; 2 | import { Context } from '@lightjs/types'; 3 | import Youch from 'youch'; 4 | import forTerminal from 'youch-terminal'; 5 | 6 | const logger = useFrameworkLogger(); 7 | 8 | export function youchMiddleware(fun: any) { 9 | return async function youchHandler(ctx: Context) { 10 | try { 11 | // eslint-disable-next-line @typescript-eslint/return-await 12 | return await fun(ctx); 13 | } catch (err) { 14 | const youch = new Youch(err, ctx.req); 15 | const json = await youch.toJSON(); 16 | logger.info(forTerminal(json)); // eslint-disable-line 17 | return youch.toHTML(); 18 | } 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/types/external/emojic.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'emojic'; 2 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/src/types/external/youch.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'youch'; 2 | declare module 'youch-terminal'; 3 | -------------------------------------------------------------------------------- /packages/@lightjs/cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/config/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/config 2 | -------------------------------------------------------------------------------- /packages/@lightjs/config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/config", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs config", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "config" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/jest": "^27.0.3", 33 | "@types/node": "^16.11.11", 34 | "jest": "^27.4.3", 35 | "ts-jest": "^27.0.7", 36 | "typescript": "^4.5.2" 37 | }, 38 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c", 39 | "dependencies": { 40 | "@lightjs/types": "^2.0.0-alpha.24" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/createConfig/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateConfig } from '@lightjs/types'; 2 | 3 | export function createConfig(config: CreateConfig) { 4 | return config; 5 | } 6 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/createLoggerConfig/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateLoggerConfig } from '@lightjs/types'; 2 | 3 | export function createLoggerConfig(logger: CreateLoggerConfig): CreateLoggerConfig { 4 | return logger; 5 | } 6 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/createMiddlewareConfig/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateMiddlewareConfig } from '@lightjs/types'; 2 | 3 | export function createMiddlewareConfig(logger: CreateMiddlewareConfig): CreateMiddlewareConfig { 4 | return logger; 5 | } 6 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/importConfig/index.ts: -------------------------------------------------------------------------------- 1 | import { CreateConfig, CreateLoggerConfig, CreateMiddlewareConfig } from '@lightjs/types'; 2 | import { join } from 'path'; 3 | import { importTSorJSFile } from '../utils/importFile'; 4 | 5 | export function importLightConfig(): CreateConfig | null { 6 | const cwd = process.cwd(); 7 | const path = join(cwd, 'light.config'); 8 | return importTSorJSFile(path); 9 | } 10 | 11 | /** 12 | * Imports a file from either the root or src directory. 13 | */ 14 | export function importProjectFile(relativePathWithoutExtension: string) { 15 | const cwd = process.cwd(); 16 | const rootDir = join(cwd); 17 | const srcDir = join(cwd, 'src'); 18 | 19 | return ( 20 | importTSorJSFile(join(rootDir, relativePathWithoutExtension)) || 21 | importTSorJSFile(join(srcDir, relativePathWithoutExtension)) || 22 | null 23 | ); 24 | } 25 | 26 | export function importLoggerConfig(): CreateLoggerConfig | null { 27 | return importProjectFile('config/_logger'); 28 | } 29 | 30 | export function importMiddlewareConfig(): CreateMiddlewareConfig | null { 31 | return importProjectFile('config/_middleware'); 32 | } 33 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/index.ts: -------------------------------------------------------------------------------- 1 | export { importLightConfig, importLoggerConfig, importMiddlewareConfig } from './importConfig'; 2 | export { createConfig } from './createConfig'; 3 | export { createLoggerConfig } from './createLoggerConfig'; 4 | export { createMiddlewareConfig } from './createMiddlewareConfig'; 5 | export { isTypescript } from './isTypescript'; 6 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/isTypescript/index.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs'; 2 | import { join } from 'path'; 3 | 4 | export function isTypescript() { 5 | const tsConfig = join(process.cwd(), 'tsconfig.json'); 6 | return existsSync(tsConfig); 7 | } 8 | -------------------------------------------------------------------------------- /packages/@lightjs/config/src/utils/importFile.ts: -------------------------------------------------------------------------------- 1 | import { existsSync } from 'fs'; 2 | 3 | function importFile(fileName: string) { 4 | if (existsSync(fileName)) { 5 | let conf = require(fileName); // eslint-disable-line 6 | if (!conf) return null; 7 | if (conf.default) conf = conf.default; 8 | return conf; 9 | } 10 | return null; 11 | } 12 | 13 | export function importTSorJSFile(fileName: string) { 14 | return importFile(`${fileName}.ts`) || importFile(`${fileName}.js`); 15 | } 16 | -------------------------------------------------------------------------------- /packages/@lightjs/config/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/core/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/core 2 | -------------------------------------------------------------------------------- /packages/@lightjs/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/core", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs core", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "light" 23 | ], 24 | "author": "Manthan Mallikarjun", 25 | "license": "MIT", 26 | "bugs": { 27 | "url": "https://github.com/ludicroushq/light/issues" 28 | }, 29 | "homepage": "https://github.com/ludicroushq/light#readme", 30 | "dependencies": { 31 | "@lightjs/types": "^2.0.0-alpha.24", 32 | "@lightjs/utils": "^2.0.0-alpha.24", 33 | "@types/connect": "^3.4.35", 34 | "aws-serverless-micro": "^1.0.4", 35 | "find-my-way": "^5.0.0", 36 | "micro": "^9.3.4" 37 | }, 38 | "devDependencies": { 39 | "@lightjs/test": "^2.0.0-alpha.26", 40 | "@netlify/functions": "^0.10.0", 41 | "@types/cors": "^2.8.12", 42 | "@types/micro": "^7.3.6", 43 | "@types/supertest": "^2.0.11", 44 | "cookie-session": "^2.0.0", 45 | "cors": "^2.8.5", 46 | "helmet": "^4.6.0", 47 | "supertest": "^6.1.6", 48 | "typescript": "^4.5.2" 49 | }, 50 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 51 | } 52 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/__tests__/index.test.ts: -------------------------------------------------------------------------------- 1 | import { createRoute, withConnect } from '../index'; 2 | 3 | it('exports route', () => { 4 | expect(createRoute).toBeTruthy(); 5 | }); 6 | 7 | it('exports withConnect', () => { 8 | expect(withConnect).toBeTruthy(); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/createRoute/__tests__/serverless.test.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable global-require */ 2 | describe('runkit', () => { 3 | it('returns the correct handler', () => { 4 | process.env.LIGHT_ENV = 'runkit'; 5 | jest.resetModules(); 6 | const { createRoute } = require('../index'); 7 | const route = createRoute(() => ({ 8 | async GET() { 9 | return 'ok'; 10 | }, 11 | })); 12 | expect(route.endpoint).toBeTruthy(); 13 | process.env.LIGHT_ENV = undefined; 14 | }); 15 | }); 16 | 17 | describe('with netlify', () => { 18 | it('returns the correct handler', () => { 19 | process.env.LIGHT_ENV = 'netlify'; 20 | jest.resetModules(); 21 | const { createRoute } = require('../index'); 22 | const route = createRoute(() => ({ 23 | async GET() { 24 | return 'ok'; 25 | }, 26 | })); 27 | expect(route.handler).toBeTruthy(); 28 | process.env.LIGHT_ENV = undefined; 29 | }); 30 | }); 31 | 32 | describe('with aws', () => { 33 | it('returns the correct handler', () => { 34 | process.env.LIGHT_ENV = 'aws'; 35 | jest.resetModules(); 36 | const { createRoute } = require('../index'); 37 | const route = createRoute(() => ({ 38 | async GET() { 39 | return 'ok'; 40 | }, 41 | })); 42 | expect(route.handler).toBeTruthy(); 43 | process.env.LIGHT_ENV = undefined; 44 | }); 45 | }); 46 | 47 | describe('with now', () => { 48 | it('returns the correct handler', () => { 49 | process.env.LIGHT_ENV = 'now'; 50 | jest.resetModules(); 51 | const { createRoute } = require('../index'); 52 | const route = createRoute(() => ({ 53 | async GET() { 54 | return 'ok'; 55 | }, 56 | })); 57 | expect(typeof route).toBe('function'); 58 | process.env.LIGHT_ENV = undefined; 59 | }); 60 | }); 61 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/createRoute/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-underscore-dangle */ 2 | /* eslint-disable @typescript-eslint/naming-convention */ 3 | import { 4 | Methods, 5 | HTTPMethod, 6 | Component, 7 | Middleware, 8 | RouteHandler, 9 | InternalRoute, 10 | Context, 11 | } from '@lightjs/types'; 12 | import { applyMiddleware, convertHandlerFunctionToRequestHandler } from '@lightjs/utils'; 13 | import { IncomingMessage, ServerResponse } from 'http'; 14 | import AWSServerlessMicro from 'aws-serverless-micro'; 15 | import { createError, run } from 'micro'; 16 | import { 17 | isAWS, 18 | isNetlify, 19 | isNextJS, 20 | isNow, 21 | isRunKit, 22 | isServerless, 23 | isVercel, 24 | } from './isServerless'; 25 | 26 | function parseHTTPMethod(method?: string): HTTPMethod { 27 | if (!method) return 'GET'; 28 | 29 | if (!Methods.includes(method as HTTPMethod)) { 30 | throw new Error(`Invalid HTTP method: ${method}`); 31 | } 32 | 33 | return method as HTTPMethod; 34 | } 35 | 36 | export function createRoute(component: Component) { 37 | const _middleware: Partial> & { _global: Middleware[] } = { 38 | _global: [], 39 | }; 40 | 41 | function useMiddleware(mw: Middleware | Middleware[], methods?: HTTPMethod[]) { 42 | const middleware = Array.isArray(mw) ? mw : [mw]; 43 | 44 | if (!methods) { 45 | _middleware._global.push(...middleware); 46 | return; 47 | } 48 | 49 | methods.forEach((method) => { 50 | if (!_middleware[method]) { 51 | _middleware[method] = []; 52 | } 53 | // TODO: Is there any way to remove the optional chaining below? 54 | _middleware[method]?.push(...middleware); 55 | }); 56 | } 57 | 58 | const _route: InternalRoute = component({ useMiddleware }); 59 | 60 | /** 61 | * Take the handler function (with context param) and convert it to a request handler 62 | */ 63 | function defaultRouteHandler(ctx: Context) { 64 | const { req } = ctx; 65 | const method = parseHTTPMethod(req.method); 66 | const routeMethod = _route[method]; 67 | if (!routeMethod) { 68 | throw createError(405, 'Method Not Allowed'); 69 | } 70 | const mw = [..._middleware._global, ...(_middleware[method] || [])]; 71 | const appliedHandler = applyMiddleware(mw, routeMethod); 72 | return appliedHandler(ctx); 73 | } 74 | 75 | /** 76 | * Export the correct request handler based on the environment 77 | * 78 | * Serverfull = request handler (with options) 79 | * Vercel/Next/Now = request handler 80 | * Netlify/AWS = AWS handler 81 | * Runkit = custom request handler 82 | */ 83 | let routeHandler: RouteHandler = defaultRouteHandler; 84 | 85 | if (isServerless) { 86 | const requestHandler = convertHandlerFunctionToRequestHandler(defaultRouteHandler); 87 | 88 | const safeGuardedRoute = (req: IncomingMessage, res: ServerResponse) => 89 | run(req, res, requestHandler); 90 | if (isNow || isVercel || isNextJS) { 91 | routeHandler = safeGuardedRoute; 92 | } 93 | if (isNetlify || isAWS) { 94 | routeHandler = { 95 | handler: AWSServerlessMicro(safeGuardedRoute), 96 | }; 97 | } 98 | if (isRunKit) { 99 | routeHandler = { 100 | endpoint: safeGuardedRoute, 101 | }; 102 | } 103 | } 104 | 105 | return routeHandler; 106 | } 107 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/createRoute/isServerless.ts: -------------------------------------------------------------------------------- 1 | const { LIGHT_ENV } = process.env; 2 | export const isNetlify = LIGHT_ENV?.toLowerCase() === 'netlify'; 3 | export const isAWS = LIGHT_ENV?.toLowerCase() === 'aws'; 4 | export const isRunKit = LIGHT_ENV?.toLowerCase() === 'runkit'; 5 | export const isNow = LIGHT_ENV?.toLowerCase() === 'now'; 6 | export const isVercel = LIGHT_ENV?.toLowerCase() === 'vercel'; 7 | export const isNextJS = LIGHT_ENV?.toLowerCase() === 'nextjs'; 8 | export const isServerless = isNetlify || isAWS || isRunKit || isNow || isVercel || isNextJS; 9 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createRoute } from './createRoute'; 2 | export { withConnect } from './withConnect'; 3 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/types/aws-server-micro.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'aws-serverless-micro' { 2 | export default function ( 3 | fn: import('micro').RequestHandler, 4 | ): import('@netlify/functions').Handler; 5 | } 6 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/withConnect/__tests__/cors.test.ts: -------------------------------------------------------------------------------- 1 | import cors from 'cors'; 2 | import supertest from 'supertest'; 3 | import { createRouteTest } from '@lightjs/test'; 4 | import { withConnect } from '..'; 5 | import { createRoute } from '../../createRoute'; 6 | 7 | describe('withConnect', () => { 8 | it('cors', async () => { 9 | const route = createRoute(({ useMiddleware }) => { 10 | useMiddleware(withConnect(cors())); 11 | return { 12 | async GET() { 13 | return 'OK'; 14 | }, 15 | }; 16 | }); 17 | const server = createRouteTest(route); 18 | const response = await supertest(server).get('/').expect(200); 19 | expect(response.status).toBe(200); 20 | expect(response.headers).toHaveProperty('access-control-allow-origin', '*'); 21 | }); 22 | 23 | it('cors configured', async () => { 24 | const route = createRoute(({ useMiddleware }) => { 25 | useMiddleware(withConnect(cors({ origin: 'http://localhost:3000' }))); 26 | return { 27 | async GET() { 28 | return 'OK'; 29 | }, 30 | }; 31 | }); 32 | const server = createRouteTest(route); 33 | const response = await supertest(server).get('/').expect(200); 34 | expect(response.status).toBe(200); 35 | expect(response.headers).toHaveProperty('access-control-allow-origin', 'http://localhost:3000'); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/withConnect/__tests__/helmet.test.ts: -------------------------------------------------------------------------------- 1 | import helmet from 'helmet'; 2 | import supertest from 'supertest'; 3 | import { createRouteTest } from '@lightjs/test'; 4 | import { withConnect } from '..'; 5 | import { createRoute } from '../../createRoute'; 6 | 7 | describe('withConnect', () => { 8 | it('helmet', async () => { 9 | const route = createRoute(({ useMiddleware }) => { 10 | useMiddleware(withConnect(helmet())); 11 | return { 12 | async GET() { 13 | return 'OK'; 14 | }, 15 | }; 16 | }); 17 | const server = createRouteTest(route); 18 | const response = await supertest(server).get('/').expect(200); 19 | expect(response.status).toBe(200); 20 | expect(response.headers).toHaveProperty('content-security-policy'); 21 | expect(response.headers).toHaveProperty('x-dns-prefetch-control', 'off'); 22 | expect(response.headers).toHaveProperty('expect-ct', 'max-age=0'); 23 | expect(response.headers).toHaveProperty('x-frame-options', 'SAMEORIGIN'); 24 | expect(response.headers).toHaveProperty( 25 | 'strict-transport-security', 26 | 'max-age=15552000; includeSubDomains', 27 | ); 28 | expect(response.headers).toHaveProperty('x-download-options', 'noopen'); 29 | expect(response.headers).toHaveProperty('x-content-type-options', 'nosniff'); 30 | expect(response.headers).toHaveProperty('x-permitted-cross-domain-policies', 'none'); 31 | expect(response.headers).toHaveProperty('referrer-policy', 'no-referrer'); 32 | expect(response.headers).toHaveProperty('x-xss-protection', '0'); 33 | }); 34 | 35 | it('helmet configured', async () => { 36 | const route = createRoute(({ useMiddleware }) => { 37 | useMiddleware(withConnect(helmet({ referrerPolicy: { policy: 'origin' } }))); 38 | return { 39 | async GET() { 40 | return 'OK'; 41 | }, 42 | }; 43 | }); 44 | const server = createRouteTest(route); 45 | const response = await supertest(server).get('/').expect(200); 46 | expect(response.status).toBe(200); 47 | // Changed 48 | expect(response.headers).toHaveProperty('referrer-policy', 'origin'); 49 | // Same as above 50 | expect(response.headers).toHaveProperty('content-security-policy'); 51 | expect(response.headers).toHaveProperty('x-dns-prefetch-control', 'off'); 52 | expect(response.headers).toHaveProperty('expect-ct', 'max-age=0'); 53 | expect(response.headers).toHaveProperty('x-frame-options', 'SAMEORIGIN'); 54 | expect(response.headers).toHaveProperty( 55 | 'strict-transport-security', 56 | 'max-age=15552000; includeSubDomains', 57 | ); 58 | expect(response.headers).toHaveProperty('x-download-options', 'noopen'); 59 | expect(response.headers).toHaveProperty('x-content-type-options', 'nosniff'); 60 | expect(response.headers).toHaveProperty('x-permitted-cross-domain-policies', 'none'); 61 | expect(response.headers).toHaveProperty('x-xss-protection', '0'); 62 | }); 63 | }); 64 | -------------------------------------------------------------------------------- /packages/@lightjs/core/src/withConnect/index.ts: -------------------------------------------------------------------------------- 1 | import { Context } from '@lightjs/types'; 2 | import type { NextHandleFunction } from 'connect'; 3 | 4 | export const withConnect = (connect: NextHandleFunction) => (fn: any) => async (ctx: Context) => { 5 | await new Promise((resolve, reject) => { 6 | connect(ctx.req, ctx.res, (result: any) => { 7 | if (result instanceof Error) { 8 | return reject(result); 9 | } 10 | 11 | return resolve(result); 12 | }); 13 | }); 14 | return fn(ctx); 15 | }; 16 | -------------------------------------------------------------------------------- /packages/@lightjs/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/logger 2 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/logger", 3 | "version": "2.0.0-alpha.26", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@lightjs/logger", 9 | "version": "2.0.0-alpha.26", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "@types/node": "^16.11.11", 13 | "typescript": "^4.5.2" 14 | } 15 | }, 16 | "node_modules/@types/node": { 17 | "version": "16.11.26", 18 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 19 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 20 | "dev": true 21 | }, 22 | "node_modules/typescript": { 23 | "version": "4.6.3", 24 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 25 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 26 | "dev": true, 27 | "bin": { 28 | "tsc": "bin/tsc", 29 | "tsserver": "bin/tsserver" 30 | }, 31 | "engines": { 32 | "node": ">=4.2.0" 33 | } 34 | } 35 | }, 36 | "dependencies": { 37 | "@types/node": { 38 | "version": "16.11.26", 39 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 40 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 41 | "dev": true 42 | }, 43 | "typescript": { 44 | "version": "4.6.3", 45 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 46 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 47 | "dev": true 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/logger", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs logger", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "logger" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/node": "^16.11.11", 33 | "typescript": "^4.5.2" 34 | }, 35 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c", 36 | "dependencies": { 37 | "@lightjs/config": "^2.0.0-alpha.26", 38 | "@lightjs/types": "^2.0.0-alpha.24" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/src/index.ts: -------------------------------------------------------------------------------- 1 | export { useLogger } from './useLogger'; 2 | export { useFrameworkLogger } from './useFrameworkLogger'; 3 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/src/useFrameworkLogger/index.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-console */ 2 | import { useLogger } from '../useLogger'; 3 | 4 | type FrameworkLogger = { 5 | info: (message: string) => void; 6 | }; 7 | export function useFrameworkLogger(): FrameworkLogger { 8 | const logger = useLogger(); 9 | 10 | return { 11 | info: (message: string) => { 12 | const info = (logger as unknown as any)?.info || console.info; 13 | info(message); 14 | }, 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/src/useLogger/index.ts: -------------------------------------------------------------------------------- 1 | import { Logger } from '@lightjs/types'; 2 | import { importLoggerConfig } from '@lightjs/config'; 3 | 4 | export function useLogger(): Logger { 5 | const config = importLoggerConfig(); 6 | 7 | if (!config) { 8 | return console; 9 | } 10 | 11 | return config(); 12 | } 13 | -------------------------------------------------------------------------------- /packages/@lightjs/logger/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/router/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/router 2 | -------------------------------------------------------------------------------- /packages/@lightjs/router/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/router", 3 | "version": "2.0.0-alpha.26", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@lightjs/router", 9 | "version": "2.0.0-alpha.26", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-my-way": "^5.0.0", 13 | "glob": "^7.2.0", 14 | "micro": "^9.3.4" 15 | }, 16 | "devDependencies": { 17 | "@types/glob": "^7.2.0", 18 | "@types/micro": "^7.3.6", 19 | "typescript": "^4.5.2" 20 | } 21 | }, 22 | "node_modules/@types/glob": { 23 | "version": "7.2.0", 24 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", 25 | "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", 26 | "dev": true, 27 | "dependencies": { 28 | "@types/minimatch": "*", 29 | "@types/node": "*" 30 | } 31 | }, 32 | "node_modules/@types/micro": { 33 | "version": "7.3.7", 34 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 35 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 36 | "dev": true, 37 | "dependencies": { 38 | "@types/node": "*" 39 | } 40 | }, 41 | "node_modules/@types/minimatch": { 42 | "version": "3.0.5", 43 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", 44 | "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", 45 | "dev": true 46 | }, 47 | "node_modules/@types/node": { 48 | "version": "17.0.23", 49 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 50 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", 51 | "dev": true 52 | }, 53 | "node_modules/arg": { 54 | "version": "4.1.0", 55 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 56 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 57 | }, 58 | "node_modules/balanced-match": { 59 | "version": "1.0.2", 60 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 61 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 62 | }, 63 | "node_modules/brace-expansion": { 64 | "version": "1.1.11", 65 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 66 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 67 | "dependencies": { 68 | "balanced-match": "^1.0.0", 69 | "concat-map": "0.0.1" 70 | } 71 | }, 72 | "node_modules/bytes": { 73 | "version": "3.0.0", 74 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 75 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", 76 | "engines": { 77 | "node": ">= 0.8" 78 | } 79 | }, 80 | "node_modules/concat-map": { 81 | "version": "0.0.1", 82 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 83 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 84 | }, 85 | "node_modules/content-type": { 86 | "version": "1.0.4", 87 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 88 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 89 | "engines": { 90 | "node": ">= 0.6" 91 | } 92 | }, 93 | "node_modules/depd": { 94 | "version": "1.1.1", 95 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 96 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", 97 | "engines": { 98 | "node": ">= 0.6" 99 | } 100 | }, 101 | "node_modules/fast-decode-uri-component": { 102 | "version": "1.0.1", 103 | "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", 104 | "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" 105 | }, 106 | "node_modules/fast-deep-equal": { 107 | "version": "3.1.3", 108 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 109 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 110 | }, 111 | "node_modules/find-my-way": { 112 | "version": "5.4.0", 113 | "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-5.4.0.tgz", 114 | "integrity": "sha512-XROi2CRlo9PkgYomucEB9K6jp3YZeTSM+x2uWJoW9YWTDGr91oCZN8VTuU0V0TVjeMgjIcwD+5tzxDb9iE9kpQ==", 115 | "dependencies": { 116 | "fast-decode-uri-component": "^1.0.1", 117 | "fast-deep-equal": "^3.1.3", 118 | "safe-regex2": "^2.0.0", 119 | "semver-store": "^0.3.0" 120 | }, 121 | "engines": { 122 | "node": ">=12" 123 | } 124 | }, 125 | "node_modules/fs.realpath": { 126 | "version": "1.0.0", 127 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 128 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 129 | }, 130 | "node_modules/glob": { 131 | "version": "7.2.0", 132 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 133 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 134 | "dependencies": { 135 | "fs.realpath": "^1.0.0", 136 | "inflight": "^1.0.4", 137 | "inherits": "2", 138 | "minimatch": "^3.0.4", 139 | "once": "^1.3.0", 140 | "path-is-absolute": "^1.0.0" 141 | }, 142 | "engines": { 143 | "node": "*" 144 | }, 145 | "funding": { 146 | "url": "https://github.com/sponsors/isaacs" 147 | } 148 | }, 149 | "node_modules/http-errors": { 150 | "version": "1.6.2", 151 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 152 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 153 | "dependencies": { 154 | "depd": "1.1.1", 155 | "inherits": "2.0.3", 156 | "setprototypeof": "1.0.3", 157 | "statuses": ">= 1.3.1 < 2" 158 | }, 159 | "engines": { 160 | "node": ">= 0.6" 161 | } 162 | }, 163 | "node_modules/http-errors/node_modules/inherits": { 164 | "version": "2.0.3", 165 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 166 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 167 | }, 168 | "node_modules/iconv-lite": { 169 | "version": "0.4.19", 170 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 171 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", 172 | "engines": { 173 | "node": ">=0.10.0" 174 | } 175 | }, 176 | "node_modules/inflight": { 177 | "version": "1.0.6", 178 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 179 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 180 | "dependencies": { 181 | "once": "^1.3.0", 182 | "wrappy": "1" 183 | } 184 | }, 185 | "node_modules/inherits": { 186 | "version": "2.0.4", 187 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 188 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 189 | }, 190 | "node_modules/is-stream": { 191 | "version": "1.1.0", 192 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 193 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 194 | "engines": { 195 | "node": ">=0.10.0" 196 | } 197 | }, 198 | "node_modules/micro": { 199 | "version": "9.3.4", 200 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 201 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 202 | "dependencies": { 203 | "arg": "4.1.0", 204 | "content-type": "1.0.4", 205 | "is-stream": "1.1.0", 206 | "raw-body": "2.3.2" 207 | }, 208 | "bin": { 209 | "micro": "bin/micro.js" 210 | }, 211 | "engines": { 212 | "node": ">= 8.0.0" 213 | } 214 | }, 215 | "node_modules/minimatch": { 216 | "version": "3.1.2", 217 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 218 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 219 | "dependencies": { 220 | "brace-expansion": "^1.1.7" 221 | }, 222 | "engines": { 223 | "node": "*" 224 | } 225 | }, 226 | "node_modules/once": { 227 | "version": "1.4.0", 228 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 229 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 230 | "dependencies": { 231 | "wrappy": "1" 232 | } 233 | }, 234 | "node_modules/path-is-absolute": { 235 | "version": "1.0.1", 236 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 237 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 238 | "engines": { 239 | "node": ">=0.10.0" 240 | } 241 | }, 242 | "node_modules/raw-body": { 243 | "version": "2.3.2", 244 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 245 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 246 | "dependencies": { 247 | "bytes": "3.0.0", 248 | "http-errors": "1.6.2", 249 | "iconv-lite": "0.4.19", 250 | "unpipe": "1.0.0" 251 | }, 252 | "engines": { 253 | "node": ">= 0.8" 254 | } 255 | }, 256 | "node_modules/ret": { 257 | "version": "0.2.2", 258 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", 259 | "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", 260 | "engines": { 261 | "node": ">=4" 262 | } 263 | }, 264 | "node_modules/safe-regex2": { 265 | "version": "2.0.0", 266 | "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", 267 | "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", 268 | "dependencies": { 269 | "ret": "~0.2.0" 270 | } 271 | }, 272 | "node_modules/semver-store": { 273 | "version": "0.3.0", 274 | "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", 275 | "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" 276 | }, 277 | "node_modules/setprototypeof": { 278 | "version": "1.0.3", 279 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 280 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 281 | }, 282 | "node_modules/statuses": { 283 | "version": "1.5.0", 284 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 285 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 286 | "engines": { 287 | "node": ">= 0.6" 288 | } 289 | }, 290 | "node_modules/typescript": { 291 | "version": "4.6.3", 292 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 293 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 294 | "dev": true, 295 | "bin": { 296 | "tsc": "bin/tsc", 297 | "tsserver": "bin/tsserver" 298 | }, 299 | "engines": { 300 | "node": ">=4.2.0" 301 | } 302 | }, 303 | "node_modules/unpipe": { 304 | "version": "1.0.0", 305 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 306 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 307 | "engines": { 308 | "node": ">= 0.8" 309 | } 310 | }, 311 | "node_modules/wrappy": { 312 | "version": "1.0.2", 313 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 314 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 315 | } 316 | }, 317 | "dependencies": { 318 | "@types/glob": { 319 | "version": "7.2.0", 320 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", 321 | "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", 322 | "dev": true, 323 | "requires": { 324 | "@types/minimatch": "*", 325 | "@types/node": "*" 326 | } 327 | }, 328 | "@types/micro": { 329 | "version": "7.3.7", 330 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 331 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 332 | "dev": true, 333 | "requires": { 334 | "@types/node": "*" 335 | } 336 | }, 337 | "@types/minimatch": { 338 | "version": "3.0.5", 339 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", 340 | "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==", 341 | "dev": true 342 | }, 343 | "@types/node": { 344 | "version": "17.0.23", 345 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 346 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", 347 | "dev": true 348 | }, 349 | "arg": { 350 | "version": "4.1.0", 351 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 352 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 353 | }, 354 | "balanced-match": { 355 | "version": "1.0.2", 356 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 357 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 358 | }, 359 | "brace-expansion": { 360 | "version": "1.1.11", 361 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 362 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 363 | "requires": { 364 | "balanced-match": "^1.0.0", 365 | "concat-map": "0.0.1" 366 | } 367 | }, 368 | "bytes": { 369 | "version": "3.0.0", 370 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 371 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 372 | }, 373 | "concat-map": { 374 | "version": "0.0.1", 375 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 376 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 377 | }, 378 | "content-type": { 379 | "version": "1.0.4", 380 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 381 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 382 | }, 383 | "depd": { 384 | "version": "1.1.1", 385 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 386 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 387 | }, 388 | "fast-decode-uri-component": { 389 | "version": "1.0.1", 390 | "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", 391 | "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" 392 | }, 393 | "fast-deep-equal": { 394 | "version": "3.1.3", 395 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 396 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 397 | }, 398 | "find-my-way": { 399 | "version": "5.4.0", 400 | "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-5.4.0.tgz", 401 | "integrity": "sha512-XROi2CRlo9PkgYomucEB9K6jp3YZeTSM+x2uWJoW9YWTDGr91oCZN8VTuU0V0TVjeMgjIcwD+5tzxDb9iE9kpQ==", 402 | "requires": { 403 | "fast-decode-uri-component": "^1.0.1", 404 | "fast-deep-equal": "^3.1.3", 405 | "safe-regex2": "^2.0.0", 406 | "semver-store": "^0.3.0" 407 | } 408 | }, 409 | "fs.realpath": { 410 | "version": "1.0.0", 411 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 412 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 413 | }, 414 | "glob": { 415 | "version": "7.2.0", 416 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 417 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 418 | "requires": { 419 | "fs.realpath": "^1.0.0", 420 | "inflight": "^1.0.4", 421 | "inherits": "2", 422 | "minimatch": "^3.0.4", 423 | "once": "^1.3.0", 424 | "path-is-absolute": "^1.0.0" 425 | } 426 | }, 427 | "http-errors": { 428 | "version": "1.6.2", 429 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 430 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 431 | "requires": { 432 | "depd": "1.1.1", 433 | "inherits": "2.0.3", 434 | "setprototypeof": "1.0.3", 435 | "statuses": ">= 1.3.1 < 2" 436 | }, 437 | "dependencies": { 438 | "inherits": { 439 | "version": "2.0.3", 440 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 441 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 442 | } 443 | } 444 | }, 445 | "iconv-lite": { 446 | "version": "0.4.19", 447 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 448 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 449 | }, 450 | "inflight": { 451 | "version": "1.0.6", 452 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 453 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 454 | "requires": { 455 | "once": "^1.3.0", 456 | "wrappy": "1" 457 | } 458 | }, 459 | "inherits": { 460 | "version": "2.0.4", 461 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 462 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 463 | }, 464 | "is-stream": { 465 | "version": "1.1.0", 466 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 467 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 468 | }, 469 | "micro": { 470 | "version": "9.3.4", 471 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 472 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 473 | "requires": { 474 | "arg": "4.1.0", 475 | "content-type": "1.0.4", 476 | "is-stream": "1.1.0", 477 | "raw-body": "2.3.2" 478 | } 479 | }, 480 | "minimatch": { 481 | "version": "3.1.2", 482 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 483 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 484 | "requires": { 485 | "brace-expansion": "^1.1.7" 486 | } 487 | }, 488 | "once": { 489 | "version": "1.4.0", 490 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 491 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 492 | "requires": { 493 | "wrappy": "1" 494 | } 495 | }, 496 | "path-is-absolute": { 497 | "version": "1.0.1", 498 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 499 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 500 | }, 501 | "raw-body": { 502 | "version": "2.3.2", 503 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 504 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 505 | "requires": { 506 | "bytes": "3.0.0", 507 | "http-errors": "1.6.2", 508 | "iconv-lite": "0.4.19", 509 | "unpipe": "1.0.0" 510 | } 511 | }, 512 | "ret": { 513 | "version": "0.2.2", 514 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", 515 | "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" 516 | }, 517 | "safe-regex2": { 518 | "version": "2.0.0", 519 | "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", 520 | "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", 521 | "requires": { 522 | "ret": "~0.2.0" 523 | } 524 | }, 525 | "semver-store": { 526 | "version": "0.3.0", 527 | "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", 528 | "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" 529 | }, 530 | "setprototypeof": { 531 | "version": "1.0.3", 532 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 533 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 534 | }, 535 | "statuses": { 536 | "version": "1.5.0", 537 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 538 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 539 | }, 540 | "typescript": { 541 | "version": "4.6.3", 542 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 543 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 544 | "dev": true 545 | }, 546 | "unpipe": { 547 | "version": "1.0.0", 548 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 549 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 550 | }, 551 | "wrappy": { 552 | "version": "1.0.2", 553 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 554 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 555 | } 556 | } 557 | } 558 | -------------------------------------------------------------------------------- /packages/@lightjs/router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/router", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs router", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "router" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/glob": "^7.2.0", 33 | "@types/micro": "^7.3.6", 34 | "typescript": "^4.5.2" 35 | }, 36 | "dependencies": { 37 | "@lightjs/config": "^2.0.0-alpha.26", 38 | "@lightjs/types": "^2.0.0-alpha.24", 39 | "@lightjs/utils": "^2.0.0-alpha.24", 40 | "find-my-way": "^5.0.0", 41 | "glob": "^7.2.0", 42 | "micro": "^9.3.4" 43 | }, 44 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 45 | } 46 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/createRouter/index.ts: -------------------------------------------------------------------------------- 1 | import Router from 'find-my-way'; 2 | import { CreateRouterOptions } from '@lightjs/types'; 3 | import { createError } from 'micro'; 4 | import { convertHandlerFunctionToRequestHandler, applyMiddleware } from '@lightjs/utils'; 5 | import { join } from 'path'; 6 | import { existsSync } from 'fs'; 7 | import { findRouteFiles } from '../utils/findRouteFiles'; 8 | import { importRouteFiles } from '../utils/importRouteFiles'; 9 | import { injectRouteIntoRouter } from '../utils/injectRouteIntoRouter'; 10 | 11 | function findRoutesFolder() { 12 | const cwd = process.cwd(); 13 | const rootDir = join(cwd, 'routes'); 14 | const srcDir = join(cwd, 'src', 'routes'); 15 | 16 | if (existsSync(rootDir)) return rootDir; 17 | if (existsSync(srcDir)) return srcDir; 18 | return rootDir; 19 | } 20 | 21 | export function createRouter({ middleware = [] }: CreateRouterOptions) { 22 | // create find-my-way router with default 404 handler 23 | const defaultRoute = convertHandlerFunctionToRequestHandler( 24 | applyMiddleware(middleware, () => { 25 | throw createError(404, 'Not Found'); 26 | }) as () => never, 27 | ) as () => never; 28 | 29 | const router = Router({ 30 | ignoreTrailingSlash: true, 31 | defaultRoute, 32 | }); 33 | 34 | const routesDirPath = findRoutesFolder(); 35 | 36 | const fillRouter = () => { 37 | const routeFiles = findRouteFiles(routesDirPath); 38 | const importedRoutes = importRouteFiles(routeFiles, routesDirPath); 39 | injectRouteIntoRouter(router, importedRoutes, { middleware }); 40 | return importedRoutes; 41 | }; 42 | const importedRoutes = fillRouter(); 43 | 44 | return { 45 | router, 46 | importedRoutes, 47 | reload: () => { 48 | // reset the router 49 | router.reset(); 50 | // reimport routes 51 | return fillRouter(); 52 | }, 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createRouter } from './createRouter'; 2 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/utils/__tests__/convert-file-name-to-path.test.ts: -------------------------------------------------------------------------------- 1 | import { convertFileNameToPath } from '../convertFileNameToPath'; 2 | 3 | describe('static routes', () => { 4 | it.each([ 5 | ['/index', '/'], 6 | ['/foo', '/foo'], 7 | ['/foo/bar', '/foo/bar'], 8 | ])('convertFileNameToPath(%s) returns "%s"', (fileName, expected) => { 9 | expect(convertFileNameToPath(fileName)).toEqual(expected); 10 | }); 11 | }); 12 | 13 | describe('parametric routes', () => { 14 | it.each([ 15 | ['/[foo]', '/:foo'], 16 | ['/[foo]/[bar]', '/:foo/:bar'], 17 | ['/[foo]/[bar]/[baz]', '/:foo/:bar/:baz'], 18 | ])('convertFileNameToPath(%s) returns "%s"', (fileName, expected) => { 19 | expect(convertFileNameToPath(fileName)).toEqual(expected); 20 | }); 21 | }); 22 | 23 | describe('wildcard routes', () => { 24 | it.each([ 25 | ['/[...foo]', '/*'], 26 | ['/[foo]/[...bar]', '/:foo/*'], // might be invalid, need to check 27 | ['/[foo]/[...bar]/[baz]', '/:foo/*/:baz'], // might be invalid, need to check 28 | ])('convertFileNameToPath(%s) returns "%s"', (fileName, expected) => { 29 | expect(convertFileNameToPath(fileName)).toEqual(expected); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/utils/convertFileNameToPath.ts: -------------------------------------------------------------------------------- 1 | export function convertFileNameToPath(fileName: string) { 2 | if (fileName.endsWith('/index')) { 3 | return fileName.substring(0, fileName.length - 6) || '/'; 4 | } 5 | 6 | const splitFileName = fileName.split('/'); 7 | 8 | return splitFileName 9 | .map((name) => { 10 | if (name.startsWith('[') && name.endsWith(']')) { 11 | const newName = name.split(''); 12 | newName.pop(); 13 | newName.shift(); 14 | 15 | const joinedName = newName.join(''); 16 | 17 | if (joinedName.startsWith('...')) { 18 | return '*'; 19 | } 20 | return `:${joinedName}`; 21 | } 22 | 23 | return name; 24 | }) 25 | .join('/'); 26 | } 27 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/utils/findRouteFiles.ts: -------------------------------------------------------------------------------- 1 | import { sync as globSync } from 'glob'; 2 | 3 | export function findRouteFiles(routesDirPath: string) { 4 | const routes = globSync('**/*.[jt]s', { 5 | cwd: routesDirPath, 6 | // TODO: allow configuration of ignore 7 | ignore: ['**/__tests__/**/*.[jt]s?(x)', '**/?*.+(spec|test).[tj]s?(x)'], 8 | }); 9 | 10 | return routes; 11 | } 12 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/utils/importRouteFiles.ts: -------------------------------------------------------------------------------- 1 | import { join, parse } from 'path'; 2 | import { ImportedRoute } from '@lightjs/types'; 3 | import { convertFileNameToPath } from './convertFileNameToPath'; 4 | 5 | export function importRouteFiles(routes: string[], routesDirPath: string) { 6 | const routeObjects: ImportedRoute[] = []; 7 | routes.forEach((route: string): void => { 8 | const routePath = join(routesDirPath, route); 9 | 10 | let handler = require(routePath); // eslint-disable-line 11 | if (handler.default) { 12 | handler = handler.default; 13 | } 14 | 15 | if (!handler) throw new Error(`${route} does not export a handler`); 16 | 17 | const parsedFile = parse(join('/', route)); 18 | const fileName = join(parsedFile.dir, parsedFile.name); 19 | 20 | const path = convertFileNameToPath(fileName); 21 | 22 | routeObjects.push({ 23 | path, 24 | route: handler, 25 | file: routePath, 26 | }); 27 | }); 28 | 29 | return routeObjects; 30 | } 31 | -------------------------------------------------------------------------------- /packages/@lightjs/router/src/utils/injectRouteIntoRouter.ts: -------------------------------------------------------------------------------- 1 | import Router from 'find-my-way'; 2 | import { ImportedRoute, Middleware } from '@lightjs/types'; 3 | import { applyMiddleware, convertHandlerFunctionToRequestHandler } from '@lightjs/utils'; 4 | 5 | type InjectRoutesOptions = { 6 | middleware?: Middleware[]; 7 | }; 8 | 9 | export function injectRouteIntoRouter( 10 | router: Router.Instance, 11 | routes: ImportedRoute[], 12 | opts: InjectRoutesOptions, 13 | ) { 14 | routes.forEach((routeObj): void => { 15 | const { route, path } = routeObj; 16 | 17 | const middleware = [...(opts.middleware || [])]; 18 | const appliedHandler = applyMiddleware(middleware, route); 19 | const requestHandler = convertHandlerFunctionToRequestHandler(appliedHandler); 20 | 21 | router.all(path, requestHandler); 22 | }); 23 | } 24 | -------------------------------------------------------------------------------- /packages/@lightjs/router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/server/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/server 2 | -------------------------------------------------------------------------------- /packages/@lightjs/server/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/server", 3 | "version": "2.0.0-alpha.26", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@lightjs/server", 9 | "version": "2.0.0-alpha.26", 10 | "license": "MIT", 11 | "dependencies": { 12 | "micro": "^9.3.4" 13 | }, 14 | "devDependencies": { 15 | "@types/micro": "^7.3.6", 16 | "typescript": "^4.5.2" 17 | } 18 | }, 19 | "node_modules/@types/micro": { 20 | "version": "7.3.7", 21 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 22 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 23 | "dev": true, 24 | "dependencies": { 25 | "@types/node": "*" 26 | } 27 | }, 28 | "node_modules/@types/node": { 29 | "version": "17.0.23", 30 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 31 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", 32 | "dev": true 33 | }, 34 | "node_modules/arg": { 35 | "version": "4.1.0", 36 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 37 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 38 | }, 39 | "node_modules/bytes": { 40 | "version": "3.0.0", 41 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 42 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", 43 | "engines": { 44 | "node": ">= 0.8" 45 | } 46 | }, 47 | "node_modules/content-type": { 48 | "version": "1.0.4", 49 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 50 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 51 | "engines": { 52 | "node": ">= 0.6" 53 | } 54 | }, 55 | "node_modules/depd": { 56 | "version": "1.1.1", 57 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 58 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", 59 | "engines": { 60 | "node": ">= 0.6" 61 | } 62 | }, 63 | "node_modules/http-errors": { 64 | "version": "1.6.2", 65 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 66 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 67 | "dependencies": { 68 | "depd": "1.1.1", 69 | "inherits": "2.0.3", 70 | "setprototypeof": "1.0.3", 71 | "statuses": ">= 1.3.1 < 2" 72 | }, 73 | "engines": { 74 | "node": ">= 0.6" 75 | } 76 | }, 77 | "node_modules/http-errors/node_modules/inherits": { 78 | "version": "2.0.3", 79 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 80 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 81 | }, 82 | "node_modules/iconv-lite": { 83 | "version": "0.4.19", 84 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 85 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", 86 | "engines": { 87 | "node": ">=0.10.0" 88 | } 89 | }, 90 | "node_modules/is-stream": { 91 | "version": "1.1.0", 92 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 93 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 94 | "engines": { 95 | "node": ">=0.10.0" 96 | } 97 | }, 98 | "node_modules/micro": { 99 | "version": "9.3.4", 100 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 101 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 102 | "dependencies": { 103 | "arg": "4.1.0", 104 | "content-type": "1.0.4", 105 | "is-stream": "1.1.0", 106 | "raw-body": "2.3.2" 107 | }, 108 | "bin": { 109 | "micro": "bin/micro.js" 110 | }, 111 | "engines": { 112 | "node": ">= 8.0.0" 113 | } 114 | }, 115 | "node_modules/raw-body": { 116 | "version": "2.3.2", 117 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 118 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 119 | "dependencies": { 120 | "bytes": "3.0.0", 121 | "http-errors": "1.6.2", 122 | "iconv-lite": "0.4.19", 123 | "unpipe": "1.0.0" 124 | }, 125 | "engines": { 126 | "node": ">= 0.8" 127 | } 128 | }, 129 | "node_modules/setprototypeof": { 130 | "version": "1.0.3", 131 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 132 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 133 | }, 134 | "node_modules/statuses": { 135 | "version": "1.5.0", 136 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 137 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 138 | "engines": { 139 | "node": ">= 0.6" 140 | } 141 | }, 142 | "node_modules/typescript": { 143 | "version": "4.6.3", 144 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 145 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 146 | "dev": true, 147 | "bin": { 148 | "tsc": "bin/tsc", 149 | "tsserver": "bin/tsserver" 150 | }, 151 | "engines": { 152 | "node": ">=4.2.0" 153 | } 154 | }, 155 | "node_modules/unpipe": { 156 | "version": "1.0.0", 157 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 158 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 159 | "engines": { 160 | "node": ">= 0.8" 161 | } 162 | } 163 | }, 164 | "dependencies": { 165 | "@types/micro": { 166 | "version": "7.3.7", 167 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 168 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 169 | "dev": true, 170 | "requires": { 171 | "@types/node": "*" 172 | } 173 | }, 174 | "@types/node": { 175 | "version": "17.0.23", 176 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 177 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==", 178 | "dev": true 179 | }, 180 | "arg": { 181 | "version": "4.1.0", 182 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 183 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 184 | }, 185 | "bytes": { 186 | "version": "3.0.0", 187 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 188 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 189 | }, 190 | "content-type": { 191 | "version": "1.0.4", 192 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 193 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 194 | }, 195 | "depd": { 196 | "version": "1.1.1", 197 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 198 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 199 | }, 200 | "http-errors": { 201 | "version": "1.6.2", 202 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 203 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 204 | "requires": { 205 | "depd": "1.1.1", 206 | "inherits": "2.0.3", 207 | "setprototypeof": "1.0.3", 208 | "statuses": ">= 1.3.1 < 2" 209 | }, 210 | "dependencies": { 211 | "inherits": { 212 | "version": "2.0.3", 213 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 214 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 215 | } 216 | } 217 | }, 218 | "iconv-lite": { 219 | "version": "0.4.19", 220 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 221 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 222 | }, 223 | "is-stream": { 224 | "version": "1.1.0", 225 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 226 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 227 | }, 228 | "micro": { 229 | "version": "9.3.4", 230 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 231 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 232 | "requires": { 233 | "arg": "4.1.0", 234 | "content-type": "1.0.4", 235 | "is-stream": "1.1.0", 236 | "raw-body": "2.3.2" 237 | } 238 | }, 239 | "raw-body": { 240 | "version": "2.3.2", 241 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 242 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 243 | "requires": { 244 | "bytes": "3.0.0", 245 | "http-errors": "1.6.2", 246 | "iconv-lite": "0.4.19", 247 | "unpipe": "1.0.0" 248 | } 249 | }, 250 | "setprototypeof": { 251 | "version": "1.0.3", 252 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 253 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 254 | }, 255 | "statuses": { 256 | "version": "1.5.0", 257 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 258 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 259 | }, 260 | "typescript": { 261 | "version": "4.6.3", 262 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 263 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 264 | "dev": true 265 | }, 266 | "unpipe": { 267 | "version": "1.0.0", 268 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 269 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 270 | } 271 | } 272 | } 273 | -------------------------------------------------------------------------------- /packages/@lightjs/server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/server", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs server", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "server" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/micro": "^7.3.6", 33 | "typescript": "^4.5.2" 34 | }, 35 | "dependencies": { 36 | "@lightjs/config": "^2.0.0-alpha.26", 37 | "@lightjs/router": "^2.0.0-alpha.26", 38 | "@lightjs/types": "^2.0.0-alpha.24", 39 | "micro": "^9.3.4" 40 | }, 41 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 42 | } 43 | -------------------------------------------------------------------------------- /packages/@lightjs/server/src/createServer/index.ts: -------------------------------------------------------------------------------- 1 | import micro from 'micro'; 2 | import { IncomingMessage, ServerResponse } from 'http'; 3 | import { CreateServerOptions, CreateServer } from '@lightjs/types'; 4 | import { createRouter } from '@lightjs/router'; 5 | import { importLightConfig } from '@lightjs/config'; 6 | 7 | export function createServer({ middleware }: CreateServerOptions = {}): CreateServer { 8 | // Import the light config so that if the user has any one-off scripts defined, they will execute 9 | importLightConfig(); 10 | 11 | const { router, reload, importedRoutes } = createRouter({ middleware }); 12 | 13 | // create the http server 14 | const server = micro(async (req: IncomingMessage, res: ServerResponse) => 15 | router.lookup(req, res), 16 | ); 17 | 18 | return { 19 | router, 20 | importedRoutes, 21 | reload, 22 | server, 23 | }; 24 | } 25 | -------------------------------------------------------------------------------- /packages/@lightjs/server/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createServer } from './createServer'; 2 | -------------------------------------------------------------------------------- /packages/@lightjs/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/test/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/test 2 | -------------------------------------------------------------------------------- /packages/@lightjs/test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/test", 3 | "version": "2.0.0-alpha.26", 4 | "description": "lightjs test", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "test" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/micro": "^7.3.6", 33 | "typescript": "^4.5.2" 34 | }, 35 | "dependencies": { 36 | "@lightjs/server": "^2.0.0-alpha.26", 37 | "@lightjs/types": "^2.0.0-alpha.24", 38 | "@lightjs/utils": "^2.0.0-alpha.24", 39 | "micro": "^9.3.4" 40 | }, 41 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 42 | } 43 | -------------------------------------------------------------------------------- /packages/@lightjs/test/src/createRouteTest/index.ts: -------------------------------------------------------------------------------- 1 | import { RouteHandler, ServerfullRoute } from '@lightjs/types'; 2 | import { convertHandlerFunctionToRequestHandler } from '@lightjs/utils'; 3 | import { IncomingMessage, ServerResponse } from 'http'; 4 | import { run } from 'micro'; 5 | 6 | export function createRouteTest(route: RouteHandler) { 7 | // assume that the route is in serverfull mode 8 | const handler = convertHandlerFunctionToRequestHandler(route as ServerfullRoute); 9 | // TODO: duplicated code below, needs refactor 10 | const safeGuardedRoute = (req: IncomingMessage, res: ServerResponse) => run(req, res, handler); 11 | return safeGuardedRoute; 12 | } 13 | -------------------------------------------------------------------------------- /packages/@lightjs/test/src/createTest/index.ts: -------------------------------------------------------------------------------- 1 | import { createServer } from '@lightjs/server'; 2 | import { CreateTestOptions, CreateTest } from '@lightjs/types'; 3 | 4 | export function createTest(opts: CreateTestOptions = {}): CreateTest { 5 | const server = createServer({ middleware: opts.middleware }); 6 | return server; 7 | } 8 | -------------------------------------------------------------------------------- /packages/@lightjs/test/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createTest } from './createTest'; 2 | export { createRouteTest } from './createRouteTest'; 3 | -------------------------------------------------------------------------------- /packages/@lightjs/test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/types/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/types 2 | -------------------------------------------------------------------------------- /packages/@lightjs/types/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/types", 3 | "version": "2.0.0-alpha.24", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "@lightjs/types", 9 | "version": "2.0.0-alpha.24", 10 | "license": "MIT", 11 | "dependencies": { 12 | "find-my-way": "^5.0.0", 13 | "micro": "^9.3.4" 14 | }, 15 | "devDependencies": { 16 | "@netlify/functions": "^0.10.0", 17 | "@types/micro": "^7.3.6", 18 | "@types/node": "^16.11.11", 19 | "typescript": "^4.5.2" 20 | } 21 | }, 22 | "node_modules/@netlify/functions": { 23 | "version": "0.10.0", 24 | "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-0.10.0.tgz", 25 | "integrity": "sha512-NNFADTPnokuoMY1OUhaXlE/Jrzk5lHOl1uB4L/8pw1UJ/CaectZJACMExijbJnqaKIhOQG0WmbBQUh1lgnK/Qg==", 26 | "dev": true, 27 | "dependencies": { 28 | "is-promise": "^4.0.0" 29 | }, 30 | "engines": { 31 | "node": ">=8.3.0" 32 | } 33 | }, 34 | "node_modules/@types/micro": { 35 | "version": "7.3.7", 36 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 37 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 38 | "dev": true, 39 | "dependencies": { 40 | "@types/node": "*" 41 | } 42 | }, 43 | "node_modules/@types/node": { 44 | "version": "16.11.26", 45 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 46 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 47 | "dev": true 48 | }, 49 | "node_modules/arg": { 50 | "version": "4.1.0", 51 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 52 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 53 | }, 54 | "node_modules/bytes": { 55 | "version": "3.0.0", 56 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 57 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", 58 | "engines": { 59 | "node": ">= 0.8" 60 | } 61 | }, 62 | "node_modules/content-type": { 63 | "version": "1.0.4", 64 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 65 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 66 | "engines": { 67 | "node": ">= 0.6" 68 | } 69 | }, 70 | "node_modules/depd": { 71 | "version": "1.1.1", 72 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 73 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=", 74 | "engines": { 75 | "node": ">= 0.6" 76 | } 77 | }, 78 | "node_modules/fast-decode-uri-component": { 79 | "version": "1.0.1", 80 | "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", 81 | "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" 82 | }, 83 | "node_modules/fast-deep-equal": { 84 | "version": "3.1.3", 85 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 86 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 87 | }, 88 | "node_modules/find-my-way": { 89 | "version": "5.4.0", 90 | "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-5.4.0.tgz", 91 | "integrity": "sha512-XROi2CRlo9PkgYomucEB9K6jp3YZeTSM+x2uWJoW9YWTDGr91oCZN8VTuU0V0TVjeMgjIcwD+5tzxDb9iE9kpQ==", 92 | "dependencies": { 93 | "fast-decode-uri-component": "^1.0.1", 94 | "fast-deep-equal": "^3.1.3", 95 | "safe-regex2": "^2.0.0", 96 | "semver-store": "^0.3.0" 97 | }, 98 | "engines": { 99 | "node": ">=12" 100 | } 101 | }, 102 | "node_modules/http-errors": { 103 | "version": "1.6.2", 104 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 105 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 106 | "dependencies": { 107 | "depd": "1.1.1", 108 | "inherits": "2.0.3", 109 | "setprototypeof": "1.0.3", 110 | "statuses": ">= 1.3.1 < 2" 111 | }, 112 | "engines": { 113 | "node": ">= 0.6" 114 | } 115 | }, 116 | "node_modules/iconv-lite": { 117 | "version": "0.4.19", 118 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 119 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", 120 | "engines": { 121 | "node": ">=0.10.0" 122 | } 123 | }, 124 | "node_modules/inherits": { 125 | "version": "2.0.3", 126 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 127 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 128 | }, 129 | "node_modules/is-promise": { 130 | "version": "4.0.0", 131 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 132 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 133 | "dev": true 134 | }, 135 | "node_modules/is-stream": { 136 | "version": "1.1.0", 137 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 138 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", 139 | "engines": { 140 | "node": ">=0.10.0" 141 | } 142 | }, 143 | "node_modules/micro": { 144 | "version": "9.3.4", 145 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 146 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 147 | "dependencies": { 148 | "arg": "4.1.0", 149 | "content-type": "1.0.4", 150 | "is-stream": "1.1.0", 151 | "raw-body": "2.3.2" 152 | }, 153 | "bin": { 154 | "micro": "bin/micro.js" 155 | }, 156 | "engines": { 157 | "node": ">= 8.0.0" 158 | } 159 | }, 160 | "node_modules/raw-body": { 161 | "version": "2.3.2", 162 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 163 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 164 | "dependencies": { 165 | "bytes": "3.0.0", 166 | "http-errors": "1.6.2", 167 | "iconv-lite": "0.4.19", 168 | "unpipe": "1.0.0" 169 | }, 170 | "engines": { 171 | "node": ">= 0.8" 172 | } 173 | }, 174 | "node_modules/ret": { 175 | "version": "0.2.2", 176 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", 177 | "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==", 178 | "engines": { 179 | "node": ">=4" 180 | } 181 | }, 182 | "node_modules/safe-regex2": { 183 | "version": "2.0.0", 184 | "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", 185 | "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", 186 | "dependencies": { 187 | "ret": "~0.2.0" 188 | } 189 | }, 190 | "node_modules/semver-store": { 191 | "version": "0.3.0", 192 | "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", 193 | "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" 194 | }, 195 | "node_modules/setprototypeof": { 196 | "version": "1.0.3", 197 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 198 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 199 | }, 200 | "node_modules/statuses": { 201 | "version": "1.5.0", 202 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 203 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 204 | "engines": { 205 | "node": ">= 0.6" 206 | } 207 | }, 208 | "node_modules/typescript": { 209 | "version": "4.6.3", 210 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 211 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 212 | "dev": true, 213 | "bin": { 214 | "tsc": "bin/tsc", 215 | "tsserver": "bin/tsserver" 216 | }, 217 | "engines": { 218 | "node": ">=4.2.0" 219 | } 220 | }, 221 | "node_modules/unpipe": { 222 | "version": "1.0.0", 223 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 224 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 225 | "engines": { 226 | "node": ">= 0.8" 227 | } 228 | } 229 | }, 230 | "dependencies": { 231 | "@netlify/functions": { 232 | "version": "0.10.0", 233 | "resolved": "https://registry.npmjs.org/@netlify/functions/-/functions-0.10.0.tgz", 234 | "integrity": "sha512-NNFADTPnokuoMY1OUhaXlE/Jrzk5lHOl1uB4L/8pw1UJ/CaectZJACMExijbJnqaKIhOQG0WmbBQUh1lgnK/Qg==", 235 | "dev": true, 236 | "requires": { 237 | "is-promise": "^4.0.0" 238 | } 239 | }, 240 | "@types/micro": { 241 | "version": "7.3.7", 242 | "resolved": "https://registry.npmjs.org/@types/micro/-/micro-7.3.7.tgz", 243 | "integrity": "sha512-MFsX7eCj0Tg3TtphOQvANNvNtFpya+s/rYOCdV6o+DFjOQPFi2EVRbBALjbbgZTXUaJP1Q281MJiJOD40d0UxQ==", 244 | "dev": true, 245 | "requires": { 246 | "@types/node": "*" 247 | } 248 | }, 249 | "@types/node": { 250 | "version": "16.11.26", 251 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 252 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 253 | "dev": true 254 | }, 255 | "arg": { 256 | "version": "4.1.0", 257 | "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.0.tgz", 258 | "integrity": "sha512-ZWc51jO3qegGkVh8Hwpv636EkbesNV5ZNQPCtRa+0qytRYPEs9IYT9qITY9buezqUH5uqyzlWLcufrzU2rffdg==" 259 | }, 260 | "bytes": { 261 | "version": "3.0.0", 262 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", 263 | "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" 264 | }, 265 | "content-type": { 266 | "version": "1.0.4", 267 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 268 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 269 | }, 270 | "depd": { 271 | "version": "1.1.1", 272 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", 273 | "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" 274 | }, 275 | "fast-decode-uri-component": { 276 | "version": "1.0.1", 277 | "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", 278 | "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==" 279 | }, 280 | "fast-deep-equal": { 281 | "version": "3.1.3", 282 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 283 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" 284 | }, 285 | "find-my-way": { 286 | "version": "5.4.0", 287 | "resolved": "https://registry.npmjs.org/find-my-way/-/find-my-way-5.4.0.tgz", 288 | "integrity": "sha512-XROi2CRlo9PkgYomucEB9K6jp3YZeTSM+x2uWJoW9YWTDGr91oCZN8VTuU0V0TVjeMgjIcwD+5tzxDb9iE9kpQ==", 289 | "requires": { 290 | "fast-decode-uri-component": "^1.0.1", 291 | "fast-deep-equal": "^3.1.3", 292 | "safe-regex2": "^2.0.0", 293 | "semver-store": "^0.3.0" 294 | } 295 | }, 296 | "http-errors": { 297 | "version": "1.6.2", 298 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", 299 | "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", 300 | "requires": { 301 | "depd": "1.1.1", 302 | "inherits": "2.0.3", 303 | "setprototypeof": "1.0.3", 304 | "statuses": ">= 1.3.1 < 2" 305 | } 306 | }, 307 | "iconv-lite": { 308 | "version": "0.4.19", 309 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", 310 | "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" 311 | }, 312 | "inherits": { 313 | "version": "2.0.3", 314 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 315 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 316 | }, 317 | "is-promise": { 318 | "version": "4.0.0", 319 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", 320 | "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", 321 | "dev": true 322 | }, 323 | "is-stream": { 324 | "version": "1.1.0", 325 | "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", 326 | "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" 327 | }, 328 | "micro": { 329 | "version": "9.3.4", 330 | "resolved": "https://registry.npmjs.org/micro/-/micro-9.3.4.tgz", 331 | "integrity": "sha512-smz9naZwTG7qaFnEZ2vn248YZq9XR+XoOH3auieZbkhDL4xLOxiE+KqG8qqnBeKfXA9c1uEFGCxPN1D+nT6N7w==", 332 | "requires": { 333 | "arg": "4.1.0", 334 | "content-type": "1.0.4", 335 | "is-stream": "1.1.0", 336 | "raw-body": "2.3.2" 337 | } 338 | }, 339 | "raw-body": { 340 | "version": "2.3.2", 341 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", 342 | "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", 343 | "requires": { 344 | "bytes": "3.0.0", 345 | "http-errors": "1.6.2", 346 | "iconv-lite": "0.4.19", 347 | "unpipe": "1.0.0" 348 | } 349 | }, 350 | "ret": { 351 | "version": "0.2.2", 352 | "resolved": "https://registry.npmjs.org/ret/-/ret-0.2.2.tgz", 353 | "integrity": "sha512-M0b3YWQs7R3Z917WRQy1HHA7Ba7D8hvZg6UE5mLykJxQVE2ju0IXbGlaHPPlkY+WN7wFP+wUMXmBFA0aV6vYGQ==" 354 | }, 355 | "safe-regex2": { 356 | "version": "2.0.0", 357 | "resolved": "https://registry.npmjs.org/safe-regex2/-/safe-regex2-2.0.0.tgz", 358 | "integrity": "sha512-PaUSFsUaNNuKwkBijoAPHAK6/eM6VirvyPWlZ7BAQy4D+hCvh4B6lIG+nPdhbFfIbP+gTGBcrdsOaUs0F+ZBOQ==", 359 | "requires": { 360 | "ret": "~0.2.0" 361 | } 362 | }, 363 | "semver-store": { 364 | "version": "0.3.0", 365 | "resolved": "https://registry.npmjs.org/semver-store/-/semver-store-0.3.0.tgz", 366 | "integrity": "sha512-TcZvGMMy9vodEFSse30lWinkj+JgOBvPn8wRItpQRSayhc+4ssDs335uklkfvQQJgL/WvmHLVj4Ycv2s7QCQMg==" 367 | }, 368 | "setprototypeof": { 369 | "version": "1.0.3", 370 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", 371 | "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" 372 | }, 373 | "statuses": { 374 | "version": "1.5.0", 375 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 376 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 377 | }, 378 | "typescript": { 379 | "version": "4.6.3", 380 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 381 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 382 | "dev": true 383 | }, 384 | "unpipe": { 385 | "version": "1.0.0", 386 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 387 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 388 | } 389 | } 390 | } 391 | -------------------------------------------------------------------------------- /packages/@lightjs/types/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/types", 3 | "version": "2.0.0-alpha.24", 4 | "description": "lightjs types", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "types" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@netlify/functions": "^0.10.0", 33 | "@types/micro": "^7.3.6", 34 | "@types/node": "^16.11.11", 35 | "typescript": "^4.5.2" 36 | }, 37 | "dependencies": { 38 | "find-my-way": "^5.0.0", 39 | "micro": "^9.3.4" 40 | }, 41 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 42 | } 43 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/config.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from './createRoute'; 2 | import { Logger } from './logger'; 3 | 4 | export type Config = {}; 5 | 6 | export type CreateConfig = () => Config; 7 | 8 | export type CreateLoggerConfig = () => Logger; 9 | 10 | type MiddlewareConfig = { 11 | global: Array; 12 | }; 13 | export type CreateMiddlewareConfig = () => MiddlewareConfig; 14 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/context.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage, ServerResponse } from 'http'; 2 | import { createError } from 'micro'; 3 | 4 | export interface Request extends IncomingMessage { 5 | // params: Record; 6 | // query: Record; 7 | } 8 | 9 | export interface Response extends ServerResponse {} 10 | 11 | // Context 12 | type BodyParsingInfo = { limit?: string | number; encoding?: string }; 13 | export interface Context { 14 | req: Request; 15 | res: Response; 16 | buffer: (info?: BodyParsingInfo) => Promise; 17 | text: (info?: BodyParsingInfo) => Promise; 18 | json: (info?: BodyParsingInfo) => Promise; 19 | send: (code: number, data?: any) => Promise; 20 | sendError: (info: { 21 | statusCode?: number; 22 | status?: number; 23 | message?: string; 24 | stack?: string; 25 | }) => Promise; 26 | createError: typeof createError; 27 | } 28 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/createRoute.ts: -------------------------------------------------------------------------------- 1 | import { Context } from './context'; 2 | import { HTTPMethod } from './http'; 3 | 4 | export type UseMiddleware = (mw: Middleware | Middleware[], methods?: HTTPMethod[]) => void; 5 | export type InternalRoute = Partial>; 6 | export type ComponentOpts = { useMiddleware: UseMiddleware }; 7 | export type Component = (opts: ComponentOpts) => InternalRoute; 8 | // TODO: Restrict `HandlerFunction` type 9 | export type HandlerFunction = (params: Context) => any | Promise; 10 | export type Middleware = (fn: HandlerFunction) => HandlerFunction; 11 | 12 | // interface RouteMethod { 13 | // handler: HandlerFunction; 14 | // middleware: Middleware[]; 15 | // } 16 | // type BaseRoute = { 17 | // [key in HTTPMethod]?: RouteMethod; 18 | // }; 19 | // export interface Route extends BaseRoute { 20 | // middleware: Middleware[]; 21 | // } 22 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/createRouter.ts: -------------------------------------------------------------------------------- 1 | import { Middleware } from './createRoute'; 2 | import { ServerfullRoute } from './routeHandler'; 3 | 4 | export type CreateRouterOptions = { 5 | middleware?: Middleware[]; 6 | }; 7 | 8 | export type ImportedRoute = { 9 | path: string; 10 | route: ServerfullRoute; 11 | file: string; 12 | }; 13 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/createServer.ts: -------------------------------------------------------------------------------- 1 | import Router from 'find-my-way'; 2 | import { Server } from 'http'; 3 | import { Middleware } from './createRoute'; 4 | import { ImportedRoute } from './createRouter'; 5 | 6 | export type CreateServerOptions = { 7 | middleware?: Middleware[]; 8 | }; 9 | 10 | export type CreateServer = { 11 | server: Server; 12 | router: Router.Instance; 13 | importedRoutes: ImportedRoute[]; 14 | reload: () => ImportedRoute[]; 15 | }; 16 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/createTest.ts: -------------------------------------------------------------------------------- 1 | import { CreateServer } from './createServer'; 2 | import { Middleware } from './createRoute'; 3 | 4 | export type CreateTestOptions = { 5 | middleware?: Middleware[]; 6 | }; 7 | 8 | export type CreateTest = CreateServer; 9 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/http.ts: -------------------------------------------------------------------------------- 1 | import { HTTPMethod } from 'find-my-way'; 2 | import { METHODS } from 'http'; 3 | 4 | export const Methods: HTTPMethod[] = METHODS as HTTPMethod[]; 5 | 6 | export { HTTPMethod }; 7 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/index.ts: -------------------------------------------------------------------------------- 1 | export { Request, Response, Context } from './context'; 2 | export { HTTPMethod, Methods } from './http'; 3 | export { 4 | Component, 5 | ComponentOpts, 6 | InternalRoute, 7 | HandlerFunction, 8 | Middleware, 9 | } from './createRoute'; 10 | export { CreateRouterOptions, ImportedRoute } from './createRouter'; 11 | export { CreateServerOptions, CreateServer } from './createServer'; 12 | export { CreateTest, CreateTestOptions } from './createTest'; 13 | export { 14 | RouteHandler, 15 | NetlifyRoute, 16 | RunKitRoute, 17 | ServerfullRoute, 18 | ServerlessRoute, 19 | VercelRoute, 20 | } from './routeHandler'; 21 | export { Logger } from './logger'; 22 | export { Config, CreateConfig, CreateLoggerConfig, CreateMiddlewareConfig } from './config'; 23 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/logger.ts: -------------------------------------------------------------------------------- 1 | export interface Logger {} 2 | -------------------------------------------------------------------------------- /packages/@lightjs/types/src/routeHandler.ts: -------------------------------------------------------------------------------- 1 | import { IncomingMessage, ServerResponse } from 'http'; 2 | import type { Handler } from '@netlify/functions'; 3 | import { Context } from './context'; 4 | 5 | export type RunKitRoute = { endpoint: (req: IncomingMessage, res: ServerResponse) => any }; 6 | export type VercelRoute = (req: IncomingMessage, res: ServerResponse) => any; 7 | export type NetlifyRoute = { handler: Handler }; 8 | export type ServerfullRoute = (ctx: Context) => any; 9 | export type ServerlessRoute = RunKitRoute | VercelRoute | NetlifyRoute; 10 | export type RouteHandler = ServerfullRoute | ServerlessRoute; 11 | -------------------------------------------------------------------------------- /packages/@lightjs/types/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/README.md: -------------------------------------------------------------------------------- 1 | # @lightjs/utils 2 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@lightjs/utils", 3 | "version": "2.0.0-alpha.24", 4 | "description": "lightjs utils", 5 | "main": "lib", 6 | "types": "lib/index.d.ts", 7 | "files": [ 8 | "lib" 9 | ], 10 | "scripts": { 11 | "dev": "tsc -w", 12 | "build": "npm run clean && npm run compile", 13 | "clean": "rm -rf lib", 14 | "compile": "tsc", 15 | "prepublishOnly": "npm run build" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/ludicroushq/light.git" 20 | }, 21 | "keywords": [ 22 | "lightjs", 23 | "utils" 24 | ], 25 | "author": "Manthan Mallikarjun", 26 | "license": "MIT", 27 | "bugs": { 28 | "url": "https://github.com/ludicroushq/light/issues" 29 | }, 30 | "homepage": "https://github.com/ludicroushq/light#readme", 31 | "devDependencies": { 32 | "@types/jest": "^27.0.3", 33 | "@types/micro": "^7.3.6", 34 | "jest": "^27.4.3", 35 | "ts-jest": "^27.0.7", 36 | "typescript": "^4.5.2" 37 | }, 38 | "dependencies": { 39 | "@lightjs/types": "^2.0.0-alpha.24", 40 | "find-my-way": "^5.0.0", 41 | "micro": "^9.3.4" 42 | }, 43 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 44 | } 45 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/src/applyMiddleware.ts: -------------------------------------------------------------------------------- 1 | import { HandlerFunction, Middleware } from '@lightjs/types'; 2 | 3 | export function applyMiddleware(middleware: Middleware[], handler: HandlerFunction) { 4 | return [...middleware] 5 | .reverse() 6 | .reduce((acc: HandlerFunction, val: Middleware) => val(acc), handler); 7 | } 8 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/src/convertHandlerFunctionToRequestHandler.ts: -------------------------------------------------------------------------------- 1 | import { createError, buffer, text, json, send, sendError } from 'micro'; 2 | import { HandlerFunction } from '@lightjs/types'; 3 | import { IncomingMessage, ServerResponse } from 'http'; 4 | 5 | export function convertHandlerFunctionToRequestHandler(handler: HandlerFunction) { 6 | return (req: IncomingMessage, res: ServerResponse) => 7 | handler({ 8 | req, 9 | res, 10 | createError, 11 | buffer: (info) => buffer(req, info), 12 | text: (info) => text(req, info), 13 | json: (info) => json(req, info), 14 | send: (code, data) => send(res, code, data), 15 | sendError: (info) => sendError(req, res, info), 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/src/index.ts: -------------------------------------------------------------------------------- 1 | export { applyMiddleware } from './applyMiddleware'; 2 | export { convertHandlerFunctionToRequestHandler } from './convertHandlerFunctionToRequestHandler'; 3 | -------------------------------------------------------------------------------- /packages/@lightjs/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /packages/light/README.md: -------------------------------------------------------------------------------- 1 | # light 2 | 3 | [![Github Actions](https://img.shields.io/github/workflow/status/ludicroushq/light/main?label=ci%20status&style=for-the-badge&labelColor=0a0a0a)](https://circleci.com/gh/ludicroushq/light) 4 | [![npm](https://img.shields.io/npm/v/light.svg?label=npm%20version&style=for-the-badge&labelColor=0a0a0a)](https://www.npmjs.com/package/light) 5 | [![Downloads](https://img.shields.io/npm/dm/light.svg?label=downloads&style=for-the-badge&labelColor=0a0a0a)](https://www.npmjs.com/package/light) 6 | [![Stars](https://img.shields.io/github/stars/ludicroushq/light.svg?style=for-the-badge&labelColor=0a0a0a)](https://github.com/ludicroushq/light) 7 | [![Coveralls GitHub](https://img.shields.io/codecov/c/github/ludicroushq/light?label=code%20coverage&style=for-the-badge&labelColor=0a0a0a)](https://codecov.io/gh/ludicroushq/light) 8 | 9 | **NOTICE: Since light is a work in progress, breaking changes will be made every MINOR patch until 2.0** 10 | 11 | light is a **light**ning fast web framework. 12 | -------------------------------------------------------------------------------- /packages/light/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "light", 3 | "version": "2.0.0-alpha.26", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "light", 9 | "version": "2.0.0-alpha.26", 10 | "license": "MIT", 11 | "bin": { 12 | "light": "lib/cli/index.js" 13 | }, 14 | "devDependencies": { 15 | "@types/node": "^16.11.11", 16 | "typescript": "^4.5.2" 17 | } 18 | }, 19 | "node_modules/@types/node": { 20 | "version": "16.11.26", 21 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 22 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 23 | "dev": true 24 | }, 25 | "node_modules/typescript": { 26 | "version": "4.6.3", 27 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 28 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 29 | "dev": true, 30 | "bin": { 31 | "tsc": "bin/tsc", 32 | "tsserver": "bin/tsserver" 33 | }, 34 | "engines": { 35 | "node": ">=4.2.0" 36 | } 37 | } 38 | }, 39 | "dependencies": { 40 | "@types/node": { 41 | "version": "16.11.26", 42 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", 43 | "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==", 44 | "dev": true 45 | }, 46 | "typescript": { 47 | "version": "4.6.3", 48 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", 49 | "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", 50 | "dev": true 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /packages/light/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "light", 3 | "version": "2.0.0-alpha.26", 4 | "description": "a next-gen framework", 5 | "main": "lib", 6 | "files": [ 7 | "lib" 8 | ], 9 | "scripts": { 10 | "dev": "tsc -w", 11 | "build": "npm run clean && npm run compile", 12 | "clean": "rm -rf lib", 13 | "compile": "tsc", 14 | "prepublishOnly": "npm run build" 15 | }, 16 | "types": "lib/index.d.ts", 17 | "bin": { 18 | "light": "./lib/cli/index.js" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/ludicroushq/light.git" 23 | }, 24 | "keywords": [ 25 | "light", 26 | "server" 27 | ], 28 | "author": "Manthan Mallikarjun", 29 | "license": "MIT", 30 | "bugs": { 31 | "url": "https://github.com/ludicroushq/light/issues" 32 | }, 33 | "homepage": "https://github.com/ludicroushq/light#readme", 34 | "dependencies": { 35 | "@lightjs/cli": "^2.0.0-alpha.26", 36 | "@lightjs/config": "^2.0.0-alpha.26", 37 | "@lightjs/core": "^2.0.0-alpha.26", 38 | "@lightjs/logger": "^2.0.0-alpha.26", 39 | "@lightjs/server": "^2.0.0-alpha.26", 40 | "@lightjs/test": "^2.0.0-alpha.26", 41 | "@lightjs/types": "^2.0.0-alpha.24" 42 | }, 43 | "devDependencies": { 44 | "@types/node": "^16.11.11", 45 | "typescript": "^4.5.2" 46 | }, 47 | "gitHead": "21e1deb610f7d54f0f7da3ac0e4514db6b59c25c" 48 | } 49 | -------------------------------------------------------------------------------- /packages/light/src/cli/index.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import '@lightjs/cli'; 4 | -------------------------------------------------------------------------------- /packages/light/src/index.ts: -------------------------------------------------------------------------------- 1 | export { createConfig, createLoggerConfig, createMiddlewareConfig } from '@lightjs/config'; 2 | export { createTest, createRouteTest } from '@lightjs/test'; 3 | export { createServer } from '@lightjs/server'; 4 | export { createRoute, withConnect } from '@lightjs/core'; 5 | export { useLogger } from '@lightjs/logger'; 6 | export { 7 | Request, 8 | Response, 9 | Component, 10 | Logger, 11 | Context, 12 | HandlerFunction, 13 | Middleware, 14 | } from '@lightjs/types'; 15 | -------------------------------------------------------------------------------- /packages/light/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.build.json", 3 | "compilerOptions": { 4 | "outDir": "./lib" 5 | }, 6 | "exclude": ["**/__tests__/**/*.test.ts"], 7 | "include": ["src/**/*"] 8 | } 9 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base", ":preserveSemverRanges"], 4 | "packageRules": [ 5 | { 6 | "matchUpdateTypes": ["patch", "minor"], 7 | "groupName": "dependencies (non-major)", 8 | "automerge": true 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /scripts/update.mjs: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env zx 2 | 3 | await $`npm update && npm audit fix`; 4 | await $`lerna exec --parallel -- npm update && lerna exec --parallel -- npm audit fix`; 5 | 6 | cd('./benchmark'); 7 | await $`npm update && npm audit fix`; 8 | cd('../'); 9 | 10 | cd('./examples'); 11 | await $`lerna exec --parallel -- npm update && lerna exec --parallel -- npm audit fix`; 12 | cd('../'); 13 | 14 | cd('./website'); 15 | await $`npm update && npm audit fix`; 16 | cd('../'); 17 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2017", 4 | "module": "commonjs", 5 | "declaration": true, 6 | "outDir": "./lib", 7 | "strict": true, 8 | "esModuleInterop": true, 9 | "skipLibCheck": true, 10 | "forceConsistentCasingInFileNames": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.build.json", 3 | "include": ["packages/**/*", ".eslintrc.js", "jest.config.js"] 4 | } 5 | -------------------------------------------------------------------------------- /website/.cspell.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1", 3 | "language": "en", 4 | "dictionaries": ["light"], 5 | "dictionaryDefinitions": [ 6 | { 7 | "name": "light", 8 | "path": "./dictionary.txt" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. 4 | 5 | ## Installation 6 | 7 | ```console 8 | yarn install 9 | ``` 10 | 11 | ## Local Development 12 | 13 | ```console 14 | yarn start 15 | ``` 16 | 17 | This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ## Build 20 | 21 | ```console 22 | yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ## Deployment 28 | 29 | ```console 30 | GIT_USER= USE_SSH=true yarn deploy 31 | ``` 32 | 33 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 34 | -------------------------------------------------------------------------------- /website/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /website/blog/2019-05-28-hola.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: hola 3 | title: Hola 4 | author: Gao Wei 5 | author_title: Docusaurus Core Team 6 | author_url: https://github.com/wgao19 7 | author_image_url: https://avatars1.githubusercontent.com/u/2055384?v=4 8 | tags: [hola, docusaurus] 9 | --- 10 | 11 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque elementum dignissim ultricies. Fusce rhoncus ipsum tempor eros aliquam consequat. Lorem ipsum dolor sit amet 12 | -------------------------------------------------------------------------------- /website/blog/2019-05-29-hello-world.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: hello-world 3 | title: Hello 4 | author: Endilie Yacop Sucipto 5 | author_title: Maintainer of Docusaurus 6 | author_url: https://github.com/endiliey 7 | author_image_url: https://avatars1.githubusercontent.com/u/17883920?s=460&v=4 8 | tags: [hello, docusaurus] 9 | --- 10 | 11 | Welcome to this blog. This blog is created with [**Docusaurus 2 alpha**](https://v2.docusaurus.io/). 12 | 13 | 14 | 15 | This is a test post. 16 | 17 | A whole bunch of other information. 18 | -------------------------------------------------------------------------------- /website/blog/2019-05-30-welcome.md: -------------------------------------------------------------------------------- 1 | --- 2 | slug: welcome 3 | title: Welcome 4 | author: Yangshun Tay 5 | author_title: Front End Engineer @ Facebook 6 | author_url: https://github.com/yangshun 7 | author_image_url: https://avatars0.githubusercontent.com/u/1315101?s=400&v=4 8 | tags: [facebook, hello, docusaurus] 9 | --- 10 | 11 | Blog features are powered by the blog plugin. Simply add files to the `blog` directory. It supports tags as well! 12 | 13 | Delete the whole directory if you don't want the blog features. As simple as that! 14 | -------------------------------------------------------------------------------- /website/dictionary.txt: -------------------------------------------------------------------------------- 1 | runkit 2 | netlify's 3 | vercel 4 | kubernetes 5 | proxying 6 | usemiddleware 7 | useplugin 8 | HOCs 9 | youch 10 | stylelint 11 | Infima 12 | clsx 13 | typeof 14 | websockets 15 | semibold 16 | Fastify 17 | heroicons 18 | vercel's 19 | -------------------------------------------------------------------------------- /website/docs/api/context/buffer.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: buffer 3 | title: buffer 4 | --- 5 | 6 | ## `buffer(info?: BodyParsingInfo): Promise` 7 | 8 | TODO: coming soon 9 | 10 | ### `BodyParsingInfo` 11 | 12 | ```ts 13 | type BodyParsingInfo = { limit?: string | number; encoding?: string }; 14 | ``` 15 | -------------------------------------------------------------------------------- /website/docs/api/context/create-error.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: create-error 3 | title: createError 4 | --- 5 | 6 | ## `createError(code: number, msg: string, orig?: Error) => Error` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/context/json.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: json 3 | title: json 4 | --- 5 | 6 | 7 | 8 | ## `json(info?: BodyParsingInfo): Promise` 9 | 10 | TODO: coming soon 11 | 12 | ### [`BodyParsingInfo`](api/context/buffer.md#bodyparsinginfo) 13 | -------------------------------------------------------------------------------- /website/docs/api/context/req.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: req 3 | title: req 4 | --- 5 | 6 | ## `req: Request` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/context/res.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: res 3 | title: res 4 | --- 5 | 6 | ## `res: Response` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/context/send-error.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: send-error 3 | title: sendError 4 | --- 5 | 6 | ## `sendError: (info: SendErrorInfo) => Promise` 7 | 8 | TODO: coming soon 9 | 10 | ### `SendErrorInfo` 11 | 12 | ```ts 13 | interface SendErrorInfo { 14 | statusCode?: number; 15 | status?: number; 16 | message?: string; 17 | stack?: string; 18 | } 19 | ``` 20 | -------------------------------------------------------------------------------- /website/docs/api/context/send.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: send 3 | title: send 4 | --- 5 | 6 | ## `send: (code: number, data?: any) => Promise` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/context/text.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: text 3 | title: text 4 | --- 5 | 6 | 7 | 8 | ## `text(info?: BodyParsingInfo): Promise` 9 | 10 | TODO: coming soon 11 | 12 | ### [`BodyParsingInfo`](api/context/buffer.md#bodyparsinginfo) 13 | -------------------------------------------------------------------------------- /website/docs/api/context/use-params.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: use-params 3 | title: useParams 4 | --- 5 | 6 | ## `useParams(path: string): object` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/context/use-query.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: use-query 3 | title: useQuery 4 | --- 5 | 6 | ## `useQuery(): object` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/api/exported/create-route.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: create-route 3 | title: createRoute 4 | --- 5 | 6 | ## `createRoute(): CreateRoute` 7 | 8 | TODO: coming soon 9 | 10 | ### `type CreateRoute` 11 | 12 | ```typescript 13 | type CreateRoute = Record & { 14 | all: HandlerMethod; 15 | route: AnyRoute; 16 | useMiddleware: (middleware: Middleware, methods?: HTTPMethod[]) => void; 17 | usePlugin: (plugin: Plugin, methods?: HTTPMethod[]) => void; 18 | useConnect: (connect: any, methods?: HTTPMethod[]) => void; 19 | run: typeof run; 20 | }; 21 | ``` 22 | -------------------------------------------------------------------------------- /website/docs/api/exported/create-server.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: create-server 3 | title: createServer 4 | --- 5 | 6 | ## `createServer(opts: CreateServerOptions): LightServer` 7 | 8 | TODO: coming soon 9 | 10 | ### `CreateServerOptions` 11 | 12 | ```typescript 13 | interface CreateServerOptions { 14 | youch?: boolean; 15 | requestLogger?: boolean; 16 | } 17 | ``` 18 | ### `LightServer` 19 | 20 | ```typescript 21 | interface LightServer { 22 | server: Server; 23 | router: any; 24 | reload: () => void; 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /website/docs/api/exported/create-test.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: create-test 3 | title: createTest 4 | --- 5 | 6 | 7 | ## `createTest(opts: CreateServerOptions): LightServer` 8 | 9 | TODO: coming soon 10 | 11 | ### [`CreateServerOptions`](api/exported/create-server.md#createserveroptions) 12 | ### [`LightServer`](api/exported/create-server.md#lightserver) 13 | -------------------------------------------------------------------------------- /website/docs/api/exported/logger.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: logger 3 | title: logger 4 | --- 5 | 6 | ## `logger: any` 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/core/body-parsing.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: body-parsing 3 | title: Body Parsing 4 | --- 5 | 6 | ## Introduction 7 | 8 | Light uses [micro](https://github.com/vercel/micro) under the hood. As a result, it **does not** parse the body for you by default. However, inside of the context (along with `req`, and `res` objects), it includes the async functions `buffer`, `text`, and `json` to help you process the body. Not parsing the body automatically allows other routes to run quicker. 9 | 10 | :::note 11 | If you are looking at micro's docs, please note that you **do not** pass the `req` parameter, because light does it for you. Instead only pass in the second `options` parameter (optional). 12 | ::: 13 | 14 | ## Example 15 | 16 | import Embed from 'react-runkit'; 17 | 18 | { 24 | const body = await text(); 25 | return { body }; 26 | });\n 27 | module.exports = route;`} 28 | /> 29 | 30 | Run the following command to make a request to the URL provided in the example 31 | 32 | ``` 33 | curl -X POST URL_GOES_HERE -d "hello world" 34 | ``` 35 | -------------------------------------------------------------------------------- /website/docs/core/connect.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: connect 3 | title: Connect/Express Middleware 4 | --- 5 | 6 | :::note 7 | This is currently nothing more than a wrapper. We are looking to support all of the popular Connect middleware, so if you find one that does not work, please file an issue on GitHub! 8 | ::: 9 | 10 | ## Introduction 11 | 12 | Light has a tiny wrapper for [Connect](https://github.com/senchalabs/connect) style middleware. It currently does not do anything other than directly convert the connect middleware to light middleware. We are exploring different popular middleware and hope to support all of them. 13 | 14 | ## Using a Middleware 15 | 16 | You can convert connect middleware to light middleware by using the `withConnect` function. 17 | 18 | import Embed from 'react-runkit'; 19 | 20 | 'hello, this has cors headers!');\n 28 | module.exports = route;`} 29 | /> 30 | -------------------------------------------------------------------------------- /website/docs/core/context.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: context 3 | title: Context 4 | --- 5 | 6 | ## Introduction 7 | 8 | Context is just another name for the parameter available in middleware, plugins, and route methods. These are the available values. 9 | 10 | - `req`: request 11 | - `res`: response 12 | - `params`: see [params](core/params.mdx) docs 13 | - `query`: see [query](core/query.mdx) docs 14 | - `buffer`: [micro](https://github.com/vercel/micro)'s buffer function 15 | - `text`: [micro](https://github.com/vercel/micro)'s text function 16 | - `json`: [micro](https://github.com/vercel/micro)'s json function 17 | - `send`: [micro](https://github.com/vercel/micro)'s send function 18 | - `sendError`: [micro](https://github.com/vercel/micro)'s sendError function 19 | - `createError`: [micro](https://github.com/vercel/micro)'s createError function 20 | -------------------------------------------------------------------------------- /website/docs/core/error-handling.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: error-handling 3 | title: Error Handling 4 | --- 5 | 6 | ## Introduction 7 | 8 | Since light uses [micro](https://github.com/vercel/micro) under the hood, we can use the same techniques for error handling. Any errors that are thrown are automatically caught and handled by light/micro. 9 | 10 | 11 | 12 | In general, it checks the error object for `statusCode` and a `message`. You can also use the `createError` and `sendError` functions. See more information [here](https://github.com/vercel/micro#error-handling). 13 | 14 | :::note 15 | If you are looking at micro's docs, please note that you **do not** pass the `req` or `res` parameters, because light does it for you. Instead only pass in the third parameter, `err`. 16 | ::: 17 | 18 | ## Example 19 | 20 | 21 | 22 | import Embed from 'react-runkit'; 23 | 24 | { 30 | throw createError(401, 'please sign in'); 31 | });\n 32 | module.exports = route;`} 33 | /> 34 | 35 | or with `sendError` 36 | 37 | { 43 | const err = new Error('please sign in'); 44 | err.statusCode = 401; 45 | sendError(err); 46 | });\n 47 | module.exports = route;`} 48 | /> 49 | -------------------------------------------------------------------------------- /website/docs/core/hot-module-reloading.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: hot-module-reloading 3 | title: Hot Module Reloading (HMR) 4 | --- 5 | 6 | ## Introduction 7 | 8 | Hot Module Reloading (HMR) is not a new concept for JavaScript! However, it is almost exclusively done in the front-end with React and Vue. Using similar techniques, we can finally update our server without having to restart the whole program (like in Ruby on Rails, Phoenix, etc). 9 | 10 | ## Why? 11 | 12 | HMR is extremely useful when working with big programs. If you use tools like nodemon, anytime you make a change, your server will restart. This means that your server will re-connect to the database, re-connect to key-value stores, re-compile templates, and re-load every single route... This can take up to 3-5 seconds, every single time you make a change, so you will probably be very familiar with this page: 13 | 14 | ![connection refused](/img/hmr/connection-refused.png) 15 | 16 | With HMR all of those problems will go away. Some times you will have restart manually but it is very rare. 17 | 18 | ## Dangers 19 | 20 | The reason many avoid HMR in node is because it is known to cause memory leaks. But does it matter? Not really, for a few reasons. 21 | 22 | - This is enabled exclusively in development so you will never have to worry about leaks in your production sever. 23 | - It will generally take a LOT of reloads before memory leaks become a issue in development so it is mostly okay. 24 | 25 | To stay on the safe side, simply restart your server every couple of hours. 26 | 27 | ## Usage 28 | 29 | Simply run `light dev` to start a server with HMR. Any time you change a file, it will be hot swapped. 30 | -------------------------------------------------------------------------------- /website/docs/core/logging.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: logging 3 | title: Logging 4 | --- 5 | 6 | :::note 7 | **It is highly recommend that you always use light's logger method over `console.log`** 8 | ::: 9 | 10 | ## Introduction 11 | 12 | Logging is extremely important when it comes to building application as it lets you debug through your logs. Since the logging community in node is fragmented, light allows you to provide the logging function. By default it uses console but can be overridden in the `config/logger.js` file like so. 13 | 14 | ```js {2-4} title="config/logger.js" 15 | const { createLogger } = require('light'); 16 | 17 | module.exports = createLogger({ 18 | logger() { 19 | return myCustomLogger; 20 | }, 21 | }); 22 | ``` 23 | 24 | :::caution 25 | Defining a custom logger does not work in all serverless environments. Currently it is verified working in Vercel if you use the config provided in the [vercel deployment guide](deploy/vercel.md). 26 | ::: 27 | 28 | Everywhere else in your application you can use the logger by importing it from light. 29 | 30 | import Embed from 'react-runkit'; 31 | 32 | { 38 | logger.info(\`request made to \${req.url}\`); 39 | return 'hello world!'; 40 | });\n 41 | module.exports = route;`} 42 | /> 43 | -------------------------------------------------------------------------------- /website/docs/core/middleware.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: middleware 3 | title: Middleware 4 | --- 5 | 6 | ## Introduction 7 | 8 | Light middleware is slightly different compared to other kinds of middleware in node frameworks. Middleware allow you to wrap a request completely and run code, before the request, after the request, and also mutate the response. It is similar to Higher Order Components (HOCs) in React. 9 | 10 | ## Using a Middleware 11 | 12 | There are three different ways you can inject a middleware into a request handler. 13 | 14 | 1. Method specific - By passing it into a `GET`, `POST`, etc function 15 | 2. Route specific - By using the `useMiddleware` function exported by `createRoute` 16 | 3. Global - TODO 17 | 18 | A middleware is a function that takes in a fn and returns another function that takes in a [context](core/context.md) and a valid response. 19 | 20 | While that is the official definition of a light plugin, it is quite confusing so lets break it down: 21 | 22 | 1. A middleware is a function 23 | 2. The parameter sent to the middleware is another function (called `fn`). `fn` is the actual route handler that is defined in the http method functions. (Think of it like the `next` function in Express middleware) In the majority of cases, you will want to await `fn` in the following step to get the intended response and then mutate if you so choose. 24 | 3. The middleware should return another function that takes in a context and returns a response. You will want to use the previous `fn` that was provided to get the intended response and mutate if you so choose. 25 | 4. **Make sure to either return a value at the end of your plugin or end the request with `send`.** 26 | 27 | A typical middleware looks like this. 28 | 29 | import Embed from 'react-runkit'; 30 | 31 | async (ctx) => { 37 | const before = Date.now(); 38 | const result = await fn(ctx); 39 | const after = Date.now(); 40 | console.log('request served in', after - before, 'ms'); 41 | return result; 42 | });\n 43 | GET(() => 'hello world!');\n 44 | module.exports = route;`} 45 | /> 46 | 47 | Make a request to the URL above and take a look at the logs. You can see that we were able to start a timer before the rest of the code, and then `console.log` the difference after. 48 | -------------------------------------------------------------------------------- /website/docs/core/params.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: params 3 | title: Params 4 | --- 5 | 6 | ## Introduction 7 | 8 | Params allow you to dynamically serve routes. To set up routing in server mode (for development), check out the [routing](core/routing.md) guide. A `params` object is passed as part of the context and can be used to extract the params out of the url. 9 | 10 | TODO 11 | 12 | import Embed from 'react-runkit'; 13 | 14 | { 20 | if (!req.url.startsWith('/users')) return 'please visit /users/:username';\n 21 | const { username } = useParams('/users/:username'); 22 | return \`hello \${username}\`; 23 | });\n 24 | module.exports = route;`} 25 | /> 26 | -------------------------------------------------------------------------------- /website/docs/core/query.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: query 3 | title: Query 4 | --- 5 | 6 | ## Introduction 7 | 8 | Light automatically parses query parameters for you. A `query` object is passed as part of the context and can be used to extract the query params out of the url. If multiple values with the same key are passed, then it returns an array instead of a string. 9 | 10 | TODO 11 | 12 | import Embed from 'react-runkit'; 13 | 14 | { 20 | const { hello } = useQuery(); 21 | if (!hello) return 'please add "?hello=world" or "?hello=1&hello=2" to the url';\n 22 | return { hello }; 23 | });\n 24 | module.exports = route;`} 25 | /> 26 | -------------------------------------------------------------------------------- /website/docs/core/routes.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: routes 3 | title: Routes 4 | --- 5 | 6 | ## Introduction 7 | 8 | Every route file must make use of the `createRoute` function to work correctly. The `createRoute` wrapper allows us to understand how to process the requests for different methods and also mutate what the file exports to work in different server/serverless environments. 9 | 10 | Check out the routing guide on the left to understand how these files work together. 11 | 12 | ## Create Route 13 | 14 | The `createRoute` function can be imported from light and returns an object containing a myriad of functions. Here are the key ones you should know. 15 | 16 | - `route`: the resulting route handler that is generated by calling the other functions. **Do not invoke this function, instead just export it** 17 | - `GET`, `POST`, etc: these are route handling functions (described below) where you can specify how to respond to requests 18 | - `useMiddleware`: allows you to add middleware ([described below](#usemiddleware)) 19 | 20 | ```js 21 | const { createRoute } = require('light'); 22 | 23 | const { route, useMiddleware, GET, POST, PUT, PATCH, DELETE, ...etc } = createRoute(); 24 | 25 | // implement your methods here 26 | 27 | module.exports = route; 28 | // or optionally add serverless support 29 | // module.exports = route; 30 | ``` 31 | 32 | ## Example 33 | 34 | import Embed from 'react-runkit'; 35 | 36 | 'hello get'); 42 | POST(() => 'hello post'); 43 | module.exports = route;`} 44 | /> 45 | 46 | ## `route` 47 | 48 | Under the hood, `createRoute` is a closure containing information on how to respond requests. The `route` variable is an object that when injected into the router when the server starts or will transform based on `process.env.LIGHT_ENV`. 49 | 50 | For light to properly work, you must export this object as shown above. 51 | 52 | ## `GET`, `POST` etc 53 | 54 | Using `GET`, `POST` and other HTTP method functions will allow you to respond to requests. You may choose to implement as many methods as you want. 55 | 56 | You must pass a function to the methods which accepts a ctx parameter (see [the context docs](core/context.md) docs) which includes keys such as `req`, `res`, `send`. Inside of the function you can either respond to the request using the provided `send` function, or you can return a string or JSON. Light uses [`micro`](https://github.com/vercel/micro) under the hood to respond to requests. 57 | 58 | ## `useMiddleware` 59 | 60 | `useMiddleware` allows you to inject middleware for the route. You can also specify which methods the middleware should apply to. You may call this function as many times as you need, passing in one middleware function each time. See [the middleware docs](core/middleware.mdx) for more information. 61 | 62 | There are additional helper functions such as `withConnect` which will wrap [Connect](https://github.com/senchalabs/connect) based middleware (such as express middleware) which you can learn more about in the middleware docs. 63 | -------------------------------------------------------------------------------- /website/docs/core/routing.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: routing 3 | title: Routing 4 | --- 5 | 6 | ## Introduction 7 | 8 | **Please note that routing is environment specific. The details documented below only apply to [server mode](introduction/server-vs-serverless.md) since serverless environments will have their own custom routing** 9 | 10 | ## Introduction 11 | 12 | Under the hood, light uses [find-my-way](https://github.com/delvedor/find-my-way) to route in server mode. find-my-way turned out to be one of the fastest routers available while allowing for advanced features such as hot module reloading. Reading the find-my-way documentation in conjunction with this guide may help you understand light's router better. 13 | 14 | ## Automatic Routing 15 | 16 | When in server mode, light will try to guess the route based on its location in the directory. It is very similar to how [Next.js](https://nextjs.org/docs/routing/introduction) does its routing. Any file that ends with `index.js` will be collapsed to the root. So for example, the route `routes/users/index.js` will be treated as `/users`. All other routes will follow the system path. For example creating a file in `routes/posts/new.js` will yield the route `/posts/new`. 17 | 18 | Additionally, to support dynamic urls such as `/users/:username`, simply create a file called `[username].js` in the `users` folder. You can then use the `params` in the Context to fetch the username, [detailed here](core/params.mdx). 19 | -------------------------------------------------------------------------------- /website/docs/core/testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: testing 3 | title: Testing 4 | --- 5 | 6 | ## Introduction 7 | 8 | Light comes with an easy way to test your routes that is compatible with ava, jest and other testing frameworks. Light exports a `createTest` function which generates a server for you containing all of the routes. You can then use that server to start and test it, or you can plug it into a library such as [`supertest`](https://github.com/visionmedia/supertest) to test it. 9 | 10 | `createTest` returns an object with the keys `server` and `router` which you can use. The server is an HTTP server, and the `router` is a find-my-way route object which you can use to insert more routes if you need. 11 | 12 | ## Example 13 | 14 | ```js {4} title="index.test.js" 15 | const supertest = require('supertest'); 16 | const { createTest } = require('light'); 17 | 18 | const { server } = createTest(); 19 | 20 | it('returns JSON', async () => { 21 | const result = await supertest(server).get('/'); 22 | expect(result).toMatchObject({ 23 | hello: 'world', 24 | }); 25 | }); 26 | ``` 27 | -------------------------------------------------------------------------------- /website/docs/deploy/aws-lambda.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: aws-lambda 3 | title: AWS Lambda 4 | --- 5 | 6 | ## Introduction 7 | 8 | TODO: coming soon. We have a guide on [netlify](deploy/netlify.md) which also runs on AWS. 9 | -------------------------------------------------------------------------------- /website/docs/deploy/azure-functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: azure-functions 3 | title: Azure Functions 4 | --- 5 | 6 | ## Introduction 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/deploy/google-cloud-functions.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: google-cloud-functions 3 | title: Google Cloud Functions 4 | --- 5 | 6 | ## Introduction 7 | 8 | TODO: coming soon 9 | -------------------------------------------------------------------------------- /website/docs/deploy/heroku.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: heroku 3 | title: Heroku 4 | --- 5 | 6 | ## Introduction 7 | 8 | Heroku is an extremely popular web hosting platform that makes it as easy as a `git push` to deploy your code online. Light works well in Heroku with [server mode](deploy/server.md) enabled and is lightning fast even with Heroku's cold boots on the free tier. 9 | 10 | ## Setup 11 | 12 | This guide assumes that you have a heroku account set up and have already created a project on their website. Additionally, you need to have the Heroku CLI installed and logged in. If you have not already, follow the [getting started](introduction/getting-started.mdx) guide to get your app up and running and initialize a git repository with `git init`. 13 | 14 | Then add the following start script to your `package.json` so that Heroku knows how to start the production server. 15 | 16 | ```javascript 17 | { 18 | // ... 19 | "scripts": { 20 | "start": "light start" 21 | } 22 | // ... 23 | } 24 | ``` 25 | 26 | Then just commit, add your heroku project repo, and push! 27 | 28 | ```bash 29 | git add . 30 | git commit -m "initial commit" 31 | heroku git:remote -a light-example 32 | git push heroku master 33 | ``` 34 | 35 | Once you have pushed your code, Heroku will automatically detect that this is a `node`/`light` project and deploy it accordingly. 36 | 37 | For additional information, check out the light CLI options with `light start -h` and visit the [Heroku documentation](https://devcenter.heroku.com/categories/nodejs-support) for environment and other configuration options. 38 | -------------------------------------------------------------------------------- /website/docs/deploy/netlify.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: netlify 3 | title: Netlify 4 | --- 5 | 6 | ## Introduction 7 | 8 | Netlify is an extremely popular static website host, following the JAM stack principle. While their main focus is to build and host static content, they have released a lambda service called functions which allows you to run endpoints that have the same signature as AWS Lambda functions. The benefit of using Netlify is having quick and automatic deployments which propagate through Netlify's CDN all triggered with a simple `git push`. 9 | 10 | **NOTE: Netlify does not support functions in subdirectories! This means if you have a route `routes/hello/world.js`, it will not work.** See this [GitHub issue](https://github.com/netlify/netlify-lambda/issues/90) for more details. 11 | 12 | ## Setup 13 | 14 | This guide assumes that you have already set up a Netlify account, and a GitHub repository. 15 | 16 | Before you can deploy, you must first populate your git repository. Follow the [getting started](introduction/getting-started.mdx) guide to build your initial app, and verify everything is working with `npm run dev`. Once you have that set up, add a `netlify.toml` file that contains the path to the routes directory. 17 | 18 | ```text 19 | [build] 20 | command = "npm install" 21 | functions = "routes" 22 | ``` 23 | 24 | That's all you need in terms of code! Now head over to Netlify's website and click the "New Site From Git" button. Follow the steps to connect your GitHub account to Netlify and add your GitHub repo. Once you get to the final step, just leave the pre-filled data as is and press deploy. **This will deploy successfully, BUT your endpoints will not work.** Why is that? Well, light does not know which environment it needs to transform to. To set this up, open the settings page (on the top), go to the "Build and Deploy" section in the sidebar, and click "Environments" in the sidebar. Click "Edit Variables", and add a new environment variable which sets `LIGHT_ENVIRONMENT` to `netlify`. The end result should look like this. 25 | 26 | ![environment settings in netlify](/img/netlify/env.png) 27 | 28 | Press save to save your changes. Finally, to update your function to use this environment variable, you must go to the "Deploys" page at the top, and press "Trigger Deploy", and "Deploy Site". 29 | 30 | ![trigger deploy](/img/netlify/trigger-deploy.png) 31 | 32 | That's it! Your functions will now be deployed and ready to use! 33 | 34 | **NOTE**: Netlify uses the file system as the router, so you will not be able to use dynamic routes such as `/users/:USERNAME`, and routes such as `index` **will not** be mapped to `/`. 35 | -------------------------------------------------------------------------------- /website/docs/deploy/runkit.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: runkit 3 | title: Runkit 4 | --- 5 | 6 | ## Introduction 7 | 8 | RunKit is a fun and dynamic website which lets you prototype your applications. With their support for [endpoints](https://runkit.com/docs/endpoint) and light's flexibility, you can easily run the framework on RunKit. As you have probably noticed, light's docs makes extensive use of RunKit to provide live demos. 9 | 10 | ## Usage 11 | 12 | Simply create a new notebook and add the following code. 13 | 14 | import Embed from 'react-runkit'; 15 | 16 | 'hello world!');\n 20 | module.exports = route;`} /> 21 | 22 | Then click the "run" button. It should print `Object {endpoint: function()}`. If you get that, then you are all set. Press the little "endpoint" button underneath the title to see your project live. 23 | 24 | A demo of this functionality can be seen on the [home page](/). 25 | -------------------------------------------------------------------------------- /website/docs/deploy/server.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: server 3 | title: Server 4 | --- 5 | 6 | ## Introduction 7 | 8 | Running your application in server mode will give you many benefits such as packaging the application into a docker container, or making use of websockets. Running your light app in server mode will cause it to work exactly in dev mode except for the pretty error handling, and [HMR](core/hot-module-reloading.md). 9 | 10 | ## Setup 11 | 12 | Simply add the `light start` command to your package.json 13 | 14 | ```javascript 15 | { 16 | // ... 17 | "scripts": { 18 | "start": "light start" 19 | } 20 | // ... 21 | } 22 | ``` 23 | 24 | ## Usage 25 | 26 | You can see the options that light provides by running `light start -h`. 27 | -------------------------------------------------------------------------------- /website/docs/deploy/vercel.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: vercel 3 | title: Vercel Now 4 | --- 5 | 6 | ## Introduction 7 | 8 | Now is a new serverless platform provided by Vercel. Their aim is to make serverless deployments easy and hassle free. Fortunately light works well with Now with a little bit of configuration! 9 | 10 | ## Setup 11 | 12 | All data required to configure the Now platform is stored in a `now.json` file. 13 | 14 | ```javascript 15 | { 16 | "version": 2, 17 | "name": "my-light-project", 18 | "builds": [{ "src": "routes/**/*.js", "use": "@now/node" }], 19 | "routes": [ 20 | { "src": "/", "dest": "routes/index.js" }, 21 | { "src": "/(.*)", "dest": "routes/$1.js" } 22 | ], 23 | "env": { 24 | "NODE_ENV": "production", 25 | "LIGHT_ENV": "now" 26 | } 27 | } 28 | ``` 29 | 30 | Once you save the file in the root folder, all you need to do is configure your git repository to deploy. If you have not already, see the [guides on how to set that up](https://vercel.com/docs/v2/introduction). See the [docs for serverless functions](https://vercel.com/docs/v2/serverless-functions/introduction) to see more information on how it works. 31 | 32 | **NOTE**: The `routes` configuration provided above is very basic. You will need to configure it to account for all of your routes 33 | -------------------------------------------------------------------------------- /website/docs/introduction/getting-started.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | id: getting-started 3 | title: Getting Started 4 | sidebar_label: Getting Started 5 | --- 6 | 7 | :::caution 8 | Light is currently in development! Please note there may be breaking changes in between minor and beta versions! We will adhere to semantic versioning starting with v2.0.0 9 | ::: 10 | 11 | Getting started is quick and easy! This guide assumes you are running the latest LTS version of node. There is also a live example at the bottom if you want to try out light without setting it up locally! 12 | 13 | ## Install 14 | 15 | Initialize a new repository with `npm init`. Then install light. 16 | 17 | ```bash 18 | npm install light 19 | ``` 20 | 21 | Then add the following scripts to your `package.json`. 22 | 23 | ```json 24 | { 25 | // ... 26 | "scripts": { 27 | "start": "light start", 28 | "dev": "light dev" 29 | } 30 | // ... 31 | } 32 | ``` 33 | 34 | ## Usage 35 | 36 | Once you have installed light, all `.ts` and `.js` files under the `routes` directory will automatically be imported. Typescript will be automatically run/compiled if there is a `tsconfig.json` in the root directory. Additionally, all files that end in `.test.(t|j)s` and files in `__tests__` folders will be ignore. 37 | 38 | To get started, lets populate `routes/index.js`. Please note we use [Next.js style routing](https://nextjs.org/docs/routing/introduction). You can check out the routing docs on the left for more information. 39 | 40 | ```js 41 | const { createRoute } = require('light'); 42 | const { route, GET } = createRoute(); 43 | 44 | GET(() => { 45 | return { 46 | hello: 'world', 47 | }; 48 | }); 49 | 50 | module.exports = route; 51 | ``` 52 | 53 | This is probably different that what you are used to with `express`, `koa`, `hapi`, etc. There are a few interesting parts to this file. The `createRoute` function is the core of light and it returns an object containing `ROUTE`, `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, and a bunch of other HTTP methods. For each route you can add whatever methods you like to support. Any methods you do not define will return `404 Not Found`. At the bottom we export `route`. `route` is an object containing all of the information needed to execute your code. If the server is started with the CLI, it will transform that object and inject it in the router, but if it is run in a serverless environment, it will transform it into a request handler. 54 | 55 | Once you are done editing the file, run `npm run dev` to start the server with hot module reloading. If you did everything right, your terminal should output something similar to this. 56 | 57 | ``` 58 | [ start ] 🔥 igniting the server 🔥 59 | [ listening ] on port 3000 60 | [ hmr ] starting the hot reloader 61 | [ hmr ] watching for changes 62 | ``` 63 | 64 | ## Conclusion 65 | 66 | Phew, that was a lot. Don't worry though, you just learnt about 80% of light! It's really that simple. You now have a dev server that 67 | 68 | - hot swaps any code you change without restarting the server 69 | - can support many different serverless and hosting platforms 70 | - has very little magic behind the scenes, what you see in a route is what you get 71 | 72 | Feel free to continue with the guides in the sidebar to understand more of the framework! 73 | 74 | ## Live Example 75 | 76 | If you want to mess around with the example provided above without setting it up on your computer, you can try it out on RunKit! Just edit the code below and click the URL in the bottom right. 77 | 78 | import Embed from 'react-runkit'; 79 | 80 | { 86 | return { 87 | hello: 'world', 88 | }; 89 | });\n 90 | module.exports = route;`} 91 | /> 92 | -------------------------------------------------------------------------------- /website/docs/introduction/server-vs-serverless.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: server-vs-serverless 3 | title: Server vs Serverless 4 | --- 5 | 6 | ## Introduction 7 | 8 | You've probably heard of both of these terms, but what exactly do they mean? And why would I use one over the other? The point of this guide isn't to convince you to use one or the other but just to help you pick. **Light supports both methods** really well and has been battle tested in both environments. 9 | 10 | ## Server 11 | 12 | This is your typical server. You can spawn as many of these as you want, on as many servers as you want and load balance them. You can package these in docker containers and deploy them into a Kubernetes cluster. It is the de-facto way host your applications and allows for very fine grained control over your deployments. 13 | 14 | However, all of this comes with an overhead. You need to either learn dev-ops yourself or hire someone to do it for you. You also need to purchase servers around the world and worry about proxying requests properly. 15 | 16 | Running light in server mode works just as you would expect. A quick light start or npm start is all you need to boot up your HTTP server. You can also pass in addition configuration options as you need. 17 | 18 | Additionally, there are more features that you have and also are missing in server mode. 19 | 20 | | Pros | Cons | 21 | | :--- | :--- | 22 | | Control over deployments | Expensive | 23 | | Scale at your own pace | Manage all scaling yourself | 24 | | Web-sockets support | No fault tolerance \(by default\) | 25 | | Generally faster | | 26 | 27 | ## Serverless 28 | 29 | **NOTE: In development, you will have to use server mode to start a server and test your endpoints, but you can deploy to serverless environments with absolutely no changes to your code!** 30 | 31 | Serverless is a new term that many companies such as Vercel and AWS are pushing. The main selling point is to fix some of the cons of regular servers. As your website becomes more and more popular, you will have to worry more and more about making sure your application is available. Serverless aims to fix that by having endpoints be simple "functions". When you deploy your functions to any of the providers, your simple functions are propagated throughout the provider's network and highly available. Because of this, you don't have to worry about scaling or load balancing. All of it is done by the hosting provider. 32 | 33 | Some of the downsides include no websocket support, per execution costs (which may be very expensive if you handle millions of requests), and cold starts. Due to the sheer number of functions websites like AWS store, your function will be "cold" most of the time, and when a request is made, there is additional overhead involved in fetching the function from a datastore and running it. This can result in anywhere from 10ms-500ms of additional overhead. In addition, when you are using databases, every time your function is run, it has to reconnect to the external database. 34 | 35 | The point of light is to allow you to write code that works in both environments. That way you do not have to worry about switching around when required. If one day you can't handle the number of requests you are getting, you can switch to serverless in just minutes instead of days. Or if one day Serverless is becomes too expensive, you can spin up your own servers in minutes instead of days. 36 | 37 | Serverless has its own benefits and drawbacks and you should only use it if it is right for your application. 38 | 39 | | Pros | Cons | 40 | | :--- | :--- | 41 | | Generally cheaper | Cold starts will result in slow responses | 42 | | Instant scaling | No control over deployments | 43 | | Fault tolerant \(one crash has no affect\) | No web-sockets support | 44 | 45 | 46 | ## Why Should I Use Light Instead of the Serverless Framework 47 | 48 | Good question. The serverless framework is much more robust and feature packed, but sometimes you don't need that. The promise of light is to be **light**weight, easy to work with, \(almost\) zero configuration, and be developer friendly. If you need the robustness that the serverless framework provides, please use that instead. The purpose behind light was to build a framework that works in any environment so you don't have to worry about dev-ops. As a result the routes are explicit and simple. 49 | -------------------------------------------------------------------------------- /website/docs/third-party/apollo.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: apollo 3 | title: Apollo 4 | --- 5 | 6 | TODO: coming soon 7 | -------------------------------------------------------------------------------- /website/docs/third-party/ava.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: ava 3 | title: Ava 4 | --- 5 | 6 | TODO: coming soon 7 | -------------------------------------------------------------------------------- /website/docs/third-party/jest.md: -------------------------------------------------------------------------------- 1 | --- 2 | id: jest 3 | title: Jest 4 | --- 5 | 6 | TODO: coming soon 7 | -------------------------------------------------------------------------------- /website/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'light.js by ludicrous', 3 | tagline: 'a next-gen node framework', 4 | url: 'https://www.lightjs.dev', 5 | baseUrl: '/', 6 | onBrokenLinks: 'throw', 7 | onBrokenMarkdownLinks: 'warn', 8 | favicon: 'img/favicon.png', 9 | organizationName: 'ludicroushq', // Usually your GitHub org/user name. 10 | projectName: 'light', // Usually your repo name. 11 | plugins: ['docusaurus-tailwindcss-loader'], 12 | scripts: ['https://embed.runkit.com'], 13 | themeConfig: { 14 | algolia: { 15 | apiKey: process.env.ALGOLIA_API_KEY, 16 | appId: process.env.ALGOLIA_APP_ID, 17 | }, 18 | colorMode: { 19 | defaultMode: 'light', 20 | disableSwitch: true, 21 | }, 22 | navbar: { 23 | title: 'light.js', 24 | logo: { 25 | alt: 'light', 26 | src: 'img/light.svg', 27 | }, 28 | items: [ 29 | { 30 | to: 'docs/introduction/getting-started', 31 | activeBaseRegex: 'docs/(?!api).*', 32 | label: 'Docs', 33 | position: 'right', 34 | }, 35 | { 36 | to: 'docs/api/exported/create-route', 37 | activeBasePath: 'docs/api', 38 | label: 'API', 39 | position: 'right', 40 | }, 41 | { to: 'blog', label: 'Blog', position: 'right' }, 42 | { 43 | href: 'https://github.com/ludicroushq/light', 44 | label: 'GitHub', 45 | position: 'right', 46 | }, 47 | ], 48 | }, 49 | footer: { 50 | style: 'dark', 51 | links: [ 52 | { 53 | title: 'Documentation', 54 | items: [ 55 | { 56 | label: 'Getting Started', 57 | to: 'docs/introduction/getting-started', 58 | }, 59 | { 60 | label: 'Core Concepts', 61 | to: 'docs/core/routes', 62 | }, 63 | { 64 | label: 'Deploy', 65 | to: 'docs/deploy/vercel', 66 | }, 67 | { 68 | label: 'Third Party', 69 | to: 'docs/third-party/apollo', 70 | }, 71 | { 72 | label: 'API', 73 | to: 'docs/api/exported/create-route', 74 | }, 75 | ], 76 | }, 77 | { 78 | title: 'Community', 79 | items: [ 80 | { 81 | label: 'Discussions', 82 | href: 'https://github.com/ludicroushq/light/discussions', 83 | }, 84 | { 85 | label: 'Issues', 86 | href: 'https://github.com/ludicroushq/light/issues', 87 | }, 88 | { 89 | label: 'Discord', 90 | href: 'https://discord.gg/A6m2QmjrWY', 91 | }, 92 | ], 93 | }, 94 | { 95 | title: 'More', 96 | items: [ 97 | { 98 | label: 'Light.js Blog', 99 | to: 'blog', 100 | }, 101 | { 102 | label: 'GitHub', 103 | href: 'https://github.com/facebook/docusaurus', 104 | }, 105 | ], 106 | }, 107 | { 108 | title: 'About Ludicrous', 109 | items: [ 110 | { 111 | label: 'Home', 112 | to: 'https://www.ludicroushq.com', 113 | }, 114 | { 115 | label: 'Blog', 116 | to: 'https://blog.ludicroushq.com', 117 | }, 118 | { 119 | label: 'Twitter', 120 | href: 'https://twitter.com/ludicroushq', 121 | }, 122 | ], 123 | }, 124 | ], 125 | copyright: `Copyright © ${new Date().getFullYear()} ludicrous LLC.`, 126 | }, 127 | }, 128 | presets: [ 129 | [ 130 | '@docusaurus/preset-classic', 131 | { 132 | docs: { 133 | sidebarPath: require.resolve('./sidebars.js'), 134 | // Please change this to your repo. 135 | // editUrl: 'https://github.com/facebook/docusaurus/edit/master/website/', 136 | }, 137 | blog: { 138 | showReadingTime: true, 139 | // Please change this to your repo. 140 | // editUrl: 'https://github.com/facebook/docusaurus/edit/master/website/blog/', 141 | }, 142 | theme: { 143 | customCss: require.resolve('./src/css/custom.css'), 144 | }, 145 | }, 146 | ], 147 | ], 148 | }; 149 | -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "serve": "docusaurus serve", 12 | "clear": "docusaurus clear", 13 | "spellcheck": "cspell 'src/**/*' 'docs/**/*'" 14 | }, 15 | "dependencies": { 16 | "@docusaurus/core": "^2.0.0-beta.14", 17 | "@docusaurus/preset-classic": "^2.0.0-beta.14", 18 | "@heroicons/react": "^1.0.5", 19 | "@mdx-js/react": "^1.6.22", 20 | "@tailwindcss/postcss7-compat": "^2.2.17", 21 | "clsx": "^1.1.1", 22 | "docusaurus-tailwindcss-loader": "file:plugins/postcss-tailwindcss-loader", 23 | "postcss-import": "^14.0.2", 24 | "postcss-nested": "^5.0.6", 25 | "react": "^17.0.2", 26 | "react-dom": "^17.0.2", 27 | "react-runkit": "^0.9.0" 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.5%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | }, 41 | "devDependencies": { 42 | "@docusaurus/module-type-aliases": "^2.0.0-beta.14", 43 | "@tsconfig/docusaurus": "^1.0.4", 44 | "@types/react": "^17.0.38", 45 | "@types/react-helmet": "^6.1.5", 46 | "@types/react-router-dom": "^5.3.3", 47 | "autoprefixer": "^10.4.2", 48 | "cspell": "^5.15.2", 49 | "postcss": "^8.4.5", 50 | "postcss-preset-env": "^7.2.3", 51 | "tailwindcss": "^3.0.15", 52 | "typescript": "^4.5.4" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /website/plugins/postcss-tailwindcss-loader/index.js: -------------------------------------------------------------------------------- 1 | module.exports = function (context, options) { 2 | return { 3 | name: 'postcss-tailwindcss-loader', 4 | configurePostCss(postcssOptions) { 5 | postcssOptions.plugins.push( 6 | require('postcss-import'), 7 | require('tailwindcss'), 8 | require('postcss-nested'), 9 | require('postcss-preset-env')({ 10 | autoprefixer: { 11 | flexbox: 'no-2009', 12 | }, 13 | stage: 4, 14 | }), 15 | ); 16 | return postcssOptions; 17 | }, 18 | }; 19 | }; 20 | -------------------------------------------------------------------------------- /website/plugins/postcss-tailwindcss-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-tailwindcss-loader", 3 | "private": true 4 | } 5 | -------------------------------------------------------------------------------- /website/sidebars.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | docs: { 3 | Introduction: ['introduction/getting-started', 'introduction/server-vs-serverless'], 4 | 'Core Concepts': [ 5 | 'core/routes', 6 | 'core/context', 7 | 'core/routing', 8 | 'core/middleware', 9 | 'core/connect', 10 | 'core/logging', 11 | 'core/params', 12 | 'core/query', 13 | 'core/body-parsing', 14 | 'core/error-handling', 15 | 'core/testing', 16 | 'core/hot-module-reloading', 17 | ], 18 | Deploy: [ 19 | 'deploy/vercel', 20 | 'deploy/runkit', 21 | 'deploy/netlify', 22 | 'deploy/heroku', 23 | 'deploy/server', 24 | 'deploy/aws-lambda', 25 | 'deploy/google-cloud-functions', 26 | 'deploy/azure-functions', 27 | ], 28 | 'Third Party': ['third-party/apollo', 'third-party/jest', 'third-party/ava'], 29 | }, 30 | api: { 31 | 'Exported Functions': [ 32 | 'api/exported/create-route', 33 | 'api/exported/create-server', 34 | 'api/exported/create-test', 35 | 'api/exported/logger', 36 | ], 37 | Context: [ 38 | 'api/context/req', 39 | 'api/context/res', 40 | 'api/context/buffer', 41 | 'api/context/text', 42 | 'api/context/json', 43 | 'api/context/send', 44 | 'api/context/send-error', 45 | 'api/context/create-error', 46 | 'api/context/use-params', 47 | 'api/context/use-query', 48 | ], 49 | }, 50 | }; 51 | -------------------------------------------------------------------------------- /website/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /* stylelint-disable docusaurus/copyright-header */ 2 | /** 3 | * Any CSS included here will be global. The classic template 4 | * bundles Infima by default. Infima is a CSS framework designed to 5 | * work well for content-centric websites. 6 | */ 7 | 8 | /* You can override the default Infima variables here. */ 9 | :root { 10 | --ifm-color-primary: #6366f1; 11 | --ifm-color-primary-dark: #4f46e5; 12 | --ifm-color-primary-darker: #4338ca; 13 | --ifm-color-primary-darkest: #3730a3; 14 | --ifm-color-primary-light: #818cf8; 15 | --ifm-color-primary-lighter: #a5b4fc; 16 | --ifm-color-primary-lightest: #c7d2fe; 17 | --ifm-code-font-size: 95%; 18 | } 19 | 20 | .docusaurus-highlight-code-line { 21 | background-color: rgb(72, 77, 91); 22 | display: block; 23 | margin: 0 calc(-1 * var(--ifm-pre-padding)); 24 | padding: 0 var(--ifm-pre-padding); 25 | } 26 | 27 | #tailwind { 28 | @tailwind base; 29 | @tailwind components; 30 | } 31 | @tailwind utilities; 32 | -------------------------------------------------------------------------------- /website/src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Layout from '@theme/Layout'; 3 | import Hero from '../routes/index/Hero'; 4 | import UseAnywhere from '../routes/index/UseAnywhere'; 5 | import Features from '../routes/index/Features'; 6 | import CTA from '../routes/index/CTA'; 7 | import Runkit from '../routes/index/Runkit'; 8 | import Stats from '../routes/index/Stats'; 9 | // import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; 10 | // import clsx from 'clsx'; 11 | // import Link from '@docusaurus/Link'; 12 | // import useBaseUrl from '@docusaurus/useBaseUrl'; 13 | 14 | function Home() { 15 | // const context = useDocusaurusContext(); 16 | // const { siteConfig = {} } = context; 17 | return ( 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | ); 29 | } 30 | 31 | export default Home; 32 | -------------------------------------------------------------------------------- /website/src/routes/index/CTA.tsx: -------------------------------------------------------------------------------- 1 | import Link from '@docusaurus/Link'; 2 | import React from 'react'; 3 | 4 | export default function CTA(props) { 5 | return ( 6 |
7 |
8 |

9 | Ready to dive in? 10 | Check out the docs. 11 |

12 |
13 | 21 |
22 | 26 | Get started 27 | 28 |
29 |
30 |
31 |
32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /website/src/routes/index/Features.tsx: -------------------------------------------------------------------------------- 1 | import React, { ComponentType, FC, ReactComponentElement, ReactNode } from 'react'; 2 | import { CodeIcon } from '@heroicons/react/solid'; 3 | import { LinkIcon, TerminalIcon } from '@heroicons/react/outline'; 4 | 5 | function Item({ 6 | title, 7 | description, 8 | Icon, 9 | }: { 10 | title: string; 11 | description: string; 12 | Icon: typeof Code | typeof LinkOutline | typeof TerminalOutline; 13 | }) { 14 | return ( 15 |
16 |
17 | 18 |
19 |
20 |
{title}
21 |
{description}
22 |
23 |
24 | ); 25 | } 26 | 27 | export default function Features(props) { 28 | return ( 29 |
30 |
31 |

A better way to send money.

32 |
33 | 38 | 43 | 48 |
49 |
50 |
51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /website/src/routes/index/Hero.tsx: -------------------------------------------------------------------------------- 1 | import Link from '@docusaurus/Link'; 2 | import React from 'react'; 3 | 4 | export default function Hero() { 5 | return ( 6 |
7 |
8 |
9 |

10 | light.js 11 |

12 |

13 | The Node Framework for the Next Generation. 14 |

15 |

16 | Light is a zero-configuration node server with sane defaults and optimal performance. It 17 | ships with all of modern tools by default: hooks-style endpoints, typescript support, 18 | and file-system based routing. 19 |

20 | No Boilerplate, No Opinions, No Bulls**t. 21 |

22 |

23 |
24 | 28 | GitHub 29 | 30 | 34 | Get Started 35 | 36 |
37 |
38 |
39 |
40 | ); 41 | } 42 | -------------------------------------------------------------------------------- /website/src/routes/index/Runkit.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Embed from 'react-runkit'; 3 | 4 | const source = `// let light know that we are using it in Runkit before importing it 5 | process.env.LIGHT_ENV = 'runkit'; 6 | const cors = require('cors'); 7 | const { createRoute, withConnect } = require('light'); 8 | 9 | const { route, GET, POST, useMiddleware } = createRoute(); 10 | 11 | /* 12 | light uses a unique kind of middleware, but it also provides 13 | a wrapper for connect (express) and koa style middleware 14 | */ 15 | useMiddleware(withConnect(cors())) 16 | 17 | // define handlers for the methods you need 18 | GET(() => { 19 | return { 20 | hello: 'world', 21 | }; 22 | }); 23 | 24 | // finally we need to export our route for the world to listen! 25 | module.exports = route;`; 26 | 27 | export default function Runkit(props) { 28 | return ( 29 |
30 |
31 |
32 |
33 |

Give it a shot

34 |

35 | Since light is flexible enough to run in many different environments, you can play 36 | with it right here in the browser with Runkit! 37 |

38 |
39 |
40 | 41 |
42 |
43 |
44 |
45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /website/src/routes/index/Stats.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Stats(props) { 4 | return ( 5 |
6 |
7 |
8 |

9 | A Reliable Framework 10 |

11 |

12 | We do a lot of things behind the scenes to ensure that Light is bug free. 13 |

14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | Type Safe 25 |
26 |
Fully
27 |
28 |
29 |
30 | Code Coverage 31 |
32 |
100%
33 |
34 |
35 |
36 | Defaults 37 |
38 |
Sane
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /website/src/routes/index/UseAnywhere.tsx: -------------------------------------------------------------------------------- 1 | import { CheckIcon, ClockIcon } from '@heroicons/react/solid'; 2 | import React, { ReactNode } from 'react'; 3 | 4 | function Item({ 5 | name, 6 | description, 7 | comingSoon = false, 8 | }: { 9 | name: string; 10 | description: ReactNode; 11 | comingSoon?: boolean; 12 | }) { 13 | return ( 14 |
15 | {comingSoon ? ( 16 | 17 | ) : ( 18 | 19 | )} 20 |
21 |
{name}
22 |
{description}
23 |
24 |
25 | ); 26 | } 27 | 28 | export default function UseAnywhere(props) { 29 | return ( 30 |
31 |
32 |
33 |

34 | Without changing your code, 35 |

36 |

Use Anywhere

37 |

38 | Light can run as a normal server, or transform itself to work in a variety of different 39 | serverless environments and frameworks without any code changes. 40 |

41 |
42 |
43 |
44 | 48 | 52 | 56 | 60 | 64 | 68 | 69 | 70 | 71 | 72 |
73 |
74 |
75 |
76 | ); 77 | } 78 | -------------------------------------------------------------------------------- /website/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ludicroushq/light/40e3c998cf4cc1ece85ddad7abf2c9397a721d5a/website/static/.nojekyll -------------------------------------------------------------------------------- /website/static/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ludicroushq/light/40e3c998cf4cc1ece85ddad7abf2c9397a721d5a/website/static/img/favicon.png -------------------------------------------------------------------------------- /website/static/img/hmr/connection-refused.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ludicroushq/light/40e3c998cf4cc1ece85ddad7abf2c9397a721d5a/website/static/img/hmr/connection-refused.png -------------------------------------------------------------------------------- /website/static/img/light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /website/static/img/netlify/env.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ludicroushq/light/40e3c998cf4cc1ece85ddad7abf2c9397a721d5a/website/static/img/netlify/env.png -------------------------------------------------------------------------------- /website/static/img/netlify/trigger-deploy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ludicroushq/light/40e3c998cf4cc1ece85ddad7abf2c9397a721d5a/website/static/img/netlify/trigger-deploy.png -------------------------------------------------------------------------------- /website/tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | purge: ['./src/**/*.html', './src/**/*.js', './src/**/*.tsx'], 3 | darkMode: false, 4 | important: '#tailwind', 5 | theme: { 6 | extend: {}, 7 | }, 8 | variants: { 9 | extend: {}, 10 | }, 11 | plugins: [], 12 | }; 13 | -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@tsconfig/docusaurus/tsconfig.json", 3 | "include": ["src/"] 4 | } 5 | --------------------------------------------------------------------------------