diff --git a/404.html b/404.html index 7a4e80b1..00354f15 100644 --- a/404.html +++ b/404.html @@ -12,13 +12,13 @@ - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/assets/js/2ab4562b.90c477f8.js b/assets/js/2ab4562b.19a1dc7c.js similarity index 97% rename from assets/js/2ab4562b.90c477f8.js rename to assets/js/2ab4562b.19a1dc7c.js index 76c499e4..90478bda 100644 --- a/assets/js/2ab4562b.90c477f8.js +++ b/assets/js/2ab4562b.19a1dc7c.js @@ -1 +1 @@ -"use strict";(self.webpackChunk_athenna_docs=self.webpackChunk_athenna_docs||[]).push([[9080],{3905:(e,t,r)=>{r.d(t,{Zo:()=>d,kt:()=>y});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},d=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=c(r),h=o,y=u["".concat(s,".").concat(h)]||u[h]||p[h]||i;return r?n.createElement(y,a(a({ref:t},d),{},{components:r})):n.createElement(y,a({ref:t},d))}));function y(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:o,a[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),o=(r(7294),r(3905));const i={title:"Directory Structure",sidebar_position:5,description:"Understand the directory structure of your project."},a="Directory Structure",l={unversionedId:"getting-started/directory-structure",id:"getting-started/directory-structure",title:"Directory Structure",description:"Understand the directory structure of your project.",source:"@site/docs/getting-started/directory-structure.mdx",sourceDirName:"getting-started",slug:"/getting-started/directory-structure",permalink:"/docs/getting-started/directory-structure",draft:!1,editUrl:"https://github.com/AthennaIO/Docs/tree/main/docs/getting-started/directory-structure.mdx",tags:[],version:"current",sidebarPosition:5,frontMatter:{title:"Directory Structure",sidebar_position:5,description:"Understand the directory structure of your project."},sidebar:"tutorialSidebar",previous:{title:"Configuration",permalink:"/docs/getting-started/configuration"},next:{title:"Architecture Concepts",permalink:"/docs/architecture-concepts"}},s={},c=[{value:"Default structure",id:"default-structure",level:2},{value:"The app directory",id:"the-app-directory",level:3},{value:"The bootstrap directory",id:"the-bootstrap-directory",level:3},{value:"The config directory",id:"the-config-directory",level:3},{value:"The database directory",id:"the-database-directory",level:3},{value:"The providers directory",id:"the-providers-directory",level:3},{value:"The routes directory",id:"the-routes-directory",level:3},{value:"The storage directory",id:"the-storage-directory",level:3},{value:"The tests directory",id:"the-tests-directory",level:3},{value:"Slim structure",id:"slim-structure",level:2},{value:"Do your own structure",id:"do-your-own-structure",level:2}],d={toc:c},u="wrapper";function p(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},d,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"directory-structure"},"Directory Structure"),(0,o.kt)("p",null,"Understand the directory structure of your project."),(0,o.kt)("admonition",{type:"important"},(0,o.kt)("p",{parentName:"admonition"},"We highly recommend you to use the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make"),"\ncommand to generate the files of your application. If\nusing this command, it will automatically generate the\nfile and register it wherever it is needed. Take as an example\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make:command command"),". First it will\ngenerate the file and then will register the command inside\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"commands")," map property of ",(0,o.kt)("inlineCode",{parentName:"p"},".athennarc.json")," file.")),(0,o.kt)("h2",{id:"default-structure"},"Default structure"),(0,o.kt)("h3",{id:"the-app-directory"},"The app directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"app")," directory contains the core code of your application.\nWe'll explore this directory in more detail soon. Almost all\nthe classes in your application will be in this directory."),(0,o.kt)("h3",{id:"the-bootstrap-directory"},"The bootstrap directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"bootstrap")," directory contains all of your application's\nbootstrap files. It's here that Athenna holds the ",(0,o.kt)("inlineCode",{parentName:"p"},"main.ts"),"\nfile that bootstrap the application using the ",(0,o.kt)("inlineCode",{parentName:"p"},"Ignite")," class."),(0,o.kt)("h3",{id:"the-config-directory"},"The config directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"config")," directory contains all of your application's\nconfiguration files. It's a great idea to read through all\nof these files and familiarize yourself with all the options\navailable to you."),(0,o.kt)("h3",{id:"the-database-directory"},"The database directory"),(0,o.kt)("p",null,"This directory does not exist by default, but will be created\nfor you if you execute the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"node artisan configure @athenna/database\n")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"database")," directory contains your database migrations,\nmodel factories, and seeds. If you wish, you may also use\nthis directory to hold an SQLite database."),(0,o.kt)("h3",{id:"the-providers-directory"},"The providers directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"providers")," directory contains all the service providers\nfor your application. Service providers bootstrap your\napplication by binding services in the service container,\nregistering events, or performing any other tasks to prepare\nyour application to run."),(0,o.kt)("h3",{id:"the-routes-directory"},"The routes directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"routes")," directory contains all the route definitions\nfor your application. By default, several route files are\nincluded with Athenna:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"http.ts")," file is where you will define the entry\npoint of your api using the Route facade that is provided\nby the HttpRouteProvider."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"console.ts")," file is where you will define the entry\npoint of your commands using the Artisan facade that is\nprovided by the ArtisanProvider.")),(0,o.kt)("admonition",{type:"important"},(0,o.kt)("p",{parentName:"admonition"},"As you may have noticed your project does not have the\n",(0,o.kt)("inlineCode",{parentName:"p"},"console.ts")," file. We only recommend using this file when\nyou don't want to use TypeScript in your application or\nwhen you want to add some personalized option of ",(0,o.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/commander"},"commander"),"\nto your command. Check the example:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-typescript"},"import { Artisan } from '@athenna/artisan'\n\nArtisan.route('hello', function (helloArg: string, options: { hello: string }) {\n console.log(helloArg)\n console.log(options.hello)\n}) // \ud83d\udc48 Artisan.route return an instance of Commander\n.argument('', 'Description for hello argument.')\n.option('--hello', 'Description for hello flag.')\n"))),(0,o.kt)("h3",{id:"the-storage-directory"},"The storage directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"storage")," directory contains your logs, file caches,\nfiles uploaded locally and other files generated by the\nframework. This directory is segregated into the following\ndirectories:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"app")," directory may be used to store any files\ngenerated by your application."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"framework")," directory is used to store framework\ngenerated files and caches."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"logs")," directory contains your application's log\nfiles.")),(0,o.kt)("h3",{id:"the-tests-directory"},"The tests directory"),(0,o.kt)("p",null,"You can create a test executing the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make:test"),"\ncommand. The ",(0,o.kt)("inlineCode",{parentName:"p"},"tests")," directory contains your unitary and E2E\ntests. Each test file name should always end with the word\nTest at the end. You may run your tests using the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan test"),"\ncommand."),(0,o.kt)("admonition",{type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"If your test file name does not end with ",(0,o.kt)("inlineCode",{parentName:"p"},"Test"),", it will\nbe ignored and the test class will not run. But, you can\ncustomize this behavior in the configure function of ",(0,o.kt)("a",{parentName:"p",href:"https://japa.dev/docs"},"Japa"),"\ninside your ",(0,o.kt)("inlineCode",{parentName:"p"},"Path.bootstrap('test.ts')")," file.")),(0,o.kt)("h2",{id:"slim-structure"},"Slim structure"),(0,o.kt)("p",null,"The slim project structure has only three folders when you\ncreate the project:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"bin")," directory is the same as ",(0,o.kt)("a",{parentName:"li",href:"/docs/getting-started/directory-structure#bootstrap"},"bootstrap"),"."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"src")," directory is used to store all the source code files of your applications."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"tests")," directory is the same as ",(0,o.kt)("a",{parentName:"li",href:"/docs/getting-started/directory-structure#tests"},"tests"),".")),(0,o.kt)("h2",{id:"do-your-own-structure"},"Do your own structure"),(0,o.kt)("p",null,"There are some files in your project that are crucial to\nkeep in certain places. Let's analyze some of them:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.bootstrap('main.ts')")," file is the entry point of the\n",(0,o.kt)("inlineCode",{parentName:"li"},"node artisan serve")," command. Every time that you run this\ncommand, Athenna will use this file to run your application."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.bootstrap('artisan.ts')")," file is the entry point of the\n",(0,o.kt)("inlineCode",{parentName:"li"},"artisan.js")," script."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"config")," path is where you are going to set up your\nconfiguration files. You can learn more about configuration\nfiles at ",(0,o.kt)("a",{parentName:"li",href:"https://athenna.io/docs/getting-started/configuration"},"the configuration documentation section"),"."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.routes('http.ts')")," file is where you are going to register\nyour Http server routes.")),(0,o.kt)("p",null,"Athenna is a framework with a lot of opinions, with predefined\nproject structures; it was built that way to make your life easier.\nBut speaking from developer to developer, we know how much fun it\nis to be able to have control over everything in your application,\nespecially the structure of your project \ud83d\ude0e."),(0,o.kt)("p",null,"With that in mind, Athenna was built in a fully configurable\nway. You can create your files and folders anywhere, even the\none that are crucial to keep in certain places."))}p.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunk_athenna_docs=self.webpackChunk_athenna_docs||[]).push([[9080],{3905:(e,t,r)=>{r.d(t,{Zo:()=>d,kt:()=>y});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},d=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},h=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=c(r),h=o,y=u["".concat(s,".").concat(h)]||u[h]||p[h]||i;return r?n.createElement(y,a(a({ref:t},d),{},{components:r})):n.createElement(y,a({ref:t},d))}));function y(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:o,a[1]=l;for(var c=2;c{r.r(t),r.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=r(7462),o=(r(7294),r(3905));const i={title:"Directory Structure",sidebar_position:5,description:"Understand the directory structure of your project."},a="Directory Structure",l={unversionedId:"getting-started/directory-structure",id:"getting-started/directory-structure",title:"Directory Structure",description:"Understand the directory structure of your project.",source:"@site/docs/getting-started/directory-structure.mdx",sourceDirName:"getting-started",slug:"/getting-started/directory-structure",permalink:"/docs/getting-started/directory-structure",draft:!1,editUrl:"https://github.com/AthennaIO/Docs/tree/main/docs/getting-started/directory-structure.mdx",tags:[],version:"current",sidebarPosition:5,frontMatter:{title:"Directory Structure",sidebar_position:5,description:"Understand the directory structure of your project."},sidebar:"tutorialSidebar",previous:{title:"Configuration",permalink:"/docs/getting-started/configuration"},next:{title:"Architecture Concepts",permalink:"/docs/architecture-concepts"}},s={},c=[{value:"Default structure",id:"default-structure",level:2},{value:"The app directory",id:"the-app-directory",level:3},{value:"The bootstrap directory",id:"the-bootstrap-directory",level:3},{value:"The config directory",id:"the-config-directory",level:3},{value:"The database directory",id:"the-database-directory",level:3},{value:"The providers directory",id:"the-providers-directory",level:3},{value:"The routes directory",id:"the-routes-directory",level:3},{value:"The storage directory",id:"the-storage-directory",level:3},{value:"The tests directory",id:"the-tests-directory",level:3},{value:"Slim structure",id:"slim-structure",level:2},{value:"Do your own structure",id:"do-your-own-structure",level:2}],d={toc:c},u="wrapper";function p(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},d,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h1",{id:"directory-structure"},"Directory Structure"),(0,o.kt)("p",null,"Understand the directory structure of your project."),(0,o.kt)("admonition",{type:"important"},(0,o.kt)("p",{parentName:"admonition"},"We highly recommend you to use the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make"),"\ncommand to generate the files of your application. If\nusing this command, it will automatically generate the\nfile and register it wherever it is needed. Take as an example\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make:command command"),". First it will\ngenerate the file and then will register the command inside\nthe ",(0,o.kt)("inlineCode",{parentName:"p"},"commands")," map property of ",(0,o.kt)("inlineCode",{parentName:"p"},".athennarc.json")," file.")),(0,o.kt)("h2",{id:"default-structure"},"Default structure"),(0,o.kt)("h3",{id:"the-app-directory"},"The app directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"app")," directory contains the core code of your application.\nWe'll explore this directory in more detail soon. Almost all\nthe classes in your application will be in this directory."),(0,o.kt)("h3",{id:"the-bootstrap-directory"},"The bootstrap directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"bootstrap")," directory contains all of your application's\nbootstrap files. It's here that Athenna holds the ",(0,o.kt)("inlineCode",{parentName:"p"},"main.ts"),"\nfile that bootstrap the application using the ",(0,o.kt)("inlineCode",{parentName:"p"},"Ignite")," class."),(0,o.kt)("h3",{id:"the-config-directory"},"The config directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"config")," directory contains all of your application's\nconfiguration files. It's a great idea to read through all\nof these files and familiarize yourself with all the options\navailable to you."),(0,o.kt)("h3",{id:"the-database-directory"},"The database directory"),(0,o.kt)("p",null,"This directory does not exist by default, but will be created\nfor you if you execute the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-bash"},"node artisan configure @athenna/database\n")),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"database")," directory contains your database migrations,\nmodel factories, and seeds. If you wish, you may also use\nthis directory to hold an SQLite database."),(0,o.kt)("h3",{id:"the-providers-directory"},"The providers directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"providers")," directory contains all the service providers\nfor your application. Service providers bootstrap your\napplication by binding services in the service container,\nregistering events, or performing any other tasks to prepare\nyour application to run."),(0,o.kt)("h3",{id:"the-routes-directory"},"The routes directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"routes")," directory contains all the route definitions\nfor your application. By default, several route files are\nincluded with Athenna:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"http.ts")," file is where you will define the entry\npoint of your api using the Route facade that is provided\nby the HttpRouteProvider."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"console.ts")," file is where you will define the entry\npoint of your commands using the Artisan facade that is\nprovided by the ArtisanProvider.")),(0,o.kt)("admonition",{type:"important"},(0,o.kt)("p",{parentName:"admonition"},"As you may have noticed your project does not have the\n",(0,o.kt)("inlineCode",{parentName:"p"},"console.ts")," file. We only recommend using this file when\nyou don't want to use TypeScript in your application or\nwhen you want to add some personalized option of ",(0,o.kt)("a",{parentName:"p",href:"https://www.npmjs.com/package/commander"},"commander"),"\nto your command. Check the example:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-typescript"},"import { Artisan } from '@athenna/artisan'\n\nArtisan.route('hello', function (helloArg: string, options: { hello: string }) {\n console.log(helloArg)\n console.log(options.hello)\n}) // \ud83d\udc48 Artisan.route return an instance of Commander\n.argument('', 'Description for hello argument.')\n.option('--hello', 'Description for hello flag.')\n"))),(0,o.kt)("h3",{id:"the-storage-directory"},"The storage directory"),(0,o.kt)("p",null,"The ",(0,o.kt)("inlineCode",{parentName:"p"},"storage")," directory contains your logs, file caches,\nfiles uploaded locally and other files generated by the\nframework. This directory is segregated into the following\ndirectories:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"app")," directory may be used to store any files\ngenerated by your application."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"framework")," directory is used to store framework\ngenerated files and caches."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"logs")," directory contains your application's log\nfiles.")),(0,o.kt)("h3",{id:"the-tests-directory"},"The tests directory"),(0,o.kt)("p",null,"You can create a test executing the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan make:test"),"\ncommand. The ",(0,o.kt)("inlineCode",{parentName:"p"},"tests")," directory contains your unitary and E2E\ntests. Each test file name should always end with the word\nTest at the end. You may run your tests using the ",(0,o.kt)("inlineCode",{parentName:"p"},"node artisan test"),"\ncommand."),(0,o.kt)("admonition",{type:"warning"},(0,o.kt)("p",{parentName:"admonition"},"If your test file name does not end with ",(0,o.kt)("inlineCode",{parentName:"p"},"Test"),", it will\nbe ignored and the test class will not run. But, you can\ncustomize this behavior in the configure function of ",(0,o.kt)("a",{parentName:"p",href:"https://japa.dev/docs"},"Japa"),"\ninside your ",(0,o.kt)("inlineCode",{parentName:"p"},"Path.bootstrap('test.ts')")," file.")),(0,o.kt)("h2",{id:"slim-structure"},"Slim structure"),(0,o.kt)("p",null,"The slim project structure has only three folders when you\ncreate the project:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"bin")," directory is the same as ",(0,o.kt)("a",{parentName:"li",href:"/docs/getting-started/directory-structure#bootstrap"},"bootstrap"),"."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"src")," directory is used to store all the source code files of your applications."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"tests")," directory is the same as ",(0,o.kt)("a",{parentName:"li",href:"/docs/getting-started/directory-structure#tests"},"tests"),".")),(0,o.kt)("h2",{id:"do-your-own-structure"},"Do your own structure"),(0,o.kt)("p",null,"There are some files in your project that are crucial to\nkeep in certain places. Let's analyze some of them:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.bootstrap('main.ts')")," file is the entry point of the\n",(0,o.kt)("inlineCode",{parentName:"li"},"node artisan serve")," command. Every time that you run this\ncommand, Athenna will use this file to run your application."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.bootstrap('artisan.ts')")," file is the entry point of the\n",(0,o.kt)("inlineCode",{parentName:"li"},"artisan.js")," script."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"config")," path is where you are going to set up your\nconfiguration files. You can learn more about configuration\nfiles at ",(0,o.kt)("a",{parentName:"li",href:"https://athenna.io/docs/getting-started/configuration"},"the configuration documentation section"),"."),(0,o.kt)("li",{parentName:"ul"},"The ",(0,o.kt)("inlineCode",{parentName:"li"},"Path.routes('http.ts')")," file is where you are going to register\nyour Http server routes.")),(0,o.kt)("p",null,"Athenna is a framework with a lot of opinions, with predefined\nproject structures; it was built that way to make your life easier.\nBut speaking from developer to developer, we know how fun is to be\nable to have control over everything in your application,\nespecially the structure of your project \ud83d\ude0e."),(0,o.kt)("p",null,"With that in mind, Athenna was built in a fully configurable\nway. You can create your files and folders anywhere, even the\none that is crucial to keep in certain places."))}p.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.91108f77.js b/assets/js/runtime~main.fa1f4b19.js similarity index 59% rename from assets/js/runtime~main.91108f77.js rename to assets/js/runtime~main.fa1f4b19.js index 5a0163f4..1de5cd14 100644 --- a/assets/js/runtime~main.91108f77.js +++ b/assets/js/runtime~main.fa1f4b19.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,t,f,c,r={},b={};function d(e){var a=b[e];if(void 0!==a)return a.exports;var t=b[e]={id:e,loaded:!1,exports:{}};return r[e].call(t.exports,t,t.exports,d),t.loaded=!0,t.exports}d.m=r,d.c=b,e=[],d.O=(a,t,f,c)=>{if(!t){var r=1/0;for(i=0;i=c)&&Object.keys(d.O).every((e=>d.O[e](t[o])))?t.splice(o--,1):(b=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[t,f,c]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var c=Object.create(null);d.r(c);var r={};a=a||[null,t({}),t([]),t(t)];for(var b=2&f&&e;"object"==typeof b&&!~a.indexOf(b);b=t(b))Object.getOwnPropertyNames(b).forEach((a=>r[a]=()=>e[a]));return r.default=()=>e,d.d(c,r),c},d.d=(e,a)=>{for(var t in a)d.o(a,t)&&!d.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:a[t]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,t)=>(d.f[t](e,a),a)),[])),d.u=e=>"assets/js/"+({30:"29b44638",53:"935f2afb",134:"391d9c20",225:"3152febb",446:"cb55cfb3",805:"84dac133",899:"1f33cfc6",1002:"60418129",1401:"bfc576a4",1535:"e2eeca55",1977:"3aefb2a9",2206:"801e3691",2419:"94cba6ed",2628:"77db9a17",3477:"9f958c7d",3650:"30d27832",3902:"98b8cc29",4085:"4ca25bb5",4180:"25ef7947",4246:"28a593c7",4464:"bfc34fa7",4474:"205e281e",4677:"76be5683",5087:"22c3a07e",5378:"1bfe5704",5691:"26455d6c",6419:"6d39995a",6467:"08133570",6485:"f210ba15",6546:"3ebc3d67",6913:"7516947a",7054:"9dd8a0d2",7252:"f9e13beb",7439:"487f4407",7868:"6459b84b",7918:"17896441",8043:"59190afd",8223:"50bfad63",8334:"a2c501c8",8578:"d550161c",8794:"3fb3fb7f",8813:"a21dcd43",8943:"0b6406e9",9022:"31058b07",9080:"2ab4562b",9192:"ead3bc46",9514:"1be78505",9639:"4d89cf04",9687:"a7402ea8",9736:"c24fb5a2",9817:"14eb3368",9918:"62e3c86b"}[e]||e)+"."+{30:"d7c313b5",53:"c6181544",134:"b37619c9",225:"72d1de31",230:"76dec31f",446:"a54cb5b6",805:"3d8ac9bc",899:"16c8544e",1002:"d0bc6b61",1068:"091ab1fc",1401:"c09f925d",1535:"0dd5d0dc",1977:"1854ff2c",2206:"3152b3b4",2419:"092112c0",2628:"4f327571",3477:"5bf92c68",3650:"0a1d3806",3902:"c313b4ea",4085:"d532b133",4180:"b1e19c5a",4246:"0e8aa4e4",4464:"2bba80ea",4474:"9a4b1c29",4677:"45549aa8",4972:"a0723838",5087:"4b4c4682",5131:"fc6c05cb",5283:"a13d6ef9",5378:"c29e2639",5691:"bfb0d4e6",6316:"a7fccb13",6419:"759216b6",6467:"d1e503b1",6485:"9eb82c11",6546:"5133970c",6913:"c2ec5911",7054:"fdb38745",7252:"4a01e5bf",7439:"5620b62f",7724:"a79f1847",7868:"1a9dd1e9",7918:"77555dfe",8043:"4a525d05",8223:"b4a6bc96",8334:"0d37ed48",8578:"abbe48af",8794:"b2308ff7",8813:"ff4efb11",8943:"7c909a8f",9022:"14048cd2",9080:"90c477f8",9192:"c3065b84",9487:"fe42c1ae",9514:"bcd357af",9639:"53425821",9687:"7153bbb7",9736:"dddd9dc8",9817:"b6cea2b5",9918:"b742d7ab"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},c="@athenna/docs:",d.l=(e,a,t,r)=>{if(f[e])f[e].push(a);else{var b,o;if(void 0!==t)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var c=f[e];if(delete f[e],b.parentNode&&b.parentNode.removeChild(b),c&&c.forEach((e=>e(t))),a)return a(t)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",60418129:"1002","29b44638":"30","935f2afb":"53","391d9c20":"134","3152febb":"225",cb55cfb3:"446","84dac133":"805","1f33cfc6":"899",bfc576a4:"1401",e2eeca55:"1535","3aefb2a9":"1977","801e3691":"2206","94cba6ed":"2419","77db9a17":"2628","9f958c7d":"3477","30d27832":"3650","98b8cc29":"3902","4ca25bb5":"4085","25ef7947":"4180","28a593c7":"4246",bfc34fa7:"4464","205e281e":"4474","76be5683":"4677","22c3a07e":"5087","1bfe5704":"5378","26455d6c":"5691","6d39995a":"6419","08133570":"6467",f210ba15:"6485","3ebc3d67":"6546","7516947a":"6913","9dd8a0d2":"7054",f9e13beb:"7252","487f4407":"7439","6459b84b":"7868","59190afd":"8043","50bfad63":"8223",a2c501c8:"8334",d550161c:"8578","3fb3fb7f":"8794",a21dcd43:"8813","0b6406e9":"8943","31058b07":"9022","2ab4562b":"9080",ead3bc46:"9192","1be78505":"9514","4d89cf04":"9639",a7402ea8:"9687",c24fb5a2:"9736","14eb3368":"9817","62e3c86b":"9918"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(a,t)=>{var f=d.o(e,a)?e[a]:void 0;if(0!==f)if(f)t.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((t,c)=>f=e[a]=[t,c]));t.push(f[2]=c);var r=d.p+d.u(a),b=new Error;d.l(r,(t=>{if(d.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var c=t&&("load"===t.type?"missing":t.type),r=t&&t.target&&t.target.src;b.message="Loading chunk "+a+" failed.\n("+c+": "+r+")",b.name="ChunkLoadError",b.type=c,b.request=r,f[1](b)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,t)=>{var f,c,r=t[0],b=t[1],o=t[2],n=0;if(r.some((a=>0!==e[a]))){for(f in b)d.o(b,f)&&(d.m[f]=b[f]);if(o)var i=o(d)}for(a&&a(t);n{"use strict";var e,a,f,t,c,r={},b={};function d(e){var a=b[e];if(void 0!==a)return a.exports;var f=b[e]={id:e,loaded:!1,exports:{}};return r[e].call(f.exports,f,f.exports,d),f.loaded=!0,f.exports}d.m=r,d.c=b,e=[],d.O=(a,f,t,c)=>{if(!f){var r=1/0;for(i=0;i=c)&&Object.keys(d.O).every((e=>d.O[e](f[o])))?f.splice(o--,1):(b=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[f,t,c]},d.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return d.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,d.t=function(e,t){if(1&t&&(e=this(e)),8&t)return e;if("object"==typeof e&&e){if(4&t&&e.__esModule)return e;if(16&t&&"function"==typeof e.then)return e}var c=Object.create(null);d.r(c);var r={};a=a||[null,f({}),f([]),f(f)];for(var b=2&t&&e;"object"==typeof b&&!~a.indexOf(b);b=f(b))Object.getOwnPropertyNames(b).forEach((a=>r[a]=()=>e[a]));return r.default=()=>e,d.d(c,r),c},d.d=(e,a)=>{for(var f in a)d.o(a,f)&&!d.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},d.f={},d.e=e=>Promise.all(Object.keys(d.f).reduce(((a,f)=>(d.f[f](e,a),a)),[])),d.u=e=>"assets/js/"+({30:"29b44638",53:"935f2afb",134:"391d9c20",225:"3152febb",446:"cb55cfb3",805:"84dac133",899:"1f33cfc6",1002:"60418129",1401:"bfc576a4",1535:"e2eeca55",1977:"3aefb2a9",2206:"801e3691",2419:"94cba6ed",2628:"77db9a17",3477:"9f958c7d",3650:"30d27832",3902:"98b8cc29",4085:"4ca25bb5",4180:"25ef7947",4246:"28a593c7",4464:"bfc34fa7",4474:"205e281e",4677:"76be5683",5087:"22c3a07e",5378:"1bfe5704",5691:"26455d6c",6419:"6d39995a",6467:"08133570",6485:"f210ba15",6546:"3ebc3d67",6913:"7516947a",7054:"9dd8a0d2",7252:"f9e13beb",7439:"487f4407",7868:"6459b84b",7918:"17896441",8043:"59190afd",8223:"50bfad63",8334:"a2c501c8",8578:"d550161c",8794:"3fb3fb7f",8813:"a21dcd43",8943:"0b6406e9",9022:"31058b07",9080:"2ab4562b",9192:"ead3bc46",9514:"1be78505",9639:"4d89cf04",9687:"a7402ea8",9736:"c24fb5a2",9817:"14eb3368",9918:"62e3c86b"}[e]||e)+"."+{30:"d7c313b5",53:"c6181544",134:"b37619c9",225:"72d1de31",230:"76dec31f",446:"a54cb5b6",805:"3d8ac9bc",899:"16c8544e",1002:"d0bc6b61",1068:"091ab1fc",1401:"c09f925d",1535:"0dd5d0dc",1977:"1854ff2c",2206:"3152b3b4",2419:"092112c0",2628:"4f327571",3477:"5bf92c68",3650:"0a1d3806",3902:"c313b4ea",4085:"d532b133",4180:"b1e19c5a",4246:"0e8aa4e4",4464:"2bba80ea",4474:"9a4b1c29",4677:"45549aa8",4972:"a0723838",5087:"4b4c4682",5131:"fc6c05cb",5283:"a13d6ef9",5378:"c29e2639",5691:"bfb0d4e6",6316:"a7fccb13",6419:"759216b6",6467:"d1e503b1",6485:"9eb82c11",6546:"5133970c",6913:"c2ec5911",7054:"fdb38745",7252:"4a01e5bf",7439:"5620b62f",7724:"a79f1847",7868:"1a9dd1e9",7918:"77555dfe",8043:"4a525d05",8223:"b4a6bc96",8334:"0d37ed48",8578:"abbe48af",8794:"b2308ff7",8813:"ff4efb11",8943:"7c909a8f",9022:"14048cd2",9080:"19a1dc7c",9192:"c3065b84",9487:"fe42c1ae",9514:"bcd357af",9639:"53425821",9687:"7153bbb7",9736:"dddd9dc8",9817:"b6cea2b5",9918:"b742d7ab"}[e]+".js",d.miniCssF=e=>{},d.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),d.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),t={},c="@athenna/docs:",d.l=(e,a,f,r)=>{if(t[e])t[e].push(a);else{var b,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{b.onerror=b.onload=null,clearTimeout(s);var c=t[e];if(delete t[e],b.parentNode&&b.parentNode.removeChild(b),c&&c.forEach((e=>e(f))),a)return a(f)},s=setTimeout(l.bind(null,void 0,{type:"timeout",target:b}),12e4);b.onerror=l.bind(null,b.onerror),b.onload=l.bind(null,b.onload),o&&document.head.appendChild(b)}},d.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},d.p="/",d.gca=function(e){return e={17896441:"7918",60418129:"1002","29b44638":"30","935f2afb":"53","391d9c20":"134","3152febb":"225",cb55cfb3:"446","84dac133":"805","1f33cfc6":"899",bfc576a4:"1401",e2eeca55:"1535","3aefb2a9":"1977","801e3691":"2206","94cba6ed":"2419","77db9a17":"2628","9f958c7d":"3477","30d27832":"3650","98b8cc29":"3902","4ca25bb5":"4085","25ef7947":"4180","28a593c7":"4246",bfc34fa7:"4464","205e281e":"4474","76be5683":"4677","22c3a07e":"5087","1bfe5704":"5378","26455d6c":"5691","6d39995a":"6419","08133570":"6467",f210ba15:"6485","3ebc3d67":"6546","7516947a":"6913","9dd8a0d2":"7054",f9e13beb:"7252","487f4407":"7439","6459b84b":"7868","59190afd":"8043","50bfad63":"8223",a2c501c8:"8334",d550161c:"8578","3fb3fb7f":"8794",a21dcd43:"8813","0b6406e9":"8943","31058b07":"9022","2ab4562b":"9080",ead3bc46:"9192","1be78505":"9514","4d89cf04":"9639",a7402ea8:"9687",c24fb5a2:"9736","14eb3368":"9817","62e3c86b":"9918"}[e]||e,d.p+d.u(e)},(()=>{var e={1303:0,532:0};d.f.j=(a,f)=>{var t=d.o(e,a)?e[a]:void 0;if(0!==t)if(t)f.push(t[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((f,c)=>t=e[a]=[f,c]));f.push(t[2]=c);var r=d.p+d.u(a),b=new Error;d.l(r,(f=>{if(d.o(e,a)&&(0!==(t=e[a])&&(e[a]=void 0),t)){var c=f&&("load"===f.type?"missing":f.type),r=f&&f.target&&f.target.src;b.message="Loading chunk "+a+" failed.\n("+c+": "+r+")",b.name="ChunkLoadError",b.type=c,b.request=r,t[1](b)}}),"chunk-"+a,a)}},d.O.j=a=>0===e[a];var a=(a,f)=>{var t,c,r=f[0],b=f[1],o=f[2],n=0;if(r.some((a=>0!==e[a]))){for(t in b)d.o(b,t)&&(d.m[t]=b[t]);if(o)var i=o(d)}for(a&&a(f);n - + - + \ No newline at end of file diff --git a/docs/architecture-concepts/application-lifecycle.html b/docs/architecture-concepts/application-lifecycle.html index 00cd9d19..02f1fc65 100644 --- a/docs/architecture-concepts/application-lifecycle.html +++ b/docs/architecture-concepts/application-lifecycle.html @@ -12,7 +12,7 @@ - + @@ -128,7 +128,7 @@ service container bindings. For large applications, you may wish to create several service providers, each with more granular bootstrapping for specific services used by your application.

- + \ No newline at end of file diff --git a/docs/architecture-concepts/facades.html b/docs/architecture-concepts/facades.html index f18768ac..dd23bd35 100644 --- a/docs/architecture-concepts/facades.html +++ b/docs/architecture-concepts/facades.html @@ -12,7 +12,7 @@ - + @@ -65,7 +65,7 @@ providers array.

Artisan can generate a new facade via the make:facade command:

node artisan make:facade String

The facade file will be generated inside the providers/facades directory. Open this file and change the alias to your provider alias and set up the generic type:

import { Facade } from '@athenna/ioc'
import { String as StringImpl } from '#app/helpers/String'

export const String = Facade.createFor<StringImpl>('App/Helpers/String')

Now we can start using our new String facade:

import { Route } from '@athenna/http' // Route Facade
import { String } from '#providers/facades/String' // String Facade

Route.get('/welcome', ({ response }) => {
return response
.status(200)
.send({ hello: String.toPascalCase('world') })
})
- + \ No newline at end of file diff --git a/docs/architecture-concepts/service-container.html b/docs/architecture-concepts/service-container.html index 2e4a789b..a6d22e08 100644 --- a/docs/architecture-concepts/service-container.html +++ b/docs/architecture-concepts/service-container.html @@ -12,7 +12,7 @@ - + @@ -93,7 +93,7 @@ annotation follows the same logic of the constructor, you need to use the camelCase name of your dependency as the property name to be resolved properly:

import { Inject } from '@athenna/ioc'
import { AppService } from '#app/services/AppService'
import { Controller, type Context } from '@athenna/http'

@Controller()
export class AppController {
@Inject()
private appService: AppService

public async show({ response }: Context) {
const data = await this.appService.getData()

return response.status(200).send(data)
}
}

When using the @Inject() annotation you could also pass as argument a specific alias to be resolved in the container:

import { Inject } from '@athenna/ioc'
import { AppService } from '#app/services/AppService'
import { Controller, type Context } from '@athenna/http'

@Controller()
export class AppController {
@Inject('App/Services/AppService')
private appService: AppService

public async show({ response }: Context) {
const data = await this.appService.getData()

return response.status(200).send(data)
}
}
- + \ No newline at end of file diff --git a/docs/architecture-concepts/service-providers.html b/docs/architecture-concepts/service-providers.html index f9eac36b..b65eba9b 100644 --- a/docs/architecture-concepts/service-providers.html +++ b/docs/architecture-concepts/service-providers.html @@ -12,7 +12,7 @@ - + @@ -63,7 +63,7 @@ your application. This means that in the example above, when running your http server, the providers bootstrapped will be only the ones that got the environments getter returning ['*'] and ['myEnv', 'http'].

- + \ No newline at end of file diff --git a/docs/cli-application.html b/docs/cli-application.html index f85f0d5e..bc6ee69a 100644 --- a/docs/cli-application.html +++ b/docs/cli-application.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/cli-application/commands.html b/docs/cli-application/commands.html index fb5cb457..db0d1c3c 100644 --- a/docs/cli-application/commands.html +++ b/docs/cli-application/commands.html @@ -12,7 +12,7 @@ - + @@ -183,7 +183,7 @@ callInChild() method:

const { stdout, stderr } = await Artisan.callInChild('make:controller TestController')

assert.isTrue(stdout.includes('[ MAKING CONTROLLER ]'))
assert.isUndefined(stderr)

By default this method will look to the Path.boostrap('artisan.ts') file to execute your command, but you can change the file to be used setting the path to it as second parameter:

const command = 'make:controller TestController'
const artisanPath = Path.pwd(`artisan.${Path.ext()}`)

await Artisan.callInChild(command, artisanPath)
- + \ No newline at end of file diff --git a/docs/cli-application/error-handling.html b/docs/cli-application/error-handling.html index 1a0f157c..65d45a4a 100644 --- a/docs/cli-application/error-handling.html +++ b/docs/cli-application/error-handling.html @@ -12,7 +12,7 @@ - + @@ -56,7 +56,7 @@ your exceptions. You can do so by creating your own exception handler:

app/console/exceptions/Handler.ts
import { ConsoleExceptionHandler } from '@athenna/artisan'

export class Handler extends ConsoleExceptionHandler {
public async handle(error: any) {
// Implement your own logic
}
}

Now you need to register your exception handler when bootstrapping your application:

Path.bootstrap('main.ts')
await ignite.console(process.argv, {
displayName: 'Athenna',
exceptionHandlerPath: '#app/console/exceptions/Handler', 👈
})
- + \ No newline at end of file diff --git a/docs/cli-application/publishing.html b/docs/cli-application/publishing.html index 17fd8791..2faedb6d 100644 --- a/docs/cli-application/publishing.html +++ b/docs/cli-application/publishing.html @@ -12,7 +12,7 @@ - + @@ -27,7 +27,7 @@ is very simple, just run the following command:

npm publish --access public

If you have been following along, then congratulations! You just published your first NPM package.

You can visit the NPM website and run a search for your package. You should see your package show up in the search results.

- + \ No newline at end of file diff --git a/docs/cli-application/running.html b/docs/cli-application/running.html index 569ea25f..a3352bba 100644 --- a/docs/cli-application/running.html +++ b/docs/cli-application/running.html @@ -12,7 +12,7 @@ - + @@ -38,7 +38,7 @@ change it for your own display name by setting the displayName property in Ignite.console() method:

Path.bootstrap('main.ts')
import { Ignite } from '@athenna/core'

const ignite = await new Ignite().load(import.meta.url)

await ignite.console({
displayName: 'Your CLI Command', 👈
})
tip

If you wish to disable the display name, set the displayName as null:

Path.bootstrap('main.ts')
import { Ignite } from '@athenna/core'

const ignite = await new Ignite().load(import.meta.url)

await ignite.console({
displayName: null, 👈
})
- + \ No newline at end of file diff --git a/docs/digging-deeper.html b/docs/digging-deeper.html index 2bb5406e..5883f5f7 100644 --- a/docs/digging-deeper.html +++ b/docs/digging-deeper.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/digging-deeper/collections.html b/docs/digging-deeper/collections.html index 8b20c661..d9c793c3 100644 --- a/docs/digging-deeper/collections.html +++ b/docs/digging-deeper/collections.html @@ -12,7 +12,7 @@ - + @@ -40,7 +40,7 @@ You may also pass a negative integer to take the specified amount of items from the end of the collection:

const collection = new Collection([0, 1, 2, 3, 4, 5])

const chunk = collection.take(3)

chunk.all()

// [0, 1, 2]

takeUntil()

The takeUntil method returns items in the collection until the given callback returns true:

const collection = new Collection([1, 2, 3, 4])

const subset = collection.takeUntil(item => item >= 3)

subset.all()

// [1, 2]

If the given value is not found or the callback never returns true, the takeUntil method will return all items in the collection.

You may also pass a simple value to the takeUntil method to get the items until the given value is found:

const collection = new Collection([1, 2, 3, 4])

const subset = collection.takeUntil(3)

subset.all()

// [1, 2]

takeWhile()

The takeWhile method returns items in the collection until the given callback returns false:

const collection = new Collection([1, 2, 3, 4])

const subset = collection.takeWhile(item => item < 3)

subset.all()

// [1, 2]

If the callback never returns false, the takeWhile method will return all items in the collection.

tap()

The tap method passes the collection to the given callback, allowing you to "tap" into the collection at a specific point and do something with the items while not affecting the collection itself:

new Collection([2, 4, 3, 1, 5])
.sort()
.tap((collection) => {
console.log(collection.all())

// [1, 2, 3, 4, 5]
})
.shift()

// 1

times()

The times method creates a new collection by invoking the callback a given amount of times:

const collection = new Collection().times(10, number => number * 9)

collection.all()

// [9, 18, 27, 36, 45, 54, 63, 72, 81, 90]

toArray()

The toArray method converts the collection into a plain array. If the collection is an object, an array containing the values will be returned.

const collection = new Collection([1, 2, 3, 'b', 'c'])

collection.toArray()

// [1, 2, 3, 'b', 'c']
const collection = new Collection({
name: 'Elon Musk',
companies: ['Tesla', 'Space X', 'SolarCity'],
})

collection.toArray()

// ['Elon Musk', ['Tesla', 'Space X', 'SolarCity']]

toJson()

The toJson method converts the collection into JSON string:

const collection = new Collection({
id: 384,
name: 'Rayquaza',
gender: 'NA',
})

const json = collection.toJson()

// {"id": 384, "name": "Rayquaza", "gender": "NA"}

toResource()

The toResource method enter all collection objects and execute the toResource method of each object:

const collection = new Collection([
{ toResource: criterias => ({ id: 1, ...criterias }) }
])

const resources = collection.toResource({ name: 'string' })

// [{ id: 1, name: 'string' }]

transform()

The transform method iterates over the collection and calls the given callback with each item in the collection. The items in the collection will be replaced by the values returned by the callback:

const collection = new Collection([1, 2, 3, 4, 5])

collection.transform((item, key) => item * 2)

collection.all()

// [2, 4, 6, 8, 10]

Unlike most other collection methods, transform modifies the collection itself. If you wish to create a new collection instead, use the map method.

undot()

The undot method expands a single-dimensional collection that uses "dot" notation into a multi-dimensional collection:

const person = new Collection({
'name.first_name': 'Marie',
'name.last_name': 'Valentine',
'address.line_1': '2992 Eagle Drive',
'address.line_2': '',
'address.suburb': 'Detroit',
'address.state': 'MI',
'address.postcode': '48219',
})

const undotted = person.undot()

const all = undotted.all()

// {
// name: {
// first_name: 'Marie',
// last_name: 'Valentine',
// },
// address: {
// line_1: '2992 Eagle Drive',
// line_2: '',
// suburb: 'Detroit',
// state: 'MI',
// postcode: '48219',
// },
// }

union()

The union method adds the given array to the collection. If the given array contains keys that are already in the original collection, the original collection's values will be preferred:

const collection = new Collection({
a: 'A',
b: 'B',
})

const union = collection.union({
a: 'AAA',
c: 'CCC',
b: 'BBB',
})

union.all()

// {
// a: 'A',
// b: 'B',
// c: 'CCC',
// }

unique()

The unique method returns all of the unique items in the collection:

const collection = new Collection([1, 1, 1, 2, 3, 3])

const unique = collection.unique()

unique.all()

// [1, 2, 3]

When dealing with an array of objects, you may specify the key used to determine uniqueness:

const collection = new Collection([
{ name: 'iPhone 6', brand: 'Apple', type: 'phone' },
{ name: 'iPhone 5', brand: 'Apple', type: 'phone' },
{ name: 'Apple Watch', brand: 'Apple', type: 'watch' },
{ name: 'Galaxy S6', brand: 'Samsung', type: 'phone' },
{ name: 'Galaxy Gear', brand: 'Samsung', type: 'watch' },
])

const unique = collection.unique('brand')

unique.all()

// [
// { name: 'iPhone 6', brand: 'Apple', type: 'phone' },
// { name: 'Galaxy S6', brand: 'Samsung', type: 'phone' },
// ]

You may also pass your own callback to determine item uniqueness:

const collection = new Collection([
{ name: 'iPhone 6', brand: 'Apple', type: 'phone' },
{ name: 'iPhone 5', brand: 'Apple', type: 'phone' },
{ name: 'Apple Watch', brand: 'Apple', type: 'watch' },
{ name: 'Galaxy S6', brand: 'Samsung', type: 'phone' },
{ name: 'Galaxy Gear', brand: 'Samsung', type: 'watch' },
])

const unique = collection.unique(item => item.brand + item.type)

unique.all()

// [
// { name: 'iPhone 6', brand: 'Apple', type: 'phone' },
// { name: 'Apple Watch', brand: 'Apple', type: 'watch' },
// { name: 'Galaxy S6', brand: 'Samsung', type: 'phone' },
// { name: 'Galaxy Gear', brand: 'Samsung', type: 'watch' },
// ]

unless()

The unless method will execute the given callback when the first argument given to the method evaluates to false:

const collection = new Collection([1, 2, 3])

collection.unless(false, items => items.push(4))

collection.all()

// [1, 2, 3, 4]

unlessEmpty()

Alias for the whenNotEmpty() method

unlessNotEmpty()

Alias for the whenEmpty() method

unwrap()

The unwrap method will unwrap the given collection:

const collection = new Collection([1, 2, 3])

new Collection().unwrap(collection)

// [1, 2, 3]

values()

The values method returns a new collection with the keys reset to consecutive integers:

const collection = new Collection({
a: 'xoxo',
b: 'abab',
c: '1337',
1337: 12,
})

const values = collection.values()

values.all()

// [12, 'xoxo', 'abab', '1337']

when()

The when method will execute the given callback when the first argument given to the method evaluates to true:

const collection = new Collection([1, 2, 3])

collection.when(true, items => items.push(4))

collection.all()

// [1, 2, 3, 4]

whenEmpty()

The whenEmpty method will execute the given callback when the collection is empty:

const collection = new Collection([])

collection.whenEmpty(c => c.push('Mohamed Salah'))

collection.all()

// ['Mohamed Salah']
const collection = new Collection(['Darwin Núñez'])

collection.whenEmpty(
c => c.push('Mohamed Salah'),
c => c.push('Xherdan Shaqiri'),
)

collection.all()

// [
// 'Darwin Núñez',
// 'Xherdan Shaqiri',
// ]

whenNotEmpty()

The whenNotEmpty method will execute the given callback when the collection is not empty:

const collection = new Collection(['Darwin Núñez'])

collection.whenNotEmpty(c => c.push('Mohamed Salah'))

collection.all()

// [
// 'Darwin Núñez',
// 'Mohamed Salah',
// ]
const collection = new Collection(['Darwin Núñez'])

collection.whenNotEmpty(
c => c.push('Mohamed Salah'),
c => c.push('Xherdan Shaqiri'),
)

collection.all()

// [
// 'Darwin Núñez',
// 'Mohamed Salah',
// ]

where()

The where method filters the collection by a given key / value pair:

const collection = new Collection([
{ product: 'Desk', price: 200, discounted: true },
{ product: 'Chair', price: 100, discounted: true },
{ product: 'Bookcase', price: 150, discounted: true },
{ product: 'Door', price: 100 },
])

const filtered = collection.where('price', 100)

filtered.all()

// [
// { product: 'Chair', price: 100 },
// { product: 'Door', price: 100 },
// ]

const discounted = collection.where('discounted')

discounted.all()

// [
// { product: 'Desk', price: 200, discounted: true },
// { product: 'Chair', price: 100, discounted: true },
// { product: 'Bookcase', price: 150, discounted: true },
// ]

const notDiscounted = collection.where('discounted', false)

discounted.all()

// [
// { product: 'Door', price: 100 },
// ]

When working with nested objects where() method allows dot notated keys. E.g. where('product.category', 'office-supplies') The where method also allows for custom comparisons:

Non-identity / strict inequality (!==)

const filtered = collection.where('price', '!==', 100)

filtered.all()

// [
// { product: 'Desk', price: 200 },
// { product: 'Bookcase', price: 150 },
// ]

Less than operator (<)

const filtered = collection.where('price', '<', 100)

filtered.all()

// []

Less than or equal operator (<=)

const filtered = collection.where('price', '<=', 100)

filtered.all()

// [
// { product: 'Chair', price: 100 },
// { product: 'Door', price: 100 },
// ]

Greater than operator (>)

const filtered = collection.where('price', '>', 100)

filtered.all()

// [
// { product: 'Desk', price: 200} ,
// { product: 'Bookcase', price: 150 },
// ]

Greater than or equal operator (>=)

const filtered = collection.where('price', '>=', 150)

filtered.all()

// [
// { product: 'Desk', price: 200} ,
// { product: 'Bookcase', price: 150 },
// ]

whereBetween()

The whereBetween method filters the collection within a given range:

const collection = new Collection([
{ product: 'Desk', price: 200 },
{ product: 'Chair', price: 80 },
{ product: 'Bookcase', price: 150 },
{ product: 'Pencil', price: 30 },
{ product: 'Door', price: 100 },
])

const filtered = collection.whereBetween('price', [100, 200])

filtered.all()

// [
// { product: 'Desk', price: 200 },
// { product: 'Bookcase', price: 150 },
// { product: 'Door', price: 100 },
// ]

whereIn()

The whereIn method filters the collection by a given key / value contained within the given array.

const collection = new Collection([
{ product: 'Desk', price: 200 },
{ product: 'Chair', price: 100 },
{ product: 'Bookcase', price: 150 },
{ product: 'Door', price: 100 },
])

const filtered = collection.whereIn('price', [100, 150])

filtered.all()

// [
// { product: 'Chair', price: 100 },
// { product: 'Bookcase', price: 150 },
// { product: 'Door', price: 100 },
// ]

When working with nested objects whereIn() method allows dot notated keys. E.g. whereIn('product.categories', ['office-supplies', 'furniture'])

whereInstanceOf()

The whereInstanceOf method filters the collection by a given class type:

const collection = new Collection([
new Player('Firmino'),
new Player('Salah'),
new Manager('Klopp'),
])

const filtered = collection.whereInstanceOf(Player)

filtered.all()

// [
// new Player('Firmino'),
// new Player('Salah'),
// ]

whereNotBetween()

The whereNotBetween method filters the collection within a given range:

const collection = new Collection([
{ product: 'Desk', price: 200 },
{ product: 'Chair', price: 80 },
{ product: 'Bookcase', price: 150 },
{ product: 'Pencil', price: 30 },
{ product: 'Door', price: 100 },
])

const filtered = collection.whereNotBetween('price', [100, 200])

filtered.all()

// [
// { product: 'Chair', price: 80 },
// { product: 'Pencil', price: 30 },
// ]

whereNotIn()

The whereNotIn method filters the collection by a given key / value not contained within the given array:

const collection = new Collection([
{ product: 'Desk', price: 200 },
{ product: 'Chair', price: 100 },
{ product: 'Bookcase', price: 150 },
{ product: 'Door', price: 100 },
])

const filtered = collection.whereNotIn('price', [150, 200])

filtered.all()

// [
// { product: 'Chair', price: 100 },
// { product: 'Door', price: 100 },
// ]

When working with nested objects whereNotIn() method allows dot notated keys. E.g. whereNotIn('product .categories', ['office-supplies', 'furniture'])

whereNotNull()

The whereNotNull method filters items where the given key is not null.

const collection = new Collection([{
name: 'Mohamed Salah',
}, {
name: null,
}, {
name: 'Darwin Núñez',
}])

const filtered = collection.whereNotNull()

filtered.all()

// [
// { name: 'Mohamed Salah' },
// { name: 'Darwin Núñez' },
// ]

whereNull()

The whereNull method filters items where the given key is null.

const collection = new Collection([{
name: 'Mohamed Salah',
}, {
name: null,
}, {
name: 'Darwin Núñez',
}])

const filtered = collection.whereNull()

filtered.all()

// [
// { name: null },
// ]

wrap()

The wrap method will wrap the given value in a collection:

const collection = new Collection().wrap([1, 2, 3])

collection.all()

// [1, 2, 3]

zip()

The zip method merges together the values of the given array with the values of the original collection at the corresponding index:

const collection = new Collection(['Chair', 'Desk'])

const zipped = collection.zip([100, 200])

zipped.all()

// [['Chair', 100], ['Desk', 200]]
- + \ No newline at end of file diff --git a/docs/digging-deeper/graceful-shutdown.html b/docs/digging-deeper/graceful-shutdown.html index bb4baa58..78de6bea 100644 --- a/docs/digging-deeper/graceful-shutdown.html +++ b/docs/digging-deeper/graceful-shutdown.html @@ -12,7 +12,7 @@ - + @@ -49,7 +49,7 @@ file:

import { LoadHelper } from '@athenna/ioc'

export default {
signals: {
SIGINT: () => {
console.log('executing SIGINT')

process.exit()
},
SIGTERM: async () => {
console.log('executing SIGTERM')

await LoadHelper.shutdownProviders()

process.kill(process.pid, signal)
},
// NEW SIGNAL
SIGKILL: async () => {
console.log('executing SIGKILL')
}
}
}
tip

To "remove" the default listeners, just implement a NOOP function in SIGINT and SIGTERM, because if you remove the key or let it undefined, Athenna will use the default:

export default {
signals: {
SIGINT: () => {},
SIGTERM: () => {},
}
}
- + \ No newline at end of file diff --git a/docs/digging-deeper/library-development.html b/docs/digging-deeper/library-development.html index f48691be..d56aafaf 100644 --- a/docs/digging-deeper/library-development.html +++ b/docs/digging-deeper/library-development.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/digging-deeper/mail.html b/docs/digging-deeper/mail.html index e3ced534..4bc87ece 100644 --- a/docs/digging-deeper/mail.html +++ b/docs/digging-deeper/mail.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/digging-deeper/repl.html b/docs/digging-deeper/repl.html index c56c8dec..89364a16 100644 --- a/docs/digging-deeper/repl.html +++ b/docs/digging-deeper/repl.html @@ -12,7 +12,7 @@ - + @@ -47,7 +47,7 @@ With repl.importAll() you can import the module names as keys to the REPL context:

import { Ignite } from '@athenna/core'

const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })

const repl = await ignite.repl()

await repl.importAll('@athenna/common')

Now you are able to use the Path helper directly in your REPL sessions:

Path.pwd()
info

By default, your Path.bootstrap('repl.ts') file already imports all the @athenna/common helpers to your REPL session 🤩.

- + \ No newline at end of file diff --git a/docs/getting-started.html b/docs/getting-started.html index 126a4452..3b2956b5 100644 --- a/docs/getting-started.html +++ b/docs/getting-started.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/getting-started/athennarc-file.html b/docs/getting-started/athennarc-file.html index 1022221a..c6c7ef3d 100644 --- a/docs/getting-started/athennarc-file.html +++ b/docs/getting-started/athennarc-file.html @@ -12,7 +12,7 @@ - + @@ -96,7 +96,7 @@ are set to it as second argument:

{
"artisan": {
"child": {
"executor": "node --inspect",
"path": "./bin/artisan.ts"
}
}
}
tip

Athenna will automatically parse the artisan.child.path using the Path.ext() method, so you don't need to worry about if the extension is .js or .ts.

- + \ No newline at end of file diff --git a/docs/getting-started/configuration.html b/docs/getting-started/configuration.html index 86f579d5..0ede34f9 100644 --- a/docs/getting-started/configuration.html +++ b/docs/getting-started/configuration.html @@ -12,7 +12,7 @@ - + @@ -156,7 +156,7 @@ this value should always be false, if the variable is set to true in production, you risk exposing sensitive configuration values to your application's end users.

- + \ No newline at end of file diff --git a/docs/getting-started/directory-structure.html b/docs/getting-started/directory-structure.html index 573fb6d7..ec7c4419 100644 --- a/docs/getting-started/directory-structure.html +++ b/docs/getting-started/directory-structure.html @@ -12,7 +12,7 @@ - + @@ -70,12 +70,12 @@ files at the configuration documentation section.
  • The Path.routes('http.ts') file is where you are going to register your Http server routes.
  • Athenna is a framework with a lot of opinions, with predefined project structures; it was built that way to make your life easier. -But speaking from developer to developer, we know how much fun it -is to be able to have control over everything in your application, +But speaking from developer to developer, we know how fun is to be +able to have control over everything in your application, especially the structure of your project 😎.

    With that in mind, Athenna was built in a fully configurable way. You can create your files and folders anywhere, even the -one that are crucial to keep in certain places.

    - +one that is crucial to keep in certain places.

    + \ No newline at end of file diff --git a/docs/getting-started/installation.html b/docs/getting-started/installation.html index 72ddf7b5..0c7664ed 100644 --- a/docs/getting-started/installation.html +++ b/docs/getting-started/installation.html @@ -12,7 +12,7 @@ - + @@ -36,7 +36,7 @@ changes and restart your application automatically when doing some change on it.
  • The serve command will look up for your Path.bootstrap('main.ts') file to bootstrap your application with predefined configurations.
  • - + \ No newline at end of file diff --git a/docs/introduction.html b/docs/introduction.html index 2429c566..1bf0301c 100644 --- a/docs/introduction.html +++ b/docs/introduction.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/introduction/benchmarks.html b/docs/introduction/benchmarks.html index ef7f65d8..4e87a2aa 100644 --- a/docs/introduction/benchmarks.html +++ b/docs/introduction/benchmarks.html @@ -12,14 +12,14 @@ - +

    Benchmarks

    See how Athenna performs in comparison to other frameworks.

    Code

    All the code used in this benchmark is available in the AthennaIO/Benchmarks repository.

    Environment

    The environment used to run the benchmarks:

    npx envinfo --system --binaries
      System:
    OS: macOS 13.3.1
    CPU: (8) arm64 Apple M1 Pro
    Memory: 107.38 MB / 16.00 GB
    Shell: 5.9 - /opt/homebrew/bin/zsh
    Binaries: Node: 18.14.2 - ~/.nvm/versions/node/v18.14.2/bin/node
    npm: 9.5.0 - ~/.nvm/versions/node/v18.14.2/bin/npm

    Results

    FrameworkVersionRequests/sec
    Fastify4.15.089974.4
    Athenna4.4.083897.4
    AdonisJS5.0.067953.6
    Express4.18.221850.2
    NestJS9.0.020019.6
    - + \ No newline at end of file diff --git a/docs/introduction/welcome.html b/docs/introduction/welcome.html index b00561b8..e4e7f2ea 100644 --- a/docs/introduction/welcome.html +++ b/docs/introduction/welcome.html @@ -12,7 +12,7 @@ - + @@ -23,7 +23,7 @@ working with microservices architecture. Expect an enjoyable, beautiful, peaceful and productive experience when working with Athenna.


    - + \ No newline at end of file diff --git a/docs/rest-api-application.html b/docs/rest-api-application.html index 6a9e7d5e..cc87bb58 100644 --- a/docs/rest-api-application.html +++ b/docs/rest-api-application.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/rest-api-application/controllers.html b/docs/rest-api-application/controllers.html index e65267ef..335b29b5 100644 --- a/docs/rest-api-application/controllers.html +++ b/docs/rest-api-application/controllers.html @@ -12,7 +12,7 @@ - + @@ -61,7 +61,7 @@ The declared dependencies will automatically be resolved and injected into the controller instance when receiving a request from the server:

    import { Inject } from '@athenna/ioc'
    import { Controller, type Context } from '@athenna/http'
    import { UserService } from '#app/services/UserService'
    import { ProfileService } from '#app/services/ProfileService'

    @Controller()
    export class UserController {
    private userService: UserService

    @Inject() 👈
    private profileService: ProfileService

    public constructor(userService) { 👈
    this.userService = userService
    }

    public async show({ response, params }: Context) {
    //
    }
    }
    - + \ No newline at end of file diff --git a/docs/rest-api-application/error-handling.html b/docs/rest-api-application/error-handling.html index 152dc868..a16e7bc3 100644 --- a/docs/rest-api-application/error-handling.html +++ b/docs/rest-api-application/error-handling.html @@ -12,7 +12,7 @@ - + @@ -58,7 +58,7 @@ your exceptions. You can do so by creating your own exception handler:

    app/http/exceptions/Handler.ts
    import { type ErrorContext, HttpExceptionHandler } from '@athenna/http'

    export class Handler extends HttpExceptionHandler {
    public async handle(ctx: ErrorContext) {
    // Implement your own logic
    }
    }

    Now you need to register your exception handler when bootstrapping your application:

    Path.bootstrap('main.ts')
    await ignite.httpServer({
    exceptionHandlerPath: '#app/http/exceptions/Handler' 👈
    })
    - + \ No newline at end of file diff --git a/docs/rest-api-application/middlewares.html b/docs/rest-api-application/middlewares.html index 3410fdf2..56441991 100644 --- a/docs/rest-api-application/middlewares.html +++ b/docs/rest-api-application/middlewares.html @@ -12,7 +12,7 @@ - + @@ -78,7 +78,7 @@ property is true in your Path.config('http.ts') file are handled by a terminator middleware! You can see the code here.

    - + \ No newline at end of file diff --git a/docs/rest-api-application/rate-limiting.html b/docs/rest-api-application/rate-limiting.html index 52fd0d54..920ac593 100644 --- a/docs/rest-api-application/rate-limiting.html +++ b/docs/rest-api-application/rate-limiting.html @@ -12,7 +12,7 @@ - + @@ -35,7 +35,7 @@ plugin registration if the package does not exist, so to disable rate-limiting in Athenna you need to remove the @fastify/rate-limit package from your application:

    npm remove @fastify/rate-limit

    You can also disable by setting http.rateLimit.enabled to false:

    Path.config('http.ts')
    export default {
    rateLimit: {
    enabled: false
    }
    }
    - + \ No newline at end of file diff --git a/docs/rest-api-application/request-context.html b/docs/rest-api-application/request-context.html index c4906f16..46476fdd 100644 --- a/docs/rest-api-application/request-context.html +++ b/docs/rest-api-application/request-context.html @@ -12,7 +12,7 @@ - + @@ -92,7 +92,7 @@ Athenna set the TerminateContext. This context is quite the same of Context, but it has additional properties body, status and responseTime.

    - + \ No newline at end of file diff --git a/docs/rest-api-application/routing.html b/docs/rest-api-application/routing.html index ef05a95d..680e0538 100644 --- a/docs/rest-api-application/routing.html +++ b/docs/rest-api-application/routing.html @@ -12,7 +12,7 @@ - + @@ -63,7 +63,7 @@ To do that you need to set the new path to Ignite.httpServer() method:

    Path.bootstrap('dev.ts')
    import { Ignite } from '@athenna/core'

    const ignite = await new Ignite().load(import.meta.url)

    await ignite.httpServer({
    routePath: './bootstrap/routes/http-dev.js' 👈
    })
    tip

    Always remember that when using relative paths to set something in Athenna, you need to use your project root path as reference, just like in the example above.

    - + \ No newline at end of file diff --git a/docs/rest-api-application/security-with-helmet.html b/docs/rest-api-application/security-with-helmet.html index 013aabd7..2b18e551 100644 --- a/docs/rest-api-application/security-with-helmet.html +++ b/docs/rest-api-application/security-with-helmet.html @@ -12,7 +12,7 @@ - + @@ -44,7 +44,7 @@ to disable helmet in Athenna you need to remove the @fastify/helmet package from your application:

    npm remove @fastify/helmet

    You can also disable by setting http.helmet.enabled to false:

    Path.config('http.ts')
    export default {
    helmet: {
    enabled: false
    }
    }
    - + \ No newline at end of file diff --git a/docs/rest-api-application/swagger-documentation.html b/docs/rest-api-application/swagger-documentation.html index b329ea4e..311f6767 100644 --- a/docs/rest-api-application/swagger-documentation.html +++ b/docs/rest-api-application/swagger-documentation.html @@ -12,7 +12,7 @@ - + @@ -36,7 +36,7 @@ to disable Swagger in Athenna you need to remove the @fastify/swagger and @fastify/swagger-ui packages from your application:

    npm remove @fastify/swagger @fastify/swagger-ui

    You can also disable by setting http.swagger.enabled to false:

    Path.config('http.ts')
    export default {
    swagger: {
    enabled: false
    }
    }
    - + \ No newline at end of file diff --git a/docs/rest-api-application/tracing-requests.html b/docs/rest-api-application/tracing-requests.html index 5837a955..0529ff05 100644 --- a/docs/rest-api-application/tracing-requests.html +++ b/docs/rest-api-application/tracing-requests.html @@ -12,7 +12,7 @@ - + @@ -34,7 +34,7 @@ to disable tracer in Athenna you need to remove the cls-rtracer package from your application:

    npm remove cls-rtracer

    You can also disable by setting http.rTracer.enabled to false:

    Path.config('http.ts')
    export default {
    rTracer: {
    enabled: false
    }
    }

    Or by setting the trace option as false when booting the server in Ignite.httpServer() method:

    Path.bootstrap('main.ts')
    import { Ignite } from '@athenna/core'

    const ignite = await new Ignite().load(import.meta.url)

    await ignite.httpServer({
    trace: false 👈
    })
    - + \ No newline at end of file diff --git a/docs/testing.html b/docs/testing.html index fc9e9c89..6377dc22 100644 --- a/docs/testing.html +++ b/docs/testing.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/testing/cli-tests.html b/docs/testing/cli-tests.html index 36ccaf3d..a07665aa 100644 --- a/docs/testing/cli-tests.html +++ b/docs/testing/cli-tests.html @@ -12,7 +12,7 @@ - + @@ -60,7 +60,7 @@ or stderr. To force the stream type where this log should match, you can set it as second argument:

    output.assertLogMatches(/Hello World/, 'stdout') // or stderr
    output.assertLogNotMatches(/Hello World/, 'stdout') // or stderr
    - + \ No newline at end of file diff --git a/docs/testing/getting-started.html b/docs/testing/getting-started.html index e19696d9..ce037ad1 100644 --- a/docs/testing/getting-started.html +++ b/docs/testing/getting-started.html @@ -12,7 +12,7 @@ - + @@ -98,7 +98,7 @@ npm script defined that already does this job for you:

    npm run test:coverage

    Creating base test classes

    If you would like to define some helper methods to be defined in all your test classes, you can create a base test class and extend it in your tests:

    tests/helpers/BaseTest.ts
    import { BeforeAll } from '@athenna/test'

    export class BaseTest {
    @BeforeAll()
    public async beforeAll() {
    console.log('Executed before all tests that extends BaseTest!')
    }

    public getMockedData() {
    return {
    name: 'Lenon'
    }
    }
    }
    tests/e2e/UserTest.ts
    import { Test, type Context } from '@athenna/test'
    import { BaseTest } from '#tests/helpers/BaseTest'

    export default class UserTest extends BaseTest {
    @Test()
    public async test({ assert }: Context) {
    const data = this.getMockedData()

    assert.equal(data.name, 'Lenon')
    }
    }
    - + \ No newline at end of file diff --git a/docs/testing/mocking.html b/docs/testing/mocking.html index 23c813eb..f5247ca5 100644 --- a/docs/testing/mocking.html +++ b/docs/testing/mocking.html @@ -12,7 +12,7 @@ - + @@ -93,7 +93,7 @@ your own Artisan console that will first mock the this.prompt.input() method and then boot Artisan:

    Path.fixtures('consoles/mock-greet-input.ts')
    import { Mock } from '@athenna/test'
    import { Ignite } from '@athenna/core'
    import { Prompt } from '@athenna/artisan'

    const ignite = await new Ignite().load(import.meta.url, { bootLogs: false })

    Mock.when(Prompt.prototype, 'input').resolve('Valmir Barbosa')

    await ignite.console(process.argv, { displayName: 'Artisan' })

    Now, we can use this new Artisan console file to run the command in our test cases:

    import { Path } from '@athenna/common'
    import { Test, type Context } from '@athenna/test'

    export default class GreetTest {
    @Test()
    public async testGreet({ command }: Context) {
    const output = await command.run('greet', {
    path: Path.fixtures('consoles/mock-greet-input.ts') 👈
    })

    output.assertLogged('Hello Valmir Barbosa!')
    }
    }
    - + \ No newline at end of file diff --git a/docs/testing/rest-api-testing.html b/docs/testing/rest-api-testing.html index e00dff3e..7a3d4d3b 100644 --- a/docs/testing/rest-api-testing.html +++ b/docs/testing/rest-api-testing.html @@ -12,7 +12,7 @@ - + @@ -54,7 +54,7 @@ the given name:

    const key = 'hello'

    response.assertHeaderContainsKey(key)
    response.assertHeaderNotContainsKey(key)

    assertHeaderContainsAllKeys()

    Assert that the response header contains all the keys with given names:

    const keys = ['hello']

    response.assertHeaderContainsAllKeys(keys)
    response.assertHeaderNotContainsAllKeys(keys)

    assertHeaderDeepEqual()

    Assert that the response header is deep equal and exactly like the given value:

    const fullHeader = [{ hello: 'world' }]

    response.assertHeaderDeepEqual(fullHeader)
    response.assertHeaderNotDeepEqual(fullHeader)
    - + \ No newline at end of file diff --git a/docs/the-basics.html b/docs/the-basics.html index 4aba1f81..ec3b8473 100644 --- a/docs/the-basics.html +++ b/docs/the-basics.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/the-basics/compilation.html b/docs/the-basics/compilation.html index 683401f7..c1627beb 100644 --- a/docs/the-basics/compilation.html +++ b/docs/the-basics/compilation.html @@ -12,7 +12,7 @@ - + @@ -44,7 +44,7 @@ prevent issues for you. The environment variables are not transferable, you must define environment variables for production separately.

    - + \ No newline at end of file diff --git a/docs/the-basics/deployment.html b/docs/the-basics/deployment.html index 29da1613..2ad8e381 100644 --- a/docs/the-basics/deployment.html +++ b/docs/the-basics/deployment.html @@ -12,13 +12,13 @@ - + - + \ No newline at end of file diff --git a/docs/the-basics/helpers.html b/docs/the-basics/helpers.html index 49a5dd66..8ecfe931 100644 --- a/docs/the-basics/helpers.html +++ b/docs/the-basics/helpers.html @@ -12,7 +12,7 @@ - + @@ -259,7 +259,7 @@ valid, this method will throw:

    import { Uuid } from '@athenna/common'

    const uuid = 'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'
    const prefixedUuid = Uuid.injectPrefix(uuid, 'adm')
    // adm::a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

    Uuid::changePrefix()

    Change the prefix of an UUID token, if the UUID token is not valid, this function will throw:

    import { Uuid } from '@athenna/common'

    const uuid = 'adm::a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11'
    const prefixedUuid = Uuid.changePrefix(uuid, 'mng')
    // mng::a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

    Uuid::changeOrGenerate()

    Change the prefix of an UUID token, or generate the token if the UUID token is undefined:

    import { Uuid } from '@athenna/common'

    const uuid = undefined
    const prefixedUuid = Uuid.changeOrGenerate('adm', uuid)
    // adm::a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11

    const changedPrefixUuid = Uuid.changeOrGenerate('mng', prefixedUuid)
    // mng::a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11
    - + \ No newline at end of file diff --git a/docs/the-basics/logging.html b/docs/the-basics/logging.html index e3f9fbdc..120b5ef6 100644 --- a/docs/the-basics/logging.html +++ b/docs/the-basics/logging.html @@ -12,7 +12,7 @@ - + @@ -111,7 +111,7 @@ the application boot process. The same happens when your application is shuting down.

    If you wish to run your application in silent mode, you can disable this kind of logs using the Ignite::load() static method:

    Path.bootstrap('main.ts')
    import { Ignite } from '@athenna/core'

    const ignite = await new Ignite().load(import.meta.url, {
    bootLogs: false, 👈
    shutdownLogs: false, 👈
    })

    await ignite.httpServer()
    - + \ No newline at end of file diff --git a/docs/the-basics/views.html b/docs/the-basics/views.html index c39876d9..4b8514fd 100644 --- a/docs/the-basics/views.html +++ b/docs/the-basics/views.html @@ -12,7 +12,7 @@ - + @@ -89,7 +89,7 @@ you make to these stubs will be reflected when you generate their correspoding classes using Artisan's make commands.

    - + \ No newline at end of file diff --git a/index.html b/index.html index 0a3800ae..9a7ec8ff 100644 --- a/index.html +++ b/index.html @@ -12,13 +12,13 @@ - +
    - + \ No newline at end of file diff --git a/sw.js b/sw.js index be893866..6be25710 100644 --- a/sw.js +++ b/sw.js @@ -4556,7 +4556,7 @@ function getPossibleURLs(url) { (async () => { const params = parseSwParams(); // eslint-disable-next-line no-underscore-dangle - const precacheManifest = [{"revision":"e5f7b797180397888f2b8496d278442a","url":"404.html"},{"revision":"72272eb0b515a05ed971b092c3d603b2","url":"assets/css/styles.fb5f6248.css"},{"revision":"6102ecf9c1acca147c59a56d9476bfe8","url":"assets/js/08133570.d1e503b1.js"},{"revision":"883385237362ae584c12ac13b8033a90","url":"assets/js/0b6406e9.7c909a8f.js"},{"revision":"f1ec9bd8f24f74c2803a00ca3c32f772","url":"assets/js/1068.091ab1fc.js"},{"revision":"83d10b4a6a058dec22e4a531825df123","url":"assets/js/14eb3368.b6cea2b5.js"},{"revision":"e3dfbe867f84a2f27b88ef1b3068a4b1","url":"assets/js/17896441.77555dfe.js"},{"revision":"d95e33b7be4c6e0758f8bd4c53661640","url":"assets/js/1be78505.bcd357af.js"},{"revision":"5547bdacee5225bf0b5cfd01870a47bf","url":"assets/js/1bfe5704.c29e2639.js"},{"revision":"ca80f7605cde7b8d9e8629e4e565cb4c","url":"assets/js/1f33cfc6.16c8544e.js"},{"revision":"aa5a085afe6b2d8c0c15a63e3ba618bc","url":"assets/js/205e281e.9a4b1c29.js"},{"revision":"d62dee970a6f775bcedf1683a73671f8","url":"assets/js/22c3a07e.4b4c4682.js"},{"revision":"10d7dd0935e40a1a8e4389aa76948883","url":"assets/js/230.76dec31f.js"},{"revision":"5cbaf2e59fa1c2a03605c1c9a815285c","url":"assets/js/25ef7947.b1e19c5a.js"},{"revision":"d701af819b6fe7efb6bfacc9f393038a","url":"assets/js/26455d6c.bfb0d4e6.js"},{"revision":"eee2d79c51e714988ef1d1fc1eca1a28","url":"assets/js/28a593c7.0e8aa4e4.js"},{"revision":"4011110834daa38ca8c2ebeaac560e35","url":"assets/js/29b44638.d7c313b5.js"},{"revision":"014909ffeb0c1c2973b22a19aeb1fc16","url":"assets/js/2ab4562b.90c477f8.js"},{"revision":"53ccd4b9969776deb2a4b43ee19e64cc","url":"assets/js/30d27832.0a1d3806.js"},{"revision":"13614ed84deec38bc4b065f71f5e924d","url":"assets/js/31058b07.14048cd2.js"},{"revision":"6bae60a3d21efcc2114737b29004536f","url":"assets/js/3152febb.72d1de31.js"},{"revision":"701353e19678b76c91876bbcbf3853d8","url":"assets/js/316.38c29d29.js"},{"revision":"b44c2fcea52f6038f1b6c6dd60f23bfb","url":"assets/js/391d9c20.b37619c9.js"},{"revision":"a1611d1d91bd16908abe1122e12d5e1e","url":"assets/js/3aefb2a9.1854ff2c.js"},{"revision":"eea7370269ba7ebd4e7339f8bf523bc3","url":"assets/js/3ebc3d67.5133970c.js"},{"revision":"8fc121177a1cbe71a3bdd80ed1ff8e35","url":"assets/js/3fb3fb7f.b2308ff7.js"},{"revision":"e95edcb5ab0eb6aa43c2478e55e67dfe","url":"assets/js/487.95e2457d.js"},{"revision":"e521682a923050453e1281fea7a24590","url":"assets/js/487f4407.5620b62f.js"},{"revision":"bb38f4b26e800a12edce759b245685ab","url":"assets/js/4972.a0723838.js"},{"revision":"e7d1516057369b045100dfbfb57a1518","url":"assets/js/4ca25bb5.d532b133.js"},{"revision":"6120a03c3ddffd6bdd3059917a9fe02b","url":"assets/js/4d89cf04.53425821.js"},{"revision":"c2a7d2cea06227a3159a47318a1636d8","url":"assets/js/50bfad63.b4a6bc96.js"},{"revision":"1740531d2568caa2ec2ccd6a43b0bb5b","url":"assets/js/5131.fc6c05cb.js"},{"revision":"fd35ba2182070c5585328b57dab87a40","url":"assets/js/5283.a13d6ef9.js"},{"revision":"53a43aa4ca06be253d47a40ee6aa13ba","url":"assets/js/59190afd.4a525d05.js"},{"revision":"f45b87c0073f61c9adce3365f8489868","url":"assets/js/60418129.d0bc6b61.js"},{"revision":"09c409d17d330d97e619d3d3776088f6","url":"assets/js/62e3c86b.b742d7ab.js"},{"revision":"330a789979673a343ea4ca7446694788","url":"assets/js/6316.a7fccb13.js"},{"revision":"877c7771db8a2da70569fac888ef30bb","url":"assets/js/6459b84b.1a9dd1e9.js"},{"revision":"e83d91761a541c80c83205da15980669","url":"assets/js/6d39995a.759216b6.js"},{"revision":"651188da53c9260a55f30cff02f7057a","url":"assets/js/724.3403caac.js"},{"revision":"0aa1fce7a0750f6d8d7b696d3da966e6","url":"assets/js/7516947a.c2ec5911.js"},{"revision":"92d7c7d00dd94075a7b9db52254c0e2d","url":"assets/js/76be5683.45549aa8.js"},{"revision":"28089d252ab99fa8ce308c0eae08949c","url":"assets/js/7724.a79f1847.js"},{"revision":"058d164d15dd00a6783af9be00255190","url":"assets/js/77db9a17.4f327571.js"},{"revision":"00e5828889d9d666acd7d29847a3ed79","url":"assets/js/801e3691.3152b3b4.js"},{"revision":"f511bcb11bde90777c2a59d49c59fbfd","url":"assets/js/84dac133.3d8ac9bc.js"},{"revision":"5ebce83383b996bf52aa52e66893a18c","url":"assets/js/935f2afb.c6181544.js"},{"revision":"8ca8be770a56902b7d5431aa26e4215c","url":"assets/js/9487.fe42c1ae.js"},{"revision":"d741b3a8d4d789655387361f28f2e220","url":"assets/js/94cba6ed.092112c0.js"},{"revision":"ee45e40d754b4812d0f513425c0ebed2","url":"assets/js/98b8cc29.c313b4ea.js"},{"revision":"d3723e1f2726f571de274707ab8aa639","url":"assets/js/9dd8a0d2.fdb38745.js"},{"revision":"539e5a639a993f8e2c9adbb1971a727b","url":"assets/js/9f958c7d.5bf92c68.js"},{"revision":"8aebf050cb3e6e0f7339f50fbecd3f0c","url":"assets/js/a21dcd43.ff4efb11.js"},{"revision":"0ca36d5825493447e52ed4d53e8afaf8","url":"assets/js/a2c501c8.0d37ed48.js"},{"revision":"99cbcc5a4bac2c9d932da68381a6269a","url":"assets/js/a7402ea8.7153bbb7.js"},{"revision":"99d7d4e23440559959910a7342b77bfd","url":"assets/js/bfc34fa7.2bba80ea.js"},{"revision":"b20f0cca810aaf24da177ade7eb1ab0a","url":"assets/js/bfc576a4.c09f925d.js"},{"revision":"a8510ad67f902ff578f1732f767ef1c9","url":"assets/js/c24fb5a2.dddd9dc8.js"},{"revision":"5dc7bddfda53512ba49807b35feca781","url":"assets/js/cb55cfb3.a54cb5b6.js"},{"revision":"316edfa8e34cae0786be58ea94d71477","url":"assets/js/d550161c.abbe48af.js"},{"revision":"5a2bf5ea31f7af9ff2137f0fbeff5f3d","url":"assets/js/e2eeca55.0dd5d0dc.js"},{"revision":"87b494736d65f06461b5582377ea53f3","url":"assets/js/ead3bc46.c3065b84.js"},{"revision":"06f71adcfff219a284b0655c21b3c956","url":"assets/js/f210ba15.9eb82c11.js"},{"revision":"d9bd9950f1bda7f435e86a99054dca4d","url":"assets/js/f9e13beb.4a01e5bf.js"},{"revision":"fdbe0300a1695e494494e45cb94b3e78","url":"assets/js/main.e6977ab9.js"},{"revision":"5c09801a71f3b4d86836114a99651552","url":"assets/js/runtime~main.91108f77.js"},{"revision":"0dd09dc1fc509cf21fe65a9bfafb5f2f","url":"css/alert.css"},{"revision":"26eccd25118cde31ccb1092089f7e247","url":"css/footer.css"},{"revision":"6b15459ec3386f0e86f1d9536797035c","url":"css/markdown.css"},{"revision":"bd1fe6dc29bd206538887be781c81aec","url":"css/navbar.css"},{"revision":"cd9fc23096ff65c105116be0d14a8876","url":"css/root.css"},{"revision":"b88bb93b23fdbf0d75ee3c80c4d6e6fa","url":"css/sidebar.css"},{"revision":"d85a13f48184e29f22ace304a716aadc","url":"css/toc.css"},{"revision":"34c77c35a4040d68db1b755b29ef386b","url":"css/video.css"},{"revision":"387cfd78fae80ea5bf833ceab5d698c4","url":"docs/architecture-concepts.html"},{"revision":"d60ef4bf7558cffc92ea5a473c394355","url":"docs/architecture-concepts/application-lifecycle.html"},{"revision":"6125183fa53d3e7069987f99db526ed8","url":"docs/architecture-concepts/facades.html"},{"revision":"e9647c288a23ff97e5705d4d6d29e49c","url":"docs/architecture-concepts/service-container.html"},{"revision":"c3a3889aeba74fce3081923bdff53a79","url":"docs/architecture-concepts/service-providers.html"},{"revision":"761594017feb8f496a358eae4683a4b5","url":"docs/cli-application.html"},{"revision":"563a98a7f3988983567b5bc3ca723470","url":"docs/cli-application/commands.html"},{"revision":"fe8f23db658891dcee42725af3dc877d","url":"docs/cli-application/error-handling.html"},{"revision":"b36f0c4e366abb91c0d191dd31233970","url":"docs/cli-application/publishing.html"},{"revision":"d1e8be0b340fcdccb4c357aa72a51760","url":"docs/cli-application/running.html"},{"revision":"3e297a8228c3efddd15f1cb55d655db4","url":"docs/digging-deeper.html"},{"revision":"dc44ebc7f3517bb621caeccaf89221ee","url":"docs/digging-deeper/collections.html"},{"revision":"af8002a5e573b3d591392d30a9a80ebf","url":"docs/digging-deeper/graceful-shutdown.html"},{"revision":"4c9ced0ac40f3ec22e734d613ae8448f","url":"docs/digging-deeper/library-development.html"},{"revision":"0beaafffad9b29ecc47f5d3caf65f497","url":"docs/digging-deeper/mail.html"},{"revision":"78d3f93aeffece3f7d25632db28150db","url":"docs/digging-deeper/repl.html"},{"revision":"43578a91a9aa53161dab774f41246050","url":"docs/getting-started.html"},{"revision":"e8eebfd809eef32895f42232ba9a2f50","url":"docs/getting-started/athennarc-file.html"},{"revision":"ede777fcc36871cb13bb534f3b2689ac","url":"docs/getting-started/configuration.html"},{"revision":"f5711cf931c895e09386693d7a4cf2f4","url":"docs/getting-started/directory-structure.html"},{"revision":"8e26979a0264d4fd86522e225c5525f2","url":"docs/getting-started/installation.html"},{"revision":"88563f69377e9c172dd9a8678525b8a3","url":"docs/introduction.html"},{"revision":"d2b544440d5dc658337e7cafa625a673","url":"docs/introduction/benchmarks.html"},{"revision":"ab16781cda4e894a1ae425d02e439b69","url":"docs/introduction/welcome.html"},{"revision":"8af01f0ea34a65c2841e708a1c68c0dc","url":"docs/rest-api-application.html"},{"revision":"922d57392d640e8693f253879d6c07bb","url":"docs/rest-api-application/controllers.html"},{"revision":"f29373c18dce8a7606a1d90898a194c5","url":"docs/rest-api-application/error-handling.html"},{"revision":"40025136641b74c435189cecb378f3da","url":"docs/rest-api-application/middlewares.html"},{"revision":"70cc5348d923b1ccd71cef4371599c6f","url":"docs/rest-api-application/rate-limiting.html"},{"revision":"ae2d49b8a89a5e64762d6f90466673bb","url":"docs/rest-api-application/request-context.html"},{"revision":"a9fd4fe52416b129f6012fac2874760e","url":"docs/rest-api-application/routing.html"},{"revision":"6a3573e2f3015356fd09507101594910","url":"docs/rest-api-application/security-with-helmet.html"},{"revision":"1593c5151e9d133dcbc4179565a2eeb2","url":"docs/rest-api-application/swagger-documentation.html"},{"revision":"ab3ffa0239a2e624c849033d02dee186","url":"docs/rest-api-application/tracing-requests.html"},{"revision":"3108cbb9afa249ffdd1d3d32dbe92c43","url":"docs/testing.html"},{"revision":"3c5e4ff910493564ad2c704581e88d6f","url":"docs/testing/cli-tests.html"},{"revision":"15999c1baaf93d63678198887585a675","url":"docs/testing/getting-started.html"},{"revision":"0826100f171e3ee81d9b0e38628b9ab1","url":"docs/testing/mocking.html"},{"revision":"2b4829719a82268b28d70f5be1bf2498","url":"docs/testing/rest-api-testing.html"},{"revision":"a373a3f9f04d3ef9f47ee8f733a6819a","url":"docs/the-basics.html"},{"revision":"7258ddd6dcb19cb2eb767dfe11afe1f0","url":"docs/the-basics/compilation.html"},{"revision":"65c590adc0d6e51a5a0c980115d971fc","url":"docs/the-basics/deployment.html"},{"revision":"936c39d98ea04649a9c9129fe2617d82","url":"docs/the-basics/helpers.html"},{"revision":"9387387f0a5d5633fad5f4f970520e57","url":"docs/the-basics/logging.html"},{"revision":"e5b8e7520f3847831c756060206a4e92","url":"docs/the-basics/views.html"},{"revision":"d087f9b4422bc23ce03e5108403010a8","url":"index.html"},{"revision":"582e41defaede7fb983d7cef696b4a69","url":"manifest.json"},{"revision":"8819ca59541f4814b6a55fcf66ecabbe","url":"img/examples/artisan-ui.png"},{"revision":"5a842a80da3f7052d79847910389ecf9","url":"img/favicons/favicon.ico"},{"revision":"d72ef880b711475e5291c0fdfb1964b3","url":"img/logos/athena.png"},{"revision":"5a842a80da3f7052d79847910389ecf9","url":"img/logos/logo.png"},{"revision":"5a035eb6229fc8d85a51b75cf458c2f1","url":"img/pre-visualization/og.jpg"},{"revision":"9fc10a629a1d43baa01c1ec8188ea3b7","url":"assets/fonts/AbrilText-Bold-a88da6fa9906de9747b0f1f11f9bd02d.woff2"},{"revision":"38d2d7a80eba1f9ba7bbcafed917c96c","url":"assets/fonts/AbrilText-Bold-f674a8f925701e9ea5db71341356a8c6.woff"},{"revision":"38d2d7a80eba1f9ba7bbcafed917c96c","url":"fonts/AbrilText-Bold.woff"},{"revision":"9fc10a629a1d43baa01c1ec8188ea3b7","url":"fonts/AbrilText-Bold.woff2"}]; + const precacheManifest = [{"revision":"076eab4c02bce8186c7c8bdee7bc4237","url":"404.html"},{"revision":"72272eb0b515a05ed971b092c3d603b2","url":"assets/css/styles.fb5f6248.css"},{"revision":"6102ecf9c1acca147c59a56d9476bfe8","url":"assets/js/08133570.d1e503b1.js"},{"revision":"883385237362ae584c12ac13b8033a90","url":"assets/js/0b6406e9.7c909a8f.js"},{"revision":"f1ec9bd8f24f74c2803a00ca3c32f772","url":"assets/js/1068.091ab1fc.js"},{"revision":"83d10b4a6a058dec22e4a531825df123","url":"assets/js/14eb3368.b6cea2b5.js"},{"revision":"e3dfbe867f84a2f27b88ef1b3068a4b1","url":"assets/js/17896441.77555dfe.js"},{"revision":"d95e33b7be4c6e0758f8bd4c53661640","url":"assets/js/1be78505.bcd357af.js"},{"revision":"5547bdacee5225bf0b5cfd01870a47bf","url":"assets/js/1bfe5704.c29e2639.js"},{"revision":"ca80f7605cde7b8d9e8629e4e565cb4c","url":"assets/js/1f33cfc6.16c8544e.js"},{"revision":"aa5a085afe6b2d8c0c15a63e3ba618bc","url":"assets/js/205e281e.9a4b1c29.js"},{"revision":"d62dee970a6f775bcedf1683a73671f8","url":"assets/js/22c3a07e.4b4c4682.js"},{"revision":"10d7dd0935e40a1a8e4389aa76948883","url":"assets/js/230.76dec31f.js"},{"revision":"5cbaf2e59fa1c2a03605c1c9a815285c","url":"assets/js/25ef7947.b1e19c5a.js"},{"revision":"d701af819b6fe7efb6bfacc9f393038a","url":"assets/js/26455d6c.bfb0d4e6.js"},{"revision":"eee2d79c51e714988ef1d1fc1eca1a28","url":"assets/js/28a593c7.0e8aa4e4.js"},{"revision":"4011110834daa38ca8c2ebeaac560e35","url":"assets/js/29b44638.d7c313b5.js"},{"revision":"d5258c58149c0154099a2a7ed9bf5dde","url":"assets/js/2ab4562b.19a1dc7c.js"},{"revision":"53ccd4b9969776deb2a4b43ee19e64cc","url":"assets/js/30d27832.0a1d3806.js"},{"revision":"13614ed84deec38bc4b065f71f5e924d","url":"assets/js/31058b07.14048cd2.js"},{"revision":"6bae60a3d21efcc2114737b29004536f","url":"assets/js/3152febb.72d1de31.js"},{"revision":"701353e19678b76c91876bbcbf3853d8","url":"assets/js/316.38c29d29.js"},{"revision":"b44c2fcea52f6038f1b6c6dd60f23bfb","url":"assets/js/391d9c20.b37619c9.js"},{"revision":"a1611d1d91bd16908abe1122e12d5e1e","url":"assets/js/3aefb2a9.1854ff2c.js"},{"revision":"eea7370269ba7ebd4e7339f8bf523bc3","url":"assets/js/3ebc3d67.5133970c.js"},{"revision":"8fc121177a1cbe71a3bdd80ed1ff8e35","url":"assets/js/3fb3fb7f.b2308ff7.js"},{"revision":"e95edcb5ab0eb6aa43c2478e55e67dfe","url":"assets/js/487.95e2457d.js"},{"revision":"e521682a923050453e1281fea7a24590","url":"assets/js/487f4407.5620b62f.js"},{"revision":"bb38f4b26e800a12edce759b245685ab","url":"assets/js/4972.a0723838.js"},{"revision":"e7d1516057369b045100dfbfb57a1518","url":"assets/js/4ca25bb5.d532b133.js"},{"revision":"6120a03c3ddffd6bdd3059917a9fe02b","url":"assets/js/4d89cf04.53425821.js"},{"revision":"c2a7d2cea06227a3159a47318a1636d8","url":"assets/js/50bfad63.b4a6bc96.js"},{"revision":"1740531d2568caa2ec2ccd6a43b0bb5b","url":"assets/js/5131.fc6c05cb.js"},{"revision":"fd35ba2182070c5585328b57dab87a40","url":"assets/js/5283.a13d6ef9.js"},{"revision":"53a43aa4ca06be253d47a40ee6aa13ba","url":"assets/js/59190afd.4a525d05.js"},{"revision":"f45b87c0073f61c9adce3365f8489868","url":"assets/js/60418129.d0bc6b61.js"},{"revision":"09c409d17d330d97e619d3d3776088f6","url":"assets/js/62e3c86b.b742d7ab.js"},{"revision":"330a789979673a343ea4ca7446694788","url":"assets/js/6316.a7fccb13.js"},{"revision":"877c7771db8a2da70569fac888ef30bb","url":"assets/js/6459b84b.1a9dd1e9.js"},{"revision":"e83d91761a541c80c83205da15980669","url":"assets/js/6d39995a.759216b6.js"},{"revision":"651188da53c9260a55f30cff02f7057a","url":"assets/js/724.3403caac.js"},{"revision":"0aa1fce7a0750f6d8d7b696d3da966e6","url":"assets/js/7516947a.c2ec5911.js"},{"revision":"92d7c7d00dd94075a7b9db52254c0e2d","url":"assets/js/76be5683.45549aa8.js"},{"revision":"28089d252ab99fa8ce308c0eae08949c","url":"assets/js/7724.a79f1847.js"},{"revision":"058d164d15dd00a6783af9be00255190","url":"assets/js/77db9a17.4f327571.js"},{"revision":"00e5828889d9d666acd7d29847a3ed79","url":"assets/js/801e3691.3152b3b4.js"},{"revision":"f511bcb11bde90777c2a59d49c59fbfd","url":"assets/js/84dac133.3d8ac9bc.js"},{"revision":"5ebce83383b996bf52aa52e66893a18c","url":"assets/js/935f2afb.c6181544.js"},{"revision":"8ca8be770a56902b7d5431aa26e4215c","url":"assets/js/9487.fe42c1ae.js"},{"revision":"d741b3a8d4d789655387361f28f2e220","url":"assets/js/94cba6ed.092112c0.js"},{"revision":"ee45e40d754b4812d0f513425c0ebed2","url":"assets/js/98b8cc29.c313b4ea.js"},{"revision":"d3723e1f2726f571de274707ab8aa639","url":"assets/js/9dd8a0d2.fdb38745.js"},{"revision":"539e5a639a993f8e2c9adbb1971a727b","url":"assets/js/9f958c7d.5bf92c68.js"},{"revision":"8aebf050cb3e6e0f7339f50fbecd3f0c","url":"assets/js/a21dcd43.ff4efb11.js"},{"revision":"0ca36d5825493447e52ed4d53e8afaf8","url":"assets/js/a2c501c8.0d37ed48.js"},{"revision":"99cbcc5a4bac2c9d932da68381a6269a","url":"assets/js/a7402ea8.7153bbb7.js"},{"revision":"99d7d4e23440559959910a7342b77bfd","url":"assets/js/bfc34fa7.2bba80ea.js"},{"revision":"b20f0cca810aaf24da177ade7eb1ab0a","url":"assets/js/bfc576a4.c09f925d.js"},{"revision":"a8510ad67f902ff578f1732f767ef1c9","url":"assets/js/c24fb5a2.dddd9dc8.js"},{"revision":"5dc7bddfda53512ba49807b35feca781","url":"assets/js/cb55cfb3.a54cb5b6.js"},{"revision":"316edfa8e34cae0786be58ea94d71477","url":"assets/js/d550161c.abbe48af.js"},{"revision":"5a2bf5ea31f7af9ff2137f0fbeff5f3d","url":"assets/js/e2eeca55.0dd5d0dc.js"},{"revision":"87b494736d65f06461b5582377ea53f3","url":"assets/js/ead3bc46.c3065b84.js"},{"revision":"06f71adcfff219a284b0655c21b3c956","url":"assets/js/f210ba15.9eb82c11.js"},{"revision":"d9bd9950f1bda7f435e86a99054dca4d","url":"assets/js/f9e13beb.4a01e5bf.js"},{"revision":"fdbe0300a1695e494494e45cb94b3e78","url":"assets/js/main.e6977ab9.js"},{"revision":"5807ec1592b8196afecc68583f3b83ea","url":"assets/js/runtime~main.fa1f4b19.js"},{"revision":"0dd09dc1fc509cf21fe65a9bfafb5f2f","url":"css/alert.css"},{"revision":"26eccd25118cde31ccb1092089f7e247","url":"css/footer.css"},{"revision":"6b15459ec3386f0e86f1d9536797035c","url":"css/markdown.css"},{"revision":"bd1fe6dc29bd206538887be781c81aec","url":"css/navbar.css"},{"revision":"cd9fc23096ff65c105116be0d14a8876","url":"css/root.css"},{"revision":"b88bb93b23fdbf0d75ee3c80c4d6e6fa","url":"css/sidebar.css"},{"revision":"d85a13f48184e29f22ace304a716aadc","url":"css/toc.css"},{"revision":"34c77c35a4040d68db1b755b29ef386b","url":"css/video.css"},{"revision":"14ee3c1af1185267f9eb6f9aed0a3704","url":"docs/architecture-concepts.html"},{"revision":"2dd19a419545c1a8c29074db707a9b33","url":"docs/architecture-concepts/application-lifecycle.html"},{"revision":"885cc7e27e38c0f0164bc4485aea7757","url":"docs/architecture-concepts/facades.html"},{"revision":"9f08f5d7211cec6d2c032c4a82a5b3d6","url":"docs/architecture-concepts/service-container.html"},{"revision":"d7021ec77b310b82f43fe839f1cd1441","url":"docs/architecture-concepts/service-providers.html"},{"revision":"a5283b6f9d01a9283f85cbfe7d2e76d5","url":"docs/cli-application.html"},{"revision":"55ef3f9361f458b56f4e81e12a50e7eb","url":"docs/cli-application/commands.html"},{"revision":"6a2c8568a97f4fe01b8d1f983fdba5a3","url":"docs/cli-application/error-handling.html"},{"revision":"43423241de1674ec927af0d503b5b10b","url":"docs/cli-application/publishing.html"},{"revision":"305cc5df13e382954b694ead6c361d24","url":"docs/cli-application/running.html"},{"revision":"f1218f066aeb48ac0d28cb0dfff5a17b","url":"docs/digging-deeper.html"},{"revision":"81c2f0da52f02a2b124e763e82dd5d8e","url":"docs/digging-deeper/collections.html"},{"revision":"8814aaad5743ef599b3a286a8a0c50aa","url":"docs/digging-deeper/graceful-shutdown.html"},{"revision":"ea3a14b246439b3aebd520101eb2aeb0","url":"docs/digging-deeper/library-development.html"},{"revision":"6385a82d698339ab55f499c7610ce8de","url":"docs/digging-deeper/mail.html"},{"revision":"e0d243c53e7c48793c2d4e6f2c9844f7","url":"docs/digging-deeper/repl.html"},{"revision":"d3185a340a169e8bc9005f37462a467b","url":"docs/getting-started.html"},{"revision":"508048af06c512e0f03010c23b0f738c","url":"docs/getting-started/athennarc-file.html"},{"revision":"ad0bcba8682fe3fb8ac39d58372cd80b","url":"docs/getting-started/configuration.html"},{"revision":"48dd990bf32b23015ddd9604894c841d","url":"docs/getting-started/directory-structure.html"},{"revision":"ba506ab93ac99508fecb9a24133c61ea","url":"docs/getting-started/installation.html"},{"revision":"3743e5d553c691bb98f4bd5a46e1fd95","url":"docs/introduction.html"},{"revision":"5bb91856b1dba25576506f79c35e7690","url":"docs/introduction/benchmarks.html"},{"revision":"3f039c3109807cbe28e89109ef4b1bd7","url":"docs/introduction/welcome.html"},{"revision":"c11325495592601d8577e8d0c06cd43e","url":"docs/rest-api-application.html"},{"revision":"7908bec80f39bbfcf007cb86484b487c","url":"docs/rest-api-application/controllers.html"},{"revision":"3e94ec6f385c102d67c139712a4992da","url":"docs/rest-api-application/error-handling.html"},{"revision":"2509e8eded47b0a716d0ed0361e35e58","url":"docs/rest-api-application/middlewares.html"},{"revision":"6399e7a30c240f773b858688296375fb","url":"docs/rest-api-application/rate-limiting.html"},{"revision":"2123d7309034b5413e5eafe72110e1d3","url":"docs/rest-api-application/request-context.html"},{"revision":"c421027c686f543381a07457c1dbb3af","url":"docs/rest-api-application/routing.html"},{"revision":"f7fbdec605f4714a6f1f65c202e4a97e","url":"docs/rest-api-application/security-with-helmet.html"},{"revision":"e562d909c8d994eb11ca3c41faef5039","url":"docs/rest-api-application/swagger-documentation.html"},{"revision":"431539079642303311f0d588ef3f49c8","url":"docs/rest-api-application/tracing-requests.html"},{"revision":"acfa93654b772143f06cff388aecbb07","url":"docs/testing.html"},{"revision":"53a8088dbce7c3df79bd4c436470c8d9","url":"docs/testing/cli-tests.html"},{"revision":"13d98b9ce4c2bf43e7369833138631a7","url":"docs/testing/getting-started.html"},{"revision":"fbe5292deff9f85dd9935920472920df","url":"docs/testing/mocking.html"},{"revision":"d5c2e02024264d5332fa293428219ec4","url":"docs/testing/rest-api-testing.html"},{"revision":"0401553b5e99d02ad7ca5c58e74e744a","url":"docs/the-basics.html"},{"revision":"4b5a849b9a828addd78ee9fde08d6c45","url":"docs/the-basics/compilation.html"},{"revision":"583a0fe86936040fe80d12839c1e0eba","url":"docs/the-basics/deployment.html"},{"revision":"2fe451e9895c8ac2d51192c14247ae13","url":"docs/the-basics/helpers.html"},{"revision":"b883da3654e33646483644369b562397","url":"docs/the-basics/logging.html"},{"revision":"fbbe4ede879888475ee17d86634685f5","url":"docs/the-basics/views.html"},{"revision":"0cebd0b0dc09a98bb351d1e96809d92f","url":"index.html"},{"revision":"582e41defaede7fb983d7cef696b4a69","url":"manifest.json"},{"revision":"8819ca59541f4814b6a55fcf66ecabbe","url":"img/examples/artisan-ui.png"},{"revision":"5a842a80da3f7052d79847910389ecf9","url":"img/favicons/favicon.ico"},{"revision":"d72ef880b711475e5291c0fdfb1964b3","url":"img/logos/athena.png"},{"revision":"5a842a80da3f7052d79847910389ecf9","url":"img/logos/logo.png"},{"revision":"5a035eb6229fc8d85a51b75cf458c2f1","url":"img/pre-visualization/og.jpg"},{"revision":"9fc10a629a1d43baa01c1ec8188ea3b7","url":"assets/fonts/AbrilText-Bold-a88da6fa9906de9747b0f1f11f9bd02d.woff2"},{"revision":"38d2d7a80eba1f9ba7bbcafed917c96c","url":"assets/fonts/AbrilText-Bold-f674a8f925701e9ea5db71341356a8c6.woff"},{"revision":"38d2d7a80eba1f9ba7bbcafed917c96c","url":"fonts/AbrilText-Bold.woff"},{"revision":"9fc10a629a1d43baa01c1ec8188ea3b7","url":"fonts/AbrilText-Bold.woff2"}]; const controller = new workbox_precaching__WEBPACK_IMPORTED_MODULE_0__.PrecacheController({ // Safer to turn this true? fallbackToNetwork: true,