diff --git a/docs/cli-application/running.mdx b/docs/cli-application/running.mdx index ab2a662b..ef30a5d5 100644 --- a/docs/cli-application/running.mdx +++ b/docs/cli-application/running.mdx @@ -63,8 +63,8 @@ yourCliCommand --help When running your CLI without any option and command, the display name will be rendered in the terminal using -[`chalk-rainbow`](https://www.npmjs.com/package/chalk-rainbow) -and [`figlet`](https://www.npmjs.com/package/figlet). +[chalk-rainbow](https://www.npmjs.com/package/chalk-rainbow) +and [figlet](https://www.npmjs.com/package/figlet). By default Artisan always display the `Artisan` name, but you can change it for your own display name by setting the `displayName` diff --git a/docs/digging-deeper/collections.mdx b/docs/digging-deeper/collections.mdx index 7f9cbe7b..d6321065 100644 --- a/docs/digging-deeper/collections.mdx +++ b/docs/digging-deeper/collections.mdx @@ -18,7 +18,7 @@ check out the following code. We'll create a new instance of `Collection` using get all elements where the id is **1, 2 or 3**, order everything in ascending mode by **name** and then get only the value of the property `name` of each one of the elements: -```javascript +```typescript const users = [ { id: 1, name: 'Marcelo Oliveira'}, { id: 2, name: 'Vinicius Campelo' }, @@ -49,13 +49,13 @@ array. In general, collections are immutable, meaning every Collection method re As you can see in the example above, creating a collection is as simples as: -```javascript +```typescript const collection = new Collection([1, 2, 3]) ``` Simplifying even more: Athenna has extended the `Array` class to simply convert an array to a collection using the `toCollection` method: -```javascript +```typescript const numbers = [1, 2, 3] const collection = numbers.toCollection() @@ -73,7 +73,7 @@ Collections are extendable, which allows you to add additional methods to the Co other methods via `this`, just as if it were a real method of the collection class. For example, the following code adds a `toUpper` method to the `Collection` class: -```javascript +```typescript import { Collection } from '@athenna/common' Collection.macro('toUpper', function () { @@ -96,7 +96,7 @@ a [service provider](/docs/architecture-concepts/providers). If necessary, you may define macros that accept additional arguments: -```javascript +```typescript Collection.macro('remove', function (key) { return this.map(item => { if (item[key]) { diff --git a/docs/digging-deeper/repl.mdx b/docs/digging-deeper/repl.mdx index 4ddbfb08..62d6719d 100644 --- a/docs/digging-deeper/repl.mdx +++ b/docs/digging-deeper/repl.mdx @@ -48,7 +48,7 @@ When running this command, Athenna will use the To import modules inside REPL you need to use dynamic imports: -```javascript +```typescript { Log } = await import('@athenna/logger') // Destructuring import helpers = await import('#app/helpers/index') // Default import ``` diff --git a/docs/rest-api-application/rate-limiting.mdx b/docs/rest-api-application/rate-limiting.mdx index 033fd576..db04ac0c 100644 --- a/docs/rest-api-application/rate-limiting.mdx +++ b/docs/rest-api-application/rate-limiting.mdx @@ -24,7 +24,7 @@ plugin inside `HttpKernel`. All the configurations that `@fastify/rate-limit` supports can be set inside `Path.config('http.ts')` file in the `rateLimit` object: -```typescript +```typescript title="Path.config('http.ts')" export default { rateLimit: { global: true, @@ -46,7 +46,7 @@ for specific routes. You can also disable the `global` option of your `rateLimit` configuration in `Path.config('http.ts')` and set different rules in your routes: -```typescript +```typescript title="Path.route('http.ts')" Route .get('/hello', 'WelcomeController.show') .rateLimit({ max: 1, timeWindow: '1 minute' }) 👈 @@ -58,7 +58,7 @@ You can also use the `rateLimit()` method in route groups. This will set the same configuration for all routes inside the group: -```typescript +```typescript title="Path.route('http.ts')" Route.group(() => { Route.get('/hello', 'WelcomeController.show') }).rateLimit({ max: 1, timeWindow: '1 minute' }) 👈 @@ -76,7 +76,7 @@ to create "defaults" configurations for all routes. Same behavior as route groups, but for resources: -```typescript +```typescript title="Path.route('http.ts')" // Set the same configurations for all routes of resource Route.resource('/tests', 'WelcomeController').rateLimit({...}) diff --git a/docs/rest-api-application/security-with-helmet.mdx b/docs/rest-api-application/security-with-helmet.mdx new file mode 100644 index 00000000..9892d178 --- /dev/null +++ b/docs/rest-api-application/security-with-helmet.mdx @@ -0,0 +1,16 @@ +--- +title: Security with Helmet +sidebar_position: 9 +description: See how to improve the security of your REST API with Helmet in Athenna. +tags: + - REST API Application + - Security with Helmet +--- + +# Security with Helmet + +See how to improve the security of your REST API with Helmet in Athenna. + +## Introduction + +Coming soon diff --git a/docs/rest-api-application/swagger.mdx b/docs/rest-api-application/swagger-documentation.mdx similarity index 93% rename from docs/rest-api-application/swagger.mdx rename to docs/rest-api-application/swagger-documentation.mdx index 17fbec6b..abc501e9 100644 --- a/docs/rest-api-application/swagger.mdx +++ b/docs/rest-api-application/swagger-documentation.mdx @@ -1,10 +1,10 @@ --- -title: Swagger +title: Swagger Documentation sidebar_position: 6 description: See how to create the Swagger documentation for Athenna REST API application. tags: - REST API Application - - Swagger + - Swagger Documentation --- # Swagger @@ -27,7 +27,7 @@ supports can be set inside `Path.config('http.ts')` file in the `swagger.configu object. And all the configurations that `@fastify/swagger-ui` supports can be set inside `Path.config('http.ts')` file in the `swagger.ui` object: -```typescript +```typescript title="Path.config('http.ts')" export default { swagger: { ui: { @@ -60,7 +60,7 @@ export default { You can set your Swagger configurations using the `Route` facade in `routes/http.js` file: -```typescript +```typescript title="Path.route('http.ts')" Route.get('/hello', 'WelcomeController.show') .summary('Hello route') .tags('hello', 'world') @@ -80,7 +80,7 @@ Route.get('/hello', 'WelcomeController.show') You can also use the `swagger()` method and use the same configurations of `@fastify/swagger` plugin: -```typescript +```typescript title="Path.route('http.ts')" Route.get('/hello', 'WelcomeController.show').swagger({ summary: 'Hello route', tags: ['hello', 'world'], @@ -111,7 +111,7 @@ You can also use all the swagger methods in route groups. This will set the same configuration for all routes inside the group: -```javascript +```typescript title="Path.route('http.ts')" Route.group(() => { Route.get('/hello', 'WelcomeController.show').summary('Hello route') }).swagger({...}) @@ -129,7 +129,7 @@ configurations for all routes such as `security`. Same behavior as route groups, but for resources: -```javascript +```typescript title="Path.route('http.ts')" // Set the same configurations for all routes of resource Route.resource('/tests', 'WelcomeController').swagger({...}) diff --git a/docs/rest-api-application/tracing-requests.mdx b/docs/rest-api-application/tracing-requests.mdx index bdda553a..fd704b61 100644 --- a/docs/rest-api-application/tracing-requests.mdx +++ b/docs/rest-api-application/tracing-requests.mdx @@ -26,7 +26,7 @@ plugin inside `HttpKernel`. All the configurations that `cls-rtracer` supports can be set inside `Path.config('http.ts')` file in the `rTracer` object: -```typescript +```typescript title="Path.config('http.ts')" export default { trace: true, rTracer: { @@ -43,7 +43,7 @@ plugin will be enabled and a UUID will be generated for each request. This UUID will be available in `request.id` property of your routes: -```typescript +```typescript title="Path.routes('http.ts')" import { Log } from '@athenna/logger' import { Route } from '@athenna/http' @@ -58,7 +58,7 @@ Route.get('/', ({ request }) => { Athenna request logger enabled by `http.logger` configuration will automatically log the request -ID for you. +ID for you depending on the formatter your are using. ::: diff --git a/docs/the-basics/helpers.mdx b/docs/the-basics/helpers.mdx index e0676a35..5861eda8 100644 --- a/docs/the-basics/helpers.mdx +++ b/docs/the-basics/helpers.mdx @@ -13,4 +13,330 @@ Understand how to use all the Athenna Helpers from @athenna/common and other pac ## Introduction +Athenna includes a variety of "helpers" classes inside +the `@athenna/common` package that comes by default +installed in your application. Many of these classes are +used by the framework itself; however, you are free to use +them in your own applications if you find them convenient. + +## Available helpers + +- [`File`](/docs/the-basics/helpers#file) - Create, copy, move, +delete and get information about files. +- [`Folder`](/docs/the-basics/helpers#folder) - Create, copy, move, +delete and get information about folders. + +### `File` + +Use the `File` class to create an instance of a file, it existing or not. + +#### `File.load()` & `File.loadSync()` + +Creates the file is does not exist and also load the file information: + +```typescript +import { File } from '@athenna/common' + +const existent = new File(Path.storage('existent.txt')) +const nonExistent = new File('./nonExistent.txt', 'File content') + +// Load the file info and content. +await existent.load({ withContent: true }) 👈 + +// Create and load the file info without the +// content (be careful when loading big files). +nonExistent.loadSync() 👈 +``` + +After loading process, the file will contain new informations: + +- createdAt - The date when the file was created. +- accessedAt - The date when the file was last accessed. +- modifiedAt - The date when the file was last modified. +- fileSize - The size of the file in MB. +- content - The content of the file as `Buffer` if `withContent` was `true`. + +#### `File.copy()` & `File.copySync()` + +Create a copy of the file in other location or with other name: + +```typescript +import { File } from '@athenna/common' + +const copiedFile = file.copySync('./copy-of-file.txt') +const copiedFile = await file.copy(Path.storage('copy-of-file.txt')) +``` + +To copy the file and load the content of the copy set the `withContent` +as `true`: + +```typescript +import { File } from '@athenna/common' + +const copiedFile = await file.copy(Path.storage('copy-of-file.txt'), { + withContent: true 👈 +}) +``` + +When copying the file you can set the `mockedValues` to `true` to create +a file with fake name: + +```typescript +import { File } from '@athenna/common' + +const copiedFile = await file.copy(Path.storage('copy-of-file.txt'), { + mockedValues: true 👈 +}) +``` + +#### `File.move()` & `File.moveSync()` + +Move the file to other location: + +```typescript +import { File } from '@athenna/common' + +const movedFile = file.moveSync('./move-of-file.txt') 👈 +const movedFile = await file.move(Path.storage('move-of-file.txt')) 👈 +``` + +To move the file and load the content of the move set the `withContent` +as `true`: + +```typescript +import { File } from '@athenna/common' + +const movedFile = await file.move(Path.storage('move-of-file.txt'), { + withContent: true 👈 +}) +``` + +When moving the file you can set the `mockedValues` to `true` to create +a file with fake name: + +```typescript +import { File } from '@athenna/common' + +const movedFile = await file.move(Path.storage('file-path.txt'), { + mockedValues: true 👈 +}) +``` + +#### `File.remove()` & `File.removeSync()` + +Delete a file from the file system: + +```typescript +import { File } from '@athenna/common' + +file.removeSync() 👈 +await file.remove() 👈 +``` + +#### `File.setContent()` & `File.setContentSync()` + +Set the content of a file overwriting the existing content: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.txt', 'Hello') + +file.setContentSync('Hello World!') 👈 +await file.setContent('Hello World!') 👈 +``` + +#### `File.getContent()` & `File.getContentSync()` + +Get the content of a file as `Buffer`: + +```typescript +import { File } from '@athenna/common' + +const contentBuffer = file.getContentSync() 👈 +const contentBuffer = await file.getContent() 👈 +``` + +To save the content of the file in the instance set the `saveContent` as `true`: + +```typescript +import { File } from '@athenna/common' + +const content = await file.getContent({ saveContent: true }) 👈 +``` + +#### `File.getContentAsString()` & `File.getContentAsStringSync()` + +Same behavior of `getContent()`/`getContentSync()`, but return the content +as `string`: + +```typescript +import { File } from '@athenna/common' + +const contentString = file.getContentAsStringSync() 👈 +const contentString = await file.getContentAsString() 👈 +``` + +#### `File.getContentAsJson()` & `File.getContentAsJsonSync()` + +Same behavior of `getContent()`/`getContentSync()`, but return the content as +`object` if the content is a valid JSON string: + +```typescript +import { File } from '@athenna/common' + +const contentJSON = file.getContentAsJsonSync() 👈 +const contentJSON = await file.getContentAsJson() 👈 +``` + +#### `File.getContentAsBuilder()` & `File.getContentAsBuilderSync()` + +Same behavior of `getContent()`/`getContentSync()`, but return the content as +an [`ObjectBuilder`](/docs/the-basics/helpers#object-builder) instance if the +content is a valid JSON string: + +```typescript +import { File } from '@athenna/common' + +const contentObjectBuilder = file.getContentAsBuilderSync() 👈 +const contentObjectBuilder = await file.getContentAsBuilder() 👈 +``` + +#### `File.append()` & `File.appendSync()` + +Add content to the end of the file: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.txt', 'Hello') + +file.appendSync(' World') 👈 +await file.append('!\n') 👈 +``` + +#### `File.prepend()` & `File.prependSync()` + +Add content to the top of the file: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.txt', 'World') + +file.prependSync('ello ') 👈 +await file.prepend('H') 👈 +``` + +#### `File.createReadStream()` + +Create a [readable stream](https://nodejs.org/api/stream.html#readable-streams) +instance of the file: + +```typescript +const stream = file.createReadStream() +``` + +#### `File.createWriteStream()` + +Create a [writable stream](https://nodejs.org/api/stream.html#writable-streams) +instance of the file: + +```typescript +const stream = file.createWriteStream() +``` + +#### `File.toJSON()` + +Get the informations of the file as JSON: + +```typescript +const infos = file.toJSON() 👈 +``` + +#### `File.import()` + +Import the file path if is a valid module: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.js', "console.log('hello')") + +const module = await file.import() 👈 +``` + +#### `File.safeImport()` + +Same as `import()` method, but if the file is not a valid module the exception +will be ignored: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.txt', "console.log('hello')") + +const module = await file.safeImport() 👈 +``` + +Importing files that got any errors like syntax errors will also not throw: + +```typescript +import { File } from '@athenna/common' + +const file = new File('./file.js', "console.log('hello") + +const module = await file.safeImport() 👈 // Nothing happens +``` + +#### `File::safeRemove()` + +Call for a delete operation without worrying about exceptions because the file +does not exist: + +```typescript +import { File } from '@athenna/common' + +await File.safeRemove(Path.storage('file.txt')) 👈 +await File.safeRemove(Path.storage('not-found.txt')) 👈 // Will not throw +``` + +#### `File::exists()` & `File::existsSync()` + +Verify if a file exists or not: + +```typescript +if (File.existsSync('package.json')) { + // do something +} + +if (await File.exists('package.json')) { + // do something +} +``` + +#### `File::isFile()` & `File::isFileSync()` + +Verify if a file is a valid file or not: + +```typescript +if (File.isFileSync('package.json')) { + // do something +} + +if (await File.isFile('package.json')) { + // do something +} +``` + +#### `File::createFileOfSize()` + +Create a fake file with determined size for testing purposes: + +```typescript +const file = await File.createFileOfSize('fake.js', 1024 * 1024 * 100) 👈 +``` + +### `Folder` + Coming soon