sat startup script for local development
This commit is contained in:
parent
9802a1d131
commit
b43c1cd5b4
@ -47,7 +47,7 @@ PGPASSWORD='postgres' psql -U postgres -c "CREATE DATABASE app_39215 OWNER app_3
|
||||
```bash
|
||||
cd backend
|
||||
yarn install
|
||||
export $(cat .env | xargs) && NODE_ENV=production yarn start
|
||||
npm run start-dev
|
||||
```
|
||||
|
||||
Backend runs on **http://localhost:8080**
|
||||
|
||||
@ -28,7 +28,7 @@ yarn install
|
||||
yarn db:create
|
||||
|
||||
# Start server (runs migrations, seeds, and watches for changes)
|
||||
export $(cat .env | xargs) && NODE_ENV=production yarn start
|
||||
npm run start-dev
|
||||
```
|
||||
|
||||
The server runs on **port 8080** by default.
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
"description": "Tour Builder Platform - template backend",
|
||||
"scripts": {
|
||||
"start": "npm run db:migrate && npm run db:seed && npm run watch",
|
||||
"start-dev": "cross-env NODE_ENV=production LOG_PRETTY=true DOTENV_CONFIG_PATH=.env NODE_OPTIONS=\"-r dotenv/config\" npm run start",
|
||||
"lint": "eslint . --ext .js",
|
||||
"db:migrate": "sequelize-cli db:migrate",
|
||||
"db:migrate:undo": "sequelize-cli db:migrate:undo",
|
||||
|
||||
@ -9,7 +9,6 @@ const config = require('../db.config')[env];
|
||||
const db = {};
|
||||
|
||||
let sequelize;
|
||||
console.log(env);
|
||||
if (config.use_env_variable) {
|
||||
sequelize = new Sequelize(process.env[config.use_env_variable], config);
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
const ValidationError = require('../services/notifications/errors/validation');
|
||||
const RolesDBApi = require('../db/api/roles');
|
||||
const { logger } = require('../utils/logger');
|
||||
|
||||
// Cache for the 'Public' role object
|
||||
let publicRoleCache = null;
|
||||
@ -11,17 +12,21 @@ async function fetchAndCachePublicRole() {
|
||||
publicRoleCache = await RolesDBApi.findBy({ name: 'Public' });
|
||||
|
||||
if (!publicRoleCache) {
|
||||
console.error(
|
||||
"WARNING: Role 'Public' not found in database during middleware startup. Check your migrations.",
|
||||
logger.warn(
|
||||
{ role: 'Public' },
|
||||
'Role not found during permissions middleware startup',
|
||||
);
|
||||
// The system might not function correctly without this role. May need to throw an error or use a fallback stub.
|
||||
} else {
|
||||
console.log("'Public' role successfully loaded and cached.");
|
||||
logger.info(
|
||||
{ role: 'Public', roleId: publicRoleCache.id },
|
||||
'Role loaded and cached',
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Error fetching 'Public' role during middleware startup:",
|
||||
error,
|
||||
logger.error(
|
||||
{ err: error, role: 'Public' },
|
||||
'Error fetching role during permissions middleware startup',
|
||||
);
|
||||
// Handle the error during startup fetch
|
||||
throw error; // Important to know if the app can proceed without the Public role
|
||||
@ -32,9 +37,9 @@ async function fetchAndCachePublicRole() {
|
||||
// This should happen during application startup when routes are being configured.
|
||||
fetchAndCachePublicRole().catch((error) => {
|
||||
// Handle the case where the fetchAndCachePublicRole promise is rejected
|
||||
console.error(
|
||||
'Critical error during permissions middleware initialization:',
|
||||
error,
|
||||
logger.error(
|
||||
{ err: error },
|
||||
'Critical error during permissions middleware initialization',
|
||||
);
|
||||
});
|
||||
|
||||
@ -81,8 +86,10 @@ function checkPermissions(permission) {
|
||||
if (!publicRoleCache) {
|
||||
// If the cache is unexpectedly empty (e.g., startup error caught),
|
||||
// we can try fetching the role again synchronously (less ideal) or just deny access.
|
||||
console.error(
|
||||
'Public role cache is empty. Attempting synchronous fetch...',
|
||||
const log = req.log || logger;
|
||||
log.warn(
|
||||
{ role: 'Public' },
|
||||
'Role cache is empty, attempting synchronous fetch',
|
||||
);
|
||||
// Less efficient fallback option:
|
||||
effectiveRole = await RolesDBApi.findBy({ name: 'Public' }); // Could be slow
|
||||
@ -117,9 +124,10 @@ function checkPermissions(permission) {
|
||||
} else if (Array.isArray(effectiveRole.permissions)) {
|
||||
rolePermissions = effectiveRole.permissions; // Or take from property if permissions are pre-loaded
|
||||
} else {
|
||||
console.error(
|
||||
'Role object lacks getPermissions() method or permissions property:',
|
||||
effectiveRole,
|
||||
const log = req.log || logger;
|
||||
log.error(
|
||||
{ roleId: effectiveRole.id, roleName: effectiveRole.name },
|
||||
'Role object lacks getPermissions method or permissions property',
|
||||
);
|
||||
return next(
|
||||
new Error('Internal Server Error: Invalid role object format.'),
|
||||
@ -140,7 +148,8 @@ function checkPermissions(permission) {
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle errors during role or permission fetching
|
||||
console.error('Error during permission check:', e);
|
||||
const log = req.log || logger;
|
||||
log.error({ err: e, permission }, 'Error during permission check');
|
||||
next(e); // Pass the error to the next middleware
|
||||
}
|
||||
};
|
||||
|
||||
@ -1,12 +1,21 @@
|
||||
const pino = require('pino');
|
||||
const crypto = require('crypto');
|
||||
|
||||
const isDevelopment = process.env.NODE_ENV === 'development';
|
||||
const shouldPrettyPrint =
|
||||
process.env.LOG_PRETTY === 'true' || process.env.NODE_ENV === 'development';
|
||||
|
||||
const logger = pino({
|
||||
level: process.env.LOG_LEVEL || 'info',
|
||||
transport: isDevelopment
|
||||
? { target: 'pino-pretty', options: { colorize: true } }
|
||||
transport: shouldPrettyPrint
|
||||
? {
|
||||
target: 'pino-pretty',
|
||||
options: {
|
||||
colorize: true,
|
||||
ignore: 'pid,hostname',
|
||||
messageFormat: '{service} | {msg}',
|
||||
translateTime: 'SYS:yyyy-mm-dd HH:MM:ss.l',
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
base: {
|
||||
service: 'tour-builder-api',
|
||||
@ -27,7 +36,7 @@ function requestLogger(req, res, next) {
|
||||
method: req.method,
|
||||
url: req.originalUrl || req.url,
|
||||
status: res.statusCode,
|
||||
duration,
|
||||
durationMs: duration,
|
||||
userAgent: req.headers['user-agent'],
|
||||
};
|
||||
|
||||
|
||||
@ -1,21 +1,38 @@
|
||||
const chokidar = require('chokidar');
|
||||
const { exec } = require('child_process');
|
||||
const nodemon = require('nodemon');
|
||||
const { logger } = require('./src/utils/logger');
|
||||
|
||||
const nodeEnv = process.env.NODE_ENV || 'dev_stage';
|
||||
const childEnv = { ...process.env, NODE_ENV: nodeEnv };
|
||||
const log = logger.child({ module: 'watcher' });
|
||||
|
||||
function logCommandResult(error, stdout, stderr, successMessage) {
|
||||
const output = stdout && stdout.trim();
|
||||
const errorOutput = stderr && stderr.trim();
|
||||
|
||||
if (output) {
|
||||
log.info({ output }, successMessage);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
log.error(
|
||||
{ err: error, stderr: errorOutput },
|
||||
'Watched database command failed',
|
||||
);
|
||||
} else if (errorOutput) {
|
||||
log.warn({ stderr: errorOutput }, 'Watched database command wrote stderr');
|
||||
}
|
||||
}
|
||||
|
||||
const migrationsWatcher = chokidar.watch('./src/db/migrations', {
|
||||
persistent: true,
|
||||
ignoreInitial: true
|
||||
});
|
||||
migrationsWatcher.on('add', (filePath) => {
|
||||
console.log(`[DEBUG] New migration file: ${filePath}`);
|
||||
log.info({ filePath }, 'New migration file detected');
|
||||
exec('npm run db:migrate', { env: childEnv }, (error, stdout, stderr) => {
|
||||
console.log(stdout);
|
||||
if (error) {
|
||||
console.error(stderr);
|
||||
}
|
||||
logCommandResult(error, stdout, stderr, 'Migration command completed');
|
||||
});
|
||||
});
|
||||
|
||||
@ -24,12 +41,9 @@ const seedersWatcher = chokidar.watch('./src/db/seeders', {
|
||||
ignoreInitial: true
|
||||
});
|
||||
seedersWatcher.on('add', (filePath) => {
|
||||
console.log(`[DEBUG] New seed file: ${filePath}`);
|
||||
log.info({ filePath }, 'New seed file detected');
|
||||
exec('npm run db:seed', { env: childEnv }, (error, stdout, stderr) => {
|
||||
console.log(stdout);
|
||||
if (error) {
|
||||
console.error(stderr);
|
||||
}
|
||||
logCommandResult(error, stdout, stderr, 'Seeder command completed');
|
||||
});
|
||||
});
|
||||
|
||||
@ -41,9 +55,13 @@ nodemon({
|
||||
});
|
||||
|
||||
nodemon.on('start', () => {
|
||||
console.log('Nodemon started');
|
||||
log.info({ nodeEnv }, 'Nodemon started');
|
||||
});
|
||||
|
||||
nodemon.on('restart', (files) => {
|
||||
console.log('Nodemon restarted due changes in:', files);
|
||||
log.info({ files }, 'Nodemon restarted due to file changes');
|
||||
});
|
||||
|
||||
nodemon.on('crash', () => {
|
||||
log.error('Nodemon app crashed');
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user