feat: initial scaffolding

This commit is contained in:
2026-02-03 10:08:03 -08:00
parent 0ecfc9b54a
commit 2f38aa3b92
63 changed files with 23000 additions and 20 deletions
+5
View File
@@ -0,0 +1,5 @@
node_modules
# Keep environment variables out of version control
.env
/generated/prisma
+10
View File
@@ -0,0 +1,10 @@
module.exports = {
displayName: 'api',
preset: '../jest.preset.js',
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../coverage/api',
};
+14
View File
@@ -0,0 +1,14 @@
// This file was generated by Prisma, and assumes you have installed the following:
// npm install --save-dev prisma dotenv
import "dotenv/config";
import { defineConfig } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: process.env["DATABASE_URL"],
},
});
+82
View File
@@ -0,0 +1,82 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "mongodb"
}
model Game {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
platform String?
status GameStatus
dateAdded DateTime @default(now())
dateCompleted DateTime?
rating Int? @db.Int @default(0)
notes String?
coverImage String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum GameStatus {
PLAYING
COMPLETED
BACKLOG
}
model Book {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
author String
isbn String?
status BookStatus
dateAdded DateTime @default(now())
dateFinished DateTime?
rating Int? @db.Int @default(0)
notes String?
coverImage String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum BookStatus {
READING
FINISHED
TO_READ
}
model Music {
id String @id @default(auto()) @map("_id") @db.ObjectId
title String
artist String
type MusicType
status MusicStatus
dateAdded DateTime @default(now())
dateCompleted DateTime?
rating Int? @db.Int @default(0)
notes String?
coverArt String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
enum MusicType {
ALBUM
SINGLE
EP
}
enum MusicStatus {
LISTENING
COMPLETED
WANT_TO_LISTEN
}
+89
View File
@@ -0,0 +1,89 @@
{
"name": "api",
"$schema": "../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "api/src",
"projectType": "application",
"tags": [],
"targets": {
"build": {
"executor": "@nx/esbuild:esbuild",
"outputs": ["{options.outputPath}"],
"defaultConfiguration": "production",
"options": {
"platform": "node",
"outputPath": "dist/api",
"format": ["cjs"],
"bundle": false,
"main": "api/src/main.ts",
"tsConfig": "api/tsconfig.app.json",
"assets": ["api/src/assets"],
"generatePackageJson": true,
"esbuildOptions": {
"sourcemap": true,
"outExtension": {
".js": ".js"
}
}
},
"configurations": {
"development": {},
"production": {
"esbuildOptions": {
"sourcemap": false,
"outExtension": {
".js": ".js"
}
}
}
}
},
"prune-lockfile": {
"dependsOn": ["build"],
"cache": true,
"executor": "@nx/js:prune-lockfile",
"outputs": [
"{workspaceRoot}/dist/api/package.json",
"{workspaceRoot}/dist/api/pnpm-lock.yaml"
],
"options": {
"buildTarget": "build"
}
},
"copy-workspace-modules": {
"dependsOn": ["build"],
"cache": true,
"outputs": ["{workspaceRoot}/dist/api/workspace_modules"],
"executor": "@nx/js:copy-workspace-modules",
"options": {
"buildTarget": "build"
}
},
"prune": {
"dependsOn": ["prune-lockfile", "copy-workspace-modules"],
"executor": "nx:noop"
},
"serve": {
"continuous": true,
"executor": "@nx/js:node",
"defaultConfiguration": "development",
"dependsOn": ["build"],
"options": {
"buildTarget": "api:build",
"runBuildTargetDependencies": false
},
"configurations": {
"development": {
"buildTarget": "api:build:development"
},
"production": {
"buildTarget": "api:build:production"
}
}
},
"test": {
"options": {
"passWithNoTests": true
}
}
}
}
+20
View File
@@ -0,0 +1,20 @@
import Fastify, { FastifyInstance } from 'fastify';
import { app } from './app';
describe('GET /', () => {
let server: FastifyInstance;
beforeEach(() => {
server = Fastify();
server.register(app);
});
it('should respond with a message', async () => {
const response = await server.inject({
method: 'GET',
url: '/',
});
expect(response.json()).toEqual({ message: 'Hello API' });
});
});
+27
View File
@@ -0,0 +1,27 @@
import * as path from 'path';
import { FastifyInstance } from 'fastify';
import AutoLoad from '@fastify/autoload';
/* eslint-disable-next-line */
export interface AppOptions {}
export async function app(fastify: FastifyInstance, opts: AppOptions) {
// Place here your custom code!
// Do not touch the following lines
// This loads all plugins defined in plugins
// those should be support plugins that are reused
// through your application
fastify.register(AutoLoad, {
dir: path.join(__dirname, 'plugins'),
options: { ...opts },
});
// This loads all plugins defined in routes
// define your routes in one of these
fastify.register(AutoLoad, {
dir: path.join(__dirname, 'routes'),
options: { ...opts },
});
}
+12
View File
@@ -0,0 +1,12 @@
import { FastifyInstance } from 'fastify';
import fp from 'fastify-plugin';
import sensible from '@fastify/sensible';
/**
* This plugins adds some utilities to handle http errors
*
* @see https://github.com/fastify/fastify-sensible
*/
export default fp(async function (fastify: FastifyInstance) {
fastify.register(sensible);
});
+7
View File
@@ -0,0 +1,7 @@
import { FastifyInstance } from 'fastify';
export default async function (fastify: FastifyInstance) {
fastify.get('/', async function () {
return { message: 'Hello API' };
});
}
View File
+23
View File
@@ -0,0 +1,23 @@
import Fastify from 'fastify';
import { app } from './app/app';
const host = process.env.HOST ?? 'localhost';
const port = process.env.PORT ? Number(process.env.PORT) : 3000;
// Instantiate Fastify with some config
const server = Fastify({
logger: true,
});
// Register your application as a normal plugin.
server.register(app);
// Start listening.
server.listen({ port, host }, (err) => {
if (err) {
server.log.error(err);
process.exit(1);
} else {
console.log(`[ ready ] http://${host}:${port}`);
}
});
+15
View File
@@ -0,0 +1,15 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../dist/out-tsc",
"module": "commonjs",
"types": ["node"]
},
"include": ["src/**/*.ts"],
"exclude": [
"jest.config.ts",
"jest.config.cts",
"src/**/*.spec.ts",
"src/**/*.test.ts"
]
}
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "../tsconfig.base.json",
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
},
{
"path": "./tsconfig.spec.json"
}
],
"compilerOptions": {
"esModuleInterop": true
}
}
+16
View File
@@ -0,0 +1,16 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../dist/out-tsc",
"module": "commonjs",
"moduleResolution": "node10",
"types": ["jest", "node"]
},
"include": [
"jest.config.ts",
"jest.config.cts",
"src/**/*.test.ts",
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}