Skip to content

Commit 62107f6

Browse files
committed
Lesson 1.2 - Creating Our AdonisJS App with Inertia
0 parents  commit 62107f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+11119
-0
lines changed

.editorconfig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# http://editorconfig.org
2+
3+
[*]
4+
indent_style = space
5+
indent_size = 2
6+
end_of_line = lf
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = true
10+
11+
[*.json]
12+
insert_final_newline = unset
13+
14+
[**.min.js]
15+
indent_style = unset
16+
insert_final_newline = unset
17+
18+
[MakeFile]
19+
indent_style = space
20+
21+
[*.md]
22+
trim_trailing_whitespace = false

.env.example

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
TZ=UTC
2+
PORT=3333
3+
HOST=localhost
4+
LOG_LEVEL=info
5+
APP_KEY=uOJThCGLLmGc3SnrMbitajHWYbCCApjg
6+
NODE_ENV=development
7+
SESSION_DRIVER=cookie
8+
DB_HOST=127.0.0.1
9+
DB_PORT=5432
10+
DB_USER=postgres
11+
DB_PASSWORD=
12+
DB_DATABASE=

.gitignore

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Dependencies and AdonisJS build
2+
node_modules
3+
build
4+
tmp
5+
6+
# Secrets
7+
.env
8+
.env.local
9+
.env.production.local
10+
.env.development.local
11+
12+
# Frontend assets compiled code
13+
public/assets
14+
15+
# Build tools specific
16+
npm-debug.log
17+
yarn-error.log
18+
19+
# Editors specific
20+
.fleet
21+
.idea
22+
.vscode
23+
24+
# Platform specific
25+
.DS_Store

ace.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
|--------------------------------------------------------------------------
3+
| JavaScript entrypoint for running ace commands
4+
|--------------------------------------------------------------------------
5+
|
6+
| DO NOT MODIFY THIS FILE AS IT WILL BE OVERRIDDEN DURING THE BUILD
7+
| PROCESS.
8+
|
9+
| See docs.adonisjs.com/guides/typescript-build-process#creating-production-build
10+
|
11+
| Since, we cannot run TypeScript source code using "node" binary, we need
12+
| a JavaScript entrypoint to run ace commands.
13+
|
14+
| This file registers the "ts-node/esm" hook with the Node.js module system
15+
| and then imports the "bin/console.ts" file.
16+
|
17+
*/
18+
19+
/**
20+
* Register hook to process TypeScript files using ts-node
21+
*/
22+
import { register } from 'node:module'
23+
register('ts-node/esm', import.meta.url)
24+
25+
/**
26+
* Import ace console entrypoint
27+
*/
28+
await import('./bin/console.js')

adonisrc.ts

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { defineConfig } from '@adonisjs/core/app'
2+
3+
export default defineConfig({
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Commands
7+
|--------------------------------------------------------------------------
8+
|
9+
| List of ace commands to register from packages. The application commands
10+
| will be scanned automatically from the "./commands" directory.
11+
|
12+
*/
13+
commands: [() => import('@adonisjs/core/commands'), () => import('@adonisjs/lucid/commands')],
14+
15+
/*
16+
|--------------------------------------------------------------------------
17+
| Service providers
18+
|--------------------------------------------------------------------------
19+
|
20+
| List of service providers to import and register when booting the
21+
| application
22+
|
23+
*/
24+
providers: [
25+
() => import('@adonisjs/core/providers/app_provider'),
26+
() => import('@adonisjs/core/providers/hash_provider'),
27+
{
28+
file: () => import('@adonisjs/core/providers/repl_provider'),
29+
environment: ['repl', 'test'],
30+
},
31+
() => import('@adonisjs/core/providers/vinejs_provider'),
32+
() => import('@adonisjs/core/providers/edge_provider'),
33+
() => import('@adonisjs/session/session_provider'),
34+
() => import('@adonisjs/vite/vite_provider'),
35+
() => import('@adonisjs/shield/shield_provider'),
36+
() => import('@adonisjs/static/static_provider'),
37+
() => import('@adonisjs/cors/cors_provider'),
38+
() => import('@adonisjs/lucid/database_provider'),
39+
() => import('@adonisjs/auth/auth_provider'),
40+
() => import('@adonisjs/inertia/inertia_provider')
41+
],
42+
43+
/*
44+
|--------------------------------------------------------------------------
45+
| Preloads
46+
|--------------------------------------------------------------------------
47+
|
48+
| List of modules to import before starting the application.
49+
|
50+
*/
51+
preloads: [() => import('#start/routes'), () => import('#start/kernel')],
52+
53+
/*
54+
|--------------------------------------------------------------------------
55+
| Tests
56+
|--------------------------------------------------------------------------
57+
|
58+
| List of test suites to organize tests by their type. Feel free to remove
59+
| and add additional suites.
60+
|
61+
*/
62+
tests: {
63+
suites: [
64+
{
65+
files: ['tests/unit/**/*.spec(.ts|.js)'],
66+
name: 'unit',
67+
timeout: 2000,
68+
},
69+
{
70+
files: ['tests/functional/**/*.spec(.ts|.js)'],
71+
name: 'functional',
72+
timeout: 30000,
73+
},
74+
],
75+
forceExit: false,
76+
},
77+
78+
/*
79+
|--------------------------------------------------------------------------
80+
| Metafiles
81+
|--------------------------------------------------------------------------
82+
|
83+
| A collection of files you want to copy to the build folder when creating
84+
| the production build.
85+
|
86+
*/
87+
metaFiles: [
88+
{
89+
pattern: 'resources/views/**/*.edge',
90+
reloadServer: false,
91+
},
92+
{
93+
pattern: 'public/**',
94+
reloadServer: false,
95+
},
96+
],
97+
98+
assetsBundler: false,
99+
hooks: {
100+
onBuildStarting: [() => import('@adonisjs/vite/build_hook')],
101+
},
102+
})

app/exceptions/handler.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import app from '@adonisjs/core/services/app'
2+
import { HttpContext, ExceptionHandler } from '@adonisjs/core/http'
3+
import type { StatusPageRange, StatusPageRenderer } from '@adonisjs/core/types/http'
4+
5+
export default class HttpExceptionHandler extends ExceptionHandler {
6+
/**
7+
* In debug mode, the exception handler will display verbose errors
8+
* with pretty printed stack traces.
9+
*/
10+
protected debug = !app.inProduction
11+
12+
/**
13+
* Status pages are used to display a custom HTML pages for certain error
14+
* codes. You might want to enable them in production only, but feel
15+
* free to enable them in development as well.
16+
*/
17+
protected renderStatusPages = app.inProduction
18+
19+
/**
20+
* Status pages is a collection of error code range and a callback
21+
* to return the HTML contents to send as a response.
22+
*/
23+
protected statusPages: Record<StatusPageRange, StatusPageRenderer> = {
24+
'404': (error, { inertia }) => inertia.render('errors/not_found', { error }),
25+
'500..599': (error, { inertia }) => inertia.render('errors/server_error', { error }),
26+
}
27+
28+
/**
29+
* The method is used for handling errors and returning
30+
* response to the client
31+
*/
32+
async handle(error: unknown, ctx: HttpContext) {
33+
return super.handle(error, ctx)
34+
}
35+
36+
/**
37+
* The method is used to report error to the logging service or
38+
* the a third party error monitoring service.
39+
*
40+
* @note You should not attempt to send a response from this method.
41+
*/
42+
async report(error: unknown, ctx: HttpContext) {
43+
return super.report(error, ctx)
44+
}
45+
}

app/middleware/auth_middleware.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import type { HttpContext } from '@adonisjs/core/http'
2+
import type { NextFn } from '@adonisjs/core/types/http'
3+
import type { Authenticators } from '@adonisjs/auth/types'
4+
5+
/**
6+
* Auth middleware is used authenticate HTTP requests and deny
7+
* access to unauthenticated users.
8+
*/
9+
export default class AuthMiddleware {
10+
/**
11+
* The URL to redirect to, when authentication fails
12+
*/
13+
redirectTo = '/login'
14+
15+
async handle(
16+
ctx: HttpContext,
17+
next: NextFn,
18+
options: {
19+
guards?: (keyof Authenticators)[]
20+
} = {}
21+
) {
22+
await ctx.auth.authenticateUsing(options.guards, { loginRoute: this.redirectTo })
23+
return next()
24+
}
25+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Logger } from '@adonisjs/core/logger'
2+
import { HttpContext } from '@adonisjs/core/http'
3+
import { NextFn } from '@adonisjs/core/types/http'
4+
5+
/**
6+
* The container bindings middleware binds classes to their request
7+
* specific value using the container resolver.
8+
*
9+
* - We bind "HttpContext" class to the "ctx" object
10+
* - And bind "Logger" class to the "ctx.logger" object
11+
*/
12+
export default class ContainerBindingsMiddleware {
13+
handle(ctx: HttpContext, next: NextFn) {
14+
ctx.containerResolver.bindValue(HttpContext, ctx)
15+
ctx.containerResolver.bindValue(Logger, ctx.logger)
16+
17+
return next()
18+
}
19+
}

app/middleware/guest_middleware.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import type { HttpContext } from '@adonisjs/core/http'
2+
import type { NextFn } from '@adonisjs/core/types/http'
3+
import type { Authenticators } from '@adonisjs/auth/types'
4+
5+
/**
6+
* Guest middleware is used to deny access to routes that should
7+
* be accessed by unauthenticated users.
8+
*
9+
* For example, the login page should not be accessible if the user
10+
* is already logged-in
11+
*/
12+
export default class GuestMiddleware {
13+
/**
14+
* The URL to redirect to when user is logged-in
15+
*/
16+
redirectTo = '/'
17+
18+
async handle(
19+
ctx: HttpContext,
20+
next: NextFn,
21+
options: { guards?: (keyof Authenticators)[] } = {}
22+
) {
23+
for (let guard of options.guards || [ctx.auth.defaultGuard]) {
24+
if (await ctx.auth.use(guard).check()) {
25+
return ctx.response.redirect(this.redirectTo, true)
26+
}
27+
}
28+
29+
return next()
30+
}
31+
}

app/models/user.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { DateTime } from 'luxon'
2+
import hash from '@adonisjs/core/services/hash'
3+
import { compose } from '@adonisjs/core/helpers'
4+
import { BaseModel, column } from '@adonisjs/lucid/orm'
5+
import { withAuthFinder } from '@adonisjs/auth/mixins/lucid'
6+
7+
const AuthFinder = withAuthFinder(() => hash.use('scrypt'), {
8+
uids: ['email'],
9+
passwordColumnName: 'password',
10+
})
11+
12+
export default class User extends compose(BaseModel, AuthFinder) {
13+
@column({ isPrimary: true })
14+
declare id: number
15+
16+
@column()
17+
declare fullName: string | null
18+
19+
@column()
20+
declare email: string
21+
22+
@column({ serializeAs: null })
23+
declare password: string
24+
25+
@column.dateTime({ autoCreate: true })
26+
declare createdAt: DateTime
27+
28+
@column.dateTime({ autoCreate: true, autoUpdate: true })
29+
declare updatedAt: DateTime | null
30+
}

0 commit comments

Comments
 (0)