Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module.exports = function (grunt) {
const { spawn, spawnSync } = require('child_process');
const fs = require('fs');
const path = require('path');

grunt.registerTask('syntax', 'Check JavaScript syntax', () => {
const result = spawnSync(process.execPath, ['--check', 'index.js'], {
cwd: __dirname,
encoding: 'utf8'
});

if (result.status !== 0) {
grunt.log.error(result.stderr || result.stdout);
return false;
}

grunt.log.ok('index.js syntax check passed.');
});

grunt.registerTask('validate-json', 'Validate project JSON files', () => {
['haikus.json', 'notes.json', 'process.json'].forEach((fileName) => {
const filePath = path.join(__dirname, fileName);
const content = fs.readFileSync(filePath, 'utf8');
JSON.parse(content);
grunt.log.ok(`${fileName} is valid JSON.`);
});
});

grunt.registerTask('check', ['syntax', 'validate-json']);

grunt.registerTask('start-app', 'Start the app process', function () {
const done = this.async();
const appProcess = spawn('npm', ['start'], {
cwd: __dirname,
stdio: 'inherit',
shell: true
});

const shutdown = () => {
if (!appProcess.killed) {
appProcess.kill('SIGTERM');
}
};

process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);

appProcess.on('exit', (code) => {
process.off('SIGINT', shutdown);
process.off('SIGTERM', shutdown);
done(code === 0);
});
});

grunt.registerTask('serve', ['check', 'start-app']);
grunt.registerTask('default', ['check']);
};
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,13 @@ This is a quick node project template for demoing Codespaces. It is based on the
This sample now includes a simple notes application. Visit `/notes` to create and view notes stored in `notes.json`.

Point your browser to [Quickstart for GitHub Codespaces](https://docs.github.com/en/codespaces/getting-started/quickstart) for a tour of using Codespaces with this repo.

## Build/Check Tooling

This project now includes a lightweight Grunt setup for local checks:

- `npm run check`: Run JavaScript syntax checks and JSON validation.
- `npm run check:json`: Validate JSON files only.
- `npm run start:checked`: Run checks, then start the app.

If Grunt commands are missing in your environment, run `npm install` in the project root to install all dependencies from `package-lock.json`.
13 changes: 11 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ const notesPath = path.join(__dirname, 'notes.json');
function loadNotes() {
try {
const data = fs.readFileSync(notesPath, 'utf8');
notes = JSON.parse(data);
const parsedNotes = JSON.parse(data);
notes = Array.isArray(parsedNotes) ? parsedNotes : [];
} catch (err) {
notes = [];
}
Expand Down Expand Up @@ -48,7 +49,15 @@ app.post('/notes', (req, res) => {
res.redirect('/notes');
});

app.listen(port, () => {
const server = app.listen(port, () => {
console.log(`Server running on port ${port}`);
});

server.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error(`Port ${port} is already in use. Please stop the existing process or set a different PORT.`);
process.exit(1);
}

throw err;
});
Loading