update(wip): I want to docker commit myself

This commit is contained in:
Maieul BOYER 2025-07-28 18:02:01 +02:00
parent f9671ea198
commit 68f8d87477
43 changed files with 557 additions and 2915 deletions

2
src/icons/.dockerignore Normal file
View file

@ -0,0 +1,2 @@
/dist
/node_modules

16
src/icons/Dockerfile Normal file
View file

@ -0,0 +1,16 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Dockerfile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: maiboyer <maiboyer@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# Created: 2025/06/16 14:57:11 by maiboyer #+# #+# #
# Updated: 2025/07/28 17:59:09 by maiboyer ### ########.fr #
# #
# **************************************************************************** #
FROM trans_builder
CMD ["node", "/src/icons/run.js"]

42
src/icons/package.json Normal file
View file

@ -0,0 +1,42 @@
{
"type": "module",
"private": false,
"name": "icons",
"version": "1.0.0",
"description": "This project was bootstrapped with Fastify-CLI.",
"main": "app.ts",
"directories": {
"test": "test"
},
"scripts": {
"test": "npm run build:ts && tsc -p test/tsconfig.json && FASTIFY_AUTOLOAD_TYPESCRIPT=1 node --test --experimental-test-coverage --loader ts-node/esm test/**/*.ts",
"start": "npm run build:ts && fastify start -l info dist/app.js",
"build:ts": "tsc -d",
"watch:ts": "tsc -d -w",
"dev": "npm run build:ts && concurrently -k -p \"[{name}]\" -n \"TypeScript,App\" -c \"yellow.bold,cyan.bold\" \"npm:watch:ts\" \"npm:dev:start\"",
"dev:start": "fastify start --ignore-watch=.ts$ -w -l info -P dist/app.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@fastify/autoload": "^6.3.1",
"@fastify/formbody": "^8.0.2",
"@fastify/multipart": "^9.0.3",
"@fastify/sensible": "^6.0.0",
"@fastify/static": "^8.2.0",
"fastify": "^5.0.0",
"fastify-cli": "^7.4.0",
"fastify-plugin": "^5.0.0",
"fastify-raw-body": "^5.0.0",
"sharp": "^0.34.2"
},
"devDependencies": {
"@types/node": "^22.1.0",
"c8": "^10.1.2",
"concurrently": "^9.0.0",
"fastify-tsconfig": "^3.0.0",
"ts-node": "^10.4.0",
"typescript": "~5.8.2"
}
}

72
src/icons/src/app.ts Normal file
View file

@ -0,0 +1,72 @@
import * as path from 'node:path'
import AutoLoad, { AutoloadPluginOptions } from '@fastify/autoload'
import { FastifyPluginAsync } from 'fastify'
import { fileURLToPath } from 'node:url'
import fastifyFormBody from '@fastify/formbody'
import fastifyMultipart from '@fastify/multipart'
import { mkdir } from 'node:fs/promises'
import fp from 'fastify-plugin'
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
export type AppOptions = {
// Place your custom options for app below here.
} & Partial<AutoloadPluginOptions>
// Pass --options via CLI arguments in command to enable these options.
const options: AppOptions = {
}
// When using .decorate you have to specify added properties for Typescript
declare module 'fastify' {
export interface FastifyInstance {
image_store: string;
}
}
const app: FastifyPluginAsync<AppOptions> = async (
fastify,
opts
): Promise<void> => {
// Place here your custom code!
//void fastify.register(MyPlugin, {})
void fastify.register(fastifyFormBody, {})
void fastify.register(fastifyMultipart, {})
// The use of fastify-plugin is required to be able
// to export the decorators to the outer scope
void fastify.register(fp(async (fastify) => {
const image_store = process.env.USER_ICONS_STORE ?? "/tmp/icons";
fastify.decorate('image_store', image_store)
await mkdir(fastify.image_store, { recursive: true })
}))
// Do not touch the following lines
// This loads all plugins defined in plugins
// those should be support plugins that are reused
// through your application
// eslint-disable-next-line no-void
void fastify.register(AutoLoad, {
dir: path.join(__dirname, 'plugins'),
options: opts,
forceESM: true
})
// This loads all plugins defined in routes
// define your routes in one of these
// eslint-disable-next-line no-void
void fastify.register(AutoLoad, {
dir: path.join(__dirname, 'routes'),
options: opts,
forceESM: true
})
}
export default app
export { app, options }

View file

@ -0,0 +1,16 @@
# Plugins Folder
Plugins define behavior that is common to all the routes in your
application. Authentication, caching, templates, and all the other cross
cutting concerns should be handled by plugins placed in this folder.
Files in this folder are typically defined through the
[`fastify-plugin`](https://github.com/fastify/fastify-plugin) module,
making them non-encapsulated. They can define decorators and set hooks
that will then be used in the rest of your application.
Check out:
* [The hitchhiker's guide to plugins](https://fastify.dev/docs/latest/Guides/Plugins-Guide/)
* [Fastify decorators](https://fastify.dev/docs/latest/Reference/Decorators/).
* [Fastify lifecycle](https://fastify.dev/docs/latest/Reference/Lifecycle/).

View file

@ -0,0 +1,11 @@
import fp from 'fastify-plugin'
import sensible, { FastifySensibleOptions } from '@fastify/sensible'
/**
* This plugins adds some utilities to handle http errors
*
* @see https://github.com/fastify/fastify-sensible
*/
export default fp<FastifySensibleOptions>(async (fastify) => {
fastify.register(sensible)
})

View file

@ -0,0 +1,29 @@
# Routes Folder
Routes define the pathways within your application.
Fastify's structure supports the modular monolith approach, where your
application is organized into distinct, self-contained modules.
This facilitates easier scaling and future transition to a microservice architecture.
In the future you might want to independently deploy some of those.
In this folder you should define all the routes that define the endpoints
of your web application.
Each service is a [Fastify
plugin](https://fastify.dev/docs/latest/Reference/Plugins/), it is
encapsulated (it can have its own independent plugins) and it is
typically stored in a file; be careful to group your routes logically,
e.g. all `/users` routes in a `users.js` file. We have added
a `root.js` file for you with a '/' root added.
If a single file becomes too large, create a folder and add a `index.js` file there:
this file must be a Fastify plugin, and it will be loaded automatically
by the application. You can now add as many files as you want inside that folder.
In this way you can create complex routes within a single monolith,
and eventually extract them.
If you need to share functionality between routes, place that
functionality into the `plugins` folder, and share it via
[decorators](https://fastify.dev/docs/latest/Reference/Decorators/).
If you're a bit confused about using `async/await` to write routes, you would
better take a look at [Promise resolution](https://fastify.dev/docs/latest/Reference/Routes/#promise-resolution) for more details.

View file

@ -0,0 +1,44 @@
import { FastifyPluginAsync } from 'fastify'
import { join } from 'node:path'
import { open } from 'node:fs/promises'
import fastifyRawBody from 'fastify-raw-body'
import sharp from 'sharp'
const example: FastifyPluginAsync = async (fastify, opts): Promise<void> => {
// await fastify.register(authMethod, {});
// here we register plugins that will be active for the current fastify instance (aka everything in this function)
await fastify.register(fastifyRawBody, { encoding: false });
// we register a route handler for: `/<USERID_HERE>`
// it sets some configuration options, and set the actual function that will handle the request
fastify.post('/:userid', { config: { rawBody: true, encoding: false } }, async function(request, reply) {
// this is how we get the `:userid` part of things
const userid: string | undefined = (request.params as any)['userid'];
if (userid === undefined) {
return await reply.code(403);
}
const image_store: string = fastify.getDecorator('image_store')
const image_path = join(image_store, userid)
try {
let img = sharp(request.rawBody as Buffer);
img.resize({
height: 512,
width: 512,
fit: 'fill',
})
const data = await img.png({ compressionLevel: 6 }).toBuffer()
let image_file = await open(image_path, "w", 0o666)
await image_file.write(data);
await image_file.close()
} catch (e: any) {
fastify.log.error(`Error: ${e}`);
reply.code(400);
return { status: "error", message: e.toString() };
}
})
}
export default example

16
src/icons/src/run.ts Normal file
View file

@ -0,0 +1,16 @@
// this sould only be used by the docker file !
import fastify, { FastifyInstance } from "fastify";
import app from './app.js'
const start = async () => {
const f: FastifyInstance = fastify({logger: true});
try {
await f.register(app, {});
await f.listen({ port: 80, host: '0.0.0.0' })
} catch (err) {
f.log.error(err)
process.exit(1)
}
}
start()

43
src/icons/test/helper.ts Normal file
View file

@ -0,0 +1,43 @@
// This file contains code that we reuse between our tests.
import helper from 'fastify-cli/helper.js'
import * as test from 'node:test'
import * as path from 'node:path'
import { fileURLToPath } from 'node:url'
export type TestContext = {
after: typeof test.after
}
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
const AppPath = path.join(__dirname, '..', 'src', 'app.ts')
// Fill in this config with all the configurations
// needed for testing the application
function config () {
return {
skipOverride: true // Register our application with fastify-plugin
}
}
// Automatically build and tear down our instance
async function build (t: TestContext) {
// you can set all the options supported by the fastify CLI command
const argv = [AppPath]
// fastify-plugin ensures that all decorators
// are exposed for testing purposes, this is
// different from the production setup
const app = await helper.build(argv, config())
// Tear down our app after we are done
// eslint-disable-next-line no-void
t.after(() => void app.close())
return app
}
export {
config,
build
}

View file

@ -0,0 +1,13 @@
import { test } from 'node:test'
import * as assert from 'node:assert'
import Fastify from 'fastify'
import Support from '../../src/plugins/support.js'
test('support works standalone', async (t) => {
const fastify = Fastify()
// eslint-disable-next-line no-void
void fastify.register(Support)
await fastify.ready()
assert.equal(fastify.someSupport(), 'hugs')
})

View file

@ -0,0 +1,13 @@
import { test } from 'node:test'
import * as assert from 'node:assert'
import { build } from '../helper.js'
test('example is loaded', async (t) => {
const app = await build(t)
const res = await app.inject({
url: '/example'
})
assert.equal(res.payload, 'this is an example')
})

View file

@ -0,0 +1,12 @@
import { test } from 'node:test'
import * as assert from 'node:assert'
import { build } from '../helper.js'
test('default root route', async (t) => {
const app = await build(t)
const res = await app.inject({
url: '/'
})
assert.deepStrictEqual(JSON.parse(res.payload), { root: true })
})

View file

@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"noEmit": false
},
"include": ["../src/**/*.ts", "**/*.ts"]
}

8
src/icons/tsconfig.json Normal file
View file

@ -0,0 +1,8 @@
{
"extends": "../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src/**/*.ts"]
}