Skip to content

Commit b33a1b3

Browse files
committed
feat: initial commit
0 parents  commit b33a1b3

Some content is hidden

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

68 files changed

+14556
-0
lines changed

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Logs
2+
logs
3+
*.log
4+
5+
# Diagnostic reports (https://nodejs.org/api/report.html)
6+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
7+
8+
# Compiled binary addons (https://nodejs.org/api/addons.html)
9+
build/Release
10+
11+
# Dependency directories
12+
node_modules/
13+
14+
# Optional npm cache directory
15+
.npm
16+
17+
# dotenv environment variables file
18+
.env
19+
20+
# Build / Dist
21+
dist
22+
build
23+
tmp
24+
25+
# macOS Metafiles
26+
.DS_Store
27+
28+
# Fonts
29+
.ttf
30+
31+
# Runtime-generated Files
32+
server/public
33+
server/temp
34+
35+
# IDE Files
36+
.vscode
37+
.idea
38+
39+
# Frontend assets compiled code
40+
admin/public/assets

admin/.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

admin/.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
PORT=8080
2+
HOST=localhost
3+
LOG_LEVEL=info
4+
APP_KEY=some_random_key
5+
NODE_ENV=development
6+
SESSION_DRIVER=cookie
7+
DRIVE_DISK=fs
8+
DB_HOST=localhost
9+
DB_PORT=3306
10+
DB_USER=root
11+
DB_DATABASE=nomad
12+
DB_PASSWORD=password
13+
DB_SSL=false

admin/Dockerfile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
FROM node:22.16.0-alpine3.22 AS base
2+
3+
# Install bash & curl for entrypoint script compatibility
4+
RUN apk add --no-cache bash curl
5+
6+
# All deps stage
7+
FROM base AS deps
8+
WORKDIR /app
9+
ADD package.json package-lock.json ./
10+
RUN npm ci
11+
12+
# Production only deps stage
13+
FROM base AS production-deps
14+
WORKDIR /app
15+
ADD package.json package-lock.json ./
16+
RUN npm ci --omit=dev
17+
18+
# Build stage
19+
FROM base AS build
20+
WORKDIR /app
21+
COPY --from=deps /app/node_modules /app/node_modules
22+
ADD . .
23+
RUN node ace build
24+
25+
# Production stage
26+
FROM base
27+
ENV NODE_ENV=production
28+
WORKDIR /app
29+
COPY --from=production-deps /app/node_modules /app/node_modules
30+
COPY --from=build /app/build /app
31+
EXPOSE 8080
32+
CMD ["node", "./bin/server.js"]

admin/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
## Docker container
3+
```
4+
docker run --rm -it -p 8080:8080 jturnercosmistack/projectnomad:admin-latest -e PORT=8080 -e HOST=0.0.0.0 -e APP_KEY=secretlongpasswordsecret -e LOG_LEVEL=debug -e DRIVE_DISK=fs
5+
```

admin/ace.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
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-maintained
21+
*/
22+
import 'ts-node-maintained/register/esm'
23+
24+
/**
25+
* Import ace console entrypoint
26+
*/
27+
await import('./bin/console.js')

admin/adonisrc.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import { defineConfig } from '@adonisjs/core/app'
2+
3+
export default defineConfig({
4+
/*
5+
|--------------------------------------------------------------------------
6+
| Experimental flags
7+
|--------------------------------------------------------------------------
8+
|
9+
| The following features will be enabled by default in the next major release
10+
| of AdonisJS. You can opt into them today to avoid any breaking changes
11+
| during upgrade.
12+
|
13+
*/
14+
experimental: {
15+
mergeMultipartFieldsAndFiles: true,
16+
shutdownInReverseOrder: true,
17+
},
18+
19+
/*
20+
|--------------------------------------------------------------------------
21+
| Commands
22+
|--------------------------------------------------------------------------
23+
|
24+
| List of ace commands to register from packages. The application commands
25+
| will be scanned automatically from the "./commands" directory.
26+
|
27+
*/
28+
commands: [() => import('@adonisjs/core/commands'), () => import('@adonisjs/lucid/commands')],
29+
30+
/*
31+
|--------------------------------------------------------------------------
32+
| Service providers
33+
|--------------------------------------------------------------------------
34+
|
35+
| List of service providers to import and register when booting the
36+
| application
37+
|
38+
*/
39+
providers: [
40+
() => import('@adonisjs/core/providers/app_provider'),
41+
() => import('@adonisjs/core/providers/hash_provider'),
42+
{
43+
file: () => import('@adonisjs/core/providers/repl_provider'),
44+
environment: ['repl', 'test'],
45+
},
46+
() => import('@adonisjs/core/providers/vinejs_provider'),
47+
() => import('@adonisjs/core/providers/edge_provider'),
48+
() => import('@adonisjs/session/session_provider'),
49+
() => import('@adonisjs/vite/vite_provider'),
50+
() => import('@adonisjs/shield/shield_provider'),
51+
() => import('@adonisjs/static/static_provider'),
52+
() => import('@adonisjs/cors/cors_provider'),
53+
() => import('@adonisjs/lucid/database_provider'),
54+
() => import('@adonisjs/inertia/inertia_provider'),
55+
() => import('@adonisjs/drive/drive_provider'),
56+
() => import('@adonisjs/transmit/transmit_provider')
57+
],
58+
59+
/*
60+
|--------------------------------------------------------------------------
61+
| Preloads
62+
|--------------------------------------------------------------------------
63+
|
64+
| List of modules to import before starting the application.
65+
|
66+
*/
67+
preloads: [() => import('#start/routes'), () => import('#start/kernel')],
68+
69+
/*
70+
|--------------------------------------------------------------------------
71+
| Tests
72+
|--------------------------------------------------------------------------
73+
|
74+
| List of test suites to organize tests by their type. Feel free to remove
75+
| and add additional suites.
76+
|
77+
*/
78+
tests: {
79+
suites: [
80+
{
81+
files: ['tests/unit/**/*.spec(.ts|.js)'],
82+
name: 'unit',
83+
timeout: 2000,
84+
},
85+
{
86+
files: ['tests/functional/**/*.spec(.ts|.js)'],
87+
name: 'functional',
88+
timeout: 30000,
89+
},
90+
],
91+
forceExit: false,
92+
},
93+
94+
/*
95+
|--------------------------------------------------------------------------
96+
| Metafiles
97+
|--------------------------------------------------------------------------
98+
|
99+
| A collection of files you want to copy to the build folder when creating
100+
| the production build.
101+
|
102+
*/
103+
metaFiles: [
104+
{
105+
pattern: 'resources/views/**/*.edge',
106+
reloadServer: false,
107+
},
108+
{
109+
pattern: 'public/**',
110+
reloadServer: false,
111+
},
112+
],
113+
114+
assetsBundler: false,
115+
hooks: {
116+
onBuildStarting: [() => import('@adonisjs/vite/build_hook')],
117+
},
118+
})
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { SystemService } from '#services/system_service'
2+
import { inject } from '@adonisjs/core'
3+
import type { HttpContext } from '@adonisjs/core/http'
4+
5+
@inject()
6+
export default class HomeController {
7+
constructor(
8+
private systemService: SystemService,
9+
) { }
10+
11+
async index({ inertia }: HttpContext) {
12+
const services = await this.systemService.getServices();
13+
return inertia.render('home', {
14+
system: {
15+
services
16+
}
17+
})
18+
}
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { DockerService } from '#services/docker_service';
2+
import { SystemService } from '#services/system_service'
3+
import { installServiceValidator } from '#validators/system';
4+
import { inject } from '@adonisjs/core'
5+
import type { HttpContext } from '@adonisjs/core/http'
6+
7+
@inject()
8+
export default class SystemController {
9+
constructor(
10+
private systemService: SystemService,
11+
private dockerService: DockerService
12+
) { }
13+
14+
async getServices({ response }: HttpContext) {
15+
const services = await this.systemService.getServices();
16+
response.send(services);
17+
}
18+
19+
async installService({ request, response }: HttpContext) {
20+
const payload = await request.validateUsing(installServiceValidator);
21+
22+
const result = await this.dockerService.createContainerPreflight(payload.service_name);
23+
if (result.success) {
24+
response.send({ message: result.message });
25+
} else {
26+
response.status(400).send({ error: result.message });
27+
}
28+
}
29+
}

admin/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+
}

0 commit comments

Comments
 (0)