devx: easier way to run the server + debugger
This commit is contained in:
parent
40b98cdc17
commit
9cf6b979da
@ -1,9 +0,0 @@
|
||||
{
|
||||
"permissions": {
|
||||
"allow": [
|
||||
"Bash(yarn add:*)",
|
||||
"Bash(yarn build)"
|
||||
],
|
||||
"deny": []
|
||||
}
|
||||
}
|
78
.cursorrules
78
.cursorrules
@ -1,78 +0,0 @@
|
||||
You are an expert in Typescript and Node.js. You are building a web server in opponiated framework.
|
||||
|
||||
Tool usage
|
||||
- When in doubt - use web tool to get answers from the web.
|
||||
- Search web when you have some failures.
|
||||
|
||||
Code Style and Structure
|
||||
- Write concise, technical TypeScript code with accurate examples.
|
||||
- Use functional and declarative programming patterns; avoid classes.
|
||||
- Prefer iteration and modularization over code duplication.
|
||||
- Use descriptive variable names with auxiliary verbs (e.g., isLoading, hasError).
|
||||
- All sources must be imported using "@/" prefix. `import "@/utils/log"` means `import "/sources/utils/log.ts"`.
|
||||
- Always use absolute imports.
|
||||
|
||||
Folder structure
|
||||
- Root of the sources is "/sources"
|
||||
- Non-application logic files are in "/sources/modules"
|
||||
- Low level or too abstract utilities are in "/sources/utils"
|
||||
- Recipes, ie scripts that you want to run outside of the server are in "/sources/recipes"
|
||||
- Applications are in /sources/apps
|
||||
- API server is in /sources/apps/api with routes in /sources/apps/api/routes
|
||||
- Modules are in /sources/modules
|
||||
|
||||
Naming Conventions
|
||||
- Use lowercase with dashes for directories (e.g., components/auth-wizard).
|
||||
|
||||
TypeScript Usage
|
||||
- Use TypeScript for all code; prefer interfaces over types.
|
||||
- Avoid enums; use maps instead.
|
||||
- Use functional components with TypeScript interfaces.
|
||||
- Use strict mode in TypeScript for better type safety.
|
||||
|
||||
Tests
|
||||
- Write tests using Vitest.
|
||||
- Always name test files in the same way as the source file, but with ".spec.ts" suffix.
|
||||
|
||||
Utilities
|
||||
- When writing utility function always name file and function in the same way, so it is easy to find it.
|
||||
- Utility functions should be modular and not too complex.
|
||||
- When writing utility functions, always write tests for them BEFORE writing the code.
|
||||
- Iterate your implementation and tests until you are sure that the function works as expected.
|
||||
- When writing utility functions, always write documentation for them.
|
||||
|
||||
Modules
|
||||
- Modules are bigger than utility functions and their goal is to abstract away complexity
|
||||
- Each module should have dedicated directory.
|
||||
- Modules usually don't have application specific logic, they are more general and could be copied to other projects.
|
||||
- Modules can depend on other modules, but should not depend on application specific logic.
|
||||
- Prefer to write code as modules instead of application specific code.
|
||||
- When using a module is a good idea:
|
||||
- When you need to integrate with external services
|
||||
- When you need to abstract away complexity of some library
|
||||
- When you want to implement some group of functions that are related to each other, like math, date, etc.
|
||||
- Some known modules are:
|
||||
- ai: AI wrappers to interact with AI services
|
||||
- eventbus: event bus to send and receive events between modules and applications
|
||||
- lock: simple lock to synchronize access to resources in the whole cluster
|
||||
- media: tools to work with media files
|
||||
|
||||
Applications
|
||||
- Applications has some application specific logic
|
||||
- Applications have the most of the complexity and other parts of the code should assist by reducing complexity here.
|
||||
- When using prompts, write them to "_prompts.ts" file relative to the application.
|
||||
|
||||
Database
|
||||
- Prisma is used as ORM.
|
||||
- Use "inTx" to wrap database operations in transactions.
|
||||
- Do not update schema without absolute necessity.
|
||||
- For complex fields, use "Json" type.
|
||||
|
||||
Events
|
||||
- eventbus allows to send and receive events inside of the process and between different processes.
|
||||
- eventbus is local or redis based.
|
||||
- use "afterTx" to send events after transaction is committed successfully instead of directly emitting events.
|
||||
|
||||
Libraries
|
||||
- Always use Zod for validation of inputs.
|
||||
- Always use axios for HTTP requests.
|
1
.cursorrules
Symbolic link
1
.cursorrules
Symbolic link
@ -0,0 +1 @@
|
||||
CLAUDE.md
|
@ -1,4 +1,3 @@
|
||||
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/handy
|
||||
REDIS_URL=redis://localhost:6379
|
||||
SEED=your-seed-for-token-generation
|
||||
HANDY_MASTER_SECRET=your-super-secret-key-for-local-development
|
||||
PORT=3005
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@ dist
|
||||
|
||||
.env.local
|
||||
.env
|
||||
|
||||
.logs/
|
||||
|
||||
.claude/
|
||||
|
30
.vscode/launch.json
vendored
Normal file
30
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Debug Server",
|
||||
"runtimeExecutable": "npx",
|
||||
"runtimeArgs": [
|
||||
"tsx",
|
||||
"--inspect",
|
||||
"./sources/main.ts"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"envFile": "${workspaceFolder}/.env.local",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"resolveSourceMapLocations": [
|
||||
"${workspaceFolder}/**",
|
||||
"!**/node_modules/**"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@ -8,12 +8,12 @@
|
||||
"scripts": {
|
||||
"build": "tsc --noEmit",
|
||||
"start": "tsx ./sources/main.ts",
|
||||
"dev": "lsof -ti tcp:3005 | xargs kill -9 && tsx --env-file=.env.local ./sources/main.ts",
|
||||
"dev": "tsx --env-file=.env.local ./sources/main.ts",
|
||||
"test": "vitest",
|
||||
"migrate": "prisma migrate dev",
|
||||
"migrate": "dotenv -e .env.local -- prisma migrate dev",
|
||||
"generate": "prisma generate",
|
||||
"postinstall": "prisma generate",
|
||||
"db": "docker run -e POSTGRES_PASSWORD=postgres -v $(pwd)/.pgdata:/var/lib/postgresql/data -p 5432:5432 postgres"
|
||||
"db": "docker run -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=handy -v $(pwd)/.pgdata:/var/lib/postgresql/data -p 5432:5432 postgres"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/chalk": "^2.2.0",
|
||||
@ -21,6 +21,7 @@
|
||||
"@types/node": "^20.12.3",
|
||||
"@types/tmp": "^0.2.6",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"dotenv-cli": "^8.0.0",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.3",
|
||||
"yaml": "^2.4.2"
|
||||
@ -40,6 +41,7 @@
|
||||
"fastify-type-provider-zod": "^4.0.2",
|
||||
"ioredis": "^5.4.1",
|
||||
"jsonwebtoken": "^9.0.2",
|
||||
"pino-pretty": "^13.0.0",
|
||||
"prisma": "^6.11.1",
|
||||
"prisma-json-types-generator": "^3.5.1",
|
||||
"privacy-kit": "^0.0.23",
|
||||
|
@ -1,7 +1,46 @@
|
||||
import pino from 'pino';
|
||||
import { mkdirSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const isDebug = process.env.DEBUG === 'true' || process.env.NODE_ENV === 'development';
|
||||
const logsDir = join(process.cwd(), '.logs');
|
||||
|
||||
if (isDebug) {
|
||||
try {
|
||||
mkdirSync(logsDir, { recursive: true });
|
||||
} catch (error) {
|
||||
console.error('Failed to create logs directory:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const transports: any[] = [];
|
||||
|
||||
transports.push({
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
translateTime: 'HH:MM:ss.l',
|
||||
ignore: 'pid,hostname',
|
||||
messageFormat: '{levelLabel} [{time}] {msg}',
|
||||
errorLikeObjectKeys: ['err', 'error'],
|
||||
},
|
||||
});
|
||||
|
||||
if (isDebug) {
|
||||
transports.push({
|
||||
target: 'pino/file',
|
||||
options: {
|
||||
destination: join(logsDir, `server-${new Date().toISOString().split('T')[0]}.log`),
|
||||
mkdir: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export const logger = pino({
|
||||
level: 'info',
|
||||
level: isDebug ? 'debug' : 'info',
|
||||
transport: {
|
||||
targets: transports,
|
||||
},
|
||||
});
|
||||
|
||||
export function log(src: any, ...args: any[]) {
|
||||
@ -11,3 +50,11 @@ export function log(src: any, ...args: any[]) {
|
||||
export function warn(src: any, ...args: any[]) {
|
||||
logger.warn(src, ...args);
|
||||
}
|
||||
|
||||
export function error(src: any, ...args: any[]) {
|
||||
logger.error(src, ...args);
|
||||
}
|
||||
|
||||
export function debug(src: any, ...args: any[]) {
|
||||
logger.debug(src, ...args);
|
||||
}
|
29
yarn.lock
29
yarn.lock
@ -1140,6 +1140,15 @@ cross-spawn@^7.0.3:
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
cross-spawn@^7.0.6:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
date-fns@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14"
|
||||
@ -1196,6 +1205,26 @@ diff@^4.0.1:
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
|
||||
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
|
||||
|
||||
dotenv-cli@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-8.0.0.tgz#cea1519f5a06c7372a1428fca4605fcf3d50e1cf"
|
||||
integrity sha512-aLqYbK7xKOiTMIRf1lDPbI+Y+Ip/wo5k3eyp6ePysVaSqbyxjyK3dK35BTxG+rmd7djf5q2UPs4noPNH+cj0Qw==
|
||||
dependencies:
|
||||
cross-spawn "^7.0.6"
|
||||
dotenv "^16.3.0"
|
||||
dotenv-expand "^10.0.0"
|
||||
minimist "^1.2.6"
|
||||
|
||||
dotenv-expand@^10.0.0:
|
||||
version "10.0.0"
|
||||
resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37"
|
||||
integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==
|
||||
|
||||
dotenv@^16.3.0:
|
||||
version "16.6.1"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020"
|
||||
integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==
|
||||
|
||||
dotenv@^16.4.5:
|
||||
version "16.4.5"
|
||||
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f"
|
||||
|
Loading…
Reference in New Issue
Block a user