diff --git "a/\345\274\240\345\256\207\350\210\252/20260316-\347\254\224\350\256\260+\344\275\234\344\270\232.md" "b/\345\274\240\345\256\207\350\210\252/20260316-\347\254\224\350\256\260+\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..ec1431807e16f99a09e2428c9e5a2091ce166e5e --- /dev/null +++ "b/\345\274\240\345\256\207\350\210\252/20260316-\347\254\224\350\256\260+\344\275\234\344\270\232.md" @@ -0,0 +1,27 @@ +/_ Node.js Runtime Info _/ +console.log(process.version); // v20.11.0 +console.log(process.versions.node); // 20.11.0 +console.log(process.versions.v8); // 11.3.244.8-jsvc1 +console.log(process.versions.modules); // ABI: 115 + +/_ Platform & Architecture _/ +console.log(process.platform); // win32 | darwin | linux +console.log(process.arch); // x64 | arm64 | ia32 + +/_ Process IDs _/ +console.log(process.pid); // current process id +console.log(process.ppid); // parent process id + +/_ Path Info _/ +console.log(process.cwd()); // working directory +console.log(process.execPath); // node executable path +console.log(process.argv[0]); // same as execPath +console.log(process.argv[1]); // script file path + +/_ Memory Usage _/ +console.log(process.memoryUsage()); +// rss: resident memory +// heapTotal: V8 heap total +// heapUsed: V8 heap used +// external: external memory +// arrayBuffers: ArrayBuffer memory diff --git "a/\345\274\240\345\256\207\350\210\252/20260318-\347\254\224\350\256\260+\344\275\234\344\270\232.md" "b/\345\274\240\345\256\207\350\210\252/20260318-\347\254\224\350\256\260+\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..7d5c54a9e7e71a4508b6099a90a53963dedaab8b --- /dev/null +++ "b/\345\274\240\345\256\207\350\210\252/20260318-\347\254\224\350\256\260+\344\275\234\344\270\232.md" @@ -0,0 +1,111 @@ +## 笔记 +const p = require('path'); + +/* path.join() - join path segments */ +const cfgPath = p.join(__dirname, '..', 'config', 'settings.json'); +// Linux: /project/config/settings.json +// Windows: C:\project\config\settings.json + +/* path.resolve() - resolve to absolute path */ +const fullPath = p.resolve('src', 'index.js'); // based on cwd +const fullPath2 = p.resolve('/usr', 'local', 'bin'); // /usr/local/bin + +/* path info extraction */ +const fp = '/home/user/project/file.txt'; + +p.basename(fp); // file.txt +p.basename(fp, '.txt'); // file +p.extname(fp); // .txt +p.dirname(fp); // /home/user/project + +/* parse path to object */ +p.parse(fp); +// { root: '/', dir: '/home/user/project', base: 'file.txt', ext: '.txt', name: 'file' } + +/* normalize path */ +p.normalize('/foo/bar//baz/../qux'); // /foo/bar/qux + +/* calculate relative path */ +p.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb'); +// ../../impl/bbb + +## 作业 +第一题 +// env.js - display environment variables +console.log('=== Environment Variables ===\n'); + +// method 1: direct output +console.log(process.env); + +// method 2: formatted +Object.entries(process.env).sort().forEach(([k, v]) => { + console.log(`${k.padEnd(30)} = ${v}`); +}); + +// method 3: filter by prefix +console.log('\n=== Node.js Variables ==='); +Object.keys(process.env) + .filter(k => k.startsWith('NODE')) + .forEach(k => console.log(`${k}: ${process.env[k]}`)); + +第二题 +// calc.js - CLI calculator +const p = require('path'); + +const params = process.argv.slice(2); + +if (params.length < 3 || params.includes('--help')) { + console.log(` +Usage: node calc.js + +Operations: + add addition (a + b) + sub subtraction (a - b) + mul multiplication (a * b) + div division (a / b) + +Examples: + node calc.js add 10 5 + node calc.js mul 3.5 2 +`); + process.exit(0); +} + +const [op, num1, num2] = params; + +const x = parseFloat(num1); +const y = parseFloat(num2); + +if (isNaN(x) || isNaN(y)) { + console.error('Error: invalid numbers'); + process.exit(1); +} + +let res; +switch (op) { + case 'add': + res = x + y; + console.log(`${x} + ${y} = ${res}`); + break; + case 'sub': + res = x - y; + console.log(`${x} - ${y} = ${res}`); + break; + case 'mul': + res = x * y; + console.log(`${x} * ${y} = ${res}`); + break; + case 'div': + if (y === 0) { + console.error('Error: division by zero'); + process.exit(1); + } + res = x / y; + console.log(`${x} / ${y} = ${res}`); + break; + default: + console.error(`Error: unknown operation "${op}"`); + process.exit(1); +} + +process.exit(0); diff --git "a/\345\274\240\345\256\207\350\210\252/20260319-\347\254\224\350\256\260+\344\275\234\344\270\232.md" "b/\345\274\240\345\256\207\350\210\252/20260319-\347\254\224\350\256\260+\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..d50de428e0806c6272762b693125c4c64003569a --- /dev/null +++ "b/\345\274\240\345\256\207\350\210\252/20260319-\347\254\224\350\256\260+\344\275\234\344\270\232.md" @@ -0,0 +1,103 @@ +## 笔记 +const fs = require('fs'); +const fsp = require('fs').promises; + +/* read text file */ +const txt = fs.readFileSync('./readme.md', 'utf8'); + +/* read binary file */ +const buf = fs.readFileSync('./photo.jpg'); // +console.log(`size: ${buf.length} bytes`); + +/* read with options */ +const content = fs.readFileSync('./data.txt', { + encoding: 'utf8', + flag: 'r' +}); + +/* promise async way */ +async function loadJson() { + const data = await fsp.readFile('./data.json', 'utf8'); + return JSON.parse(data); +} + +## 作业 +Check file exists? fs.existsSync() +Write file? fs.writeFileSync() sync / fs.writeFile() async +appendFileSync vs writeFileSync? append adds content, write overwrites +Create nested dirs? fs.mkdirSync('./a/b/c', { recursive: true }) +Get file stats? fs.statSync() + +// dir-tree.js - directory tree viewer +const fs = require('fs'); +const p = require('path'); + +const root = process.argv[2] || '.'; + +function displayTree(dir, indent = '', isEnd = true) { + if (!fs.existsSync(dir)) { + console.error(`Path not found: "${dir}"`); + process.exit(1); + } + + let info; + try { + info = fs.statSync(dir); + } catch (err) { + console.error(`Cannot access "${dir}": ${err.message}`); + process.exit(1); + } + + if (!info.isDirectory()) { + console.error(`Not a directory: "${dir}"`); + process.exit(1); + } + + if (indent === '') { + console.log(`[DIR] ${p.resolve(dir)}`); + } + + let items; + try { + items = fs.readdirSync(dir); + } catch (err) { + console.error(`${indent}└── Read error: ${err.message}`); + return; + } + + const sorted = items.map(name => { + const full = p.join(dir, name); + const s = fs.statSync(full); + return { + name, + full, + isDir: s.isDirectory(), + size: s.size + }; + }).sort((a, b) => { + if (a.isDir === b.isDir) return a.name.localeCompare(b.name); + return a.isDir ? -1 : 1; + }); + + sorted.forEach((item, i) => { + const end = i === sorted.length - 1; + const branch = end ? '└── ' : '├── '; + const nextIndent = indent + (end ? ' ' : '│ '); + + const size = item.isDir ? '' : ` [${formatSize(item.size)}]`; + console.log(`${indent}${branch}${item.name}${size}`); + + if (item.isDir) { + displayTree(item.full, nextIndent, end); + } + }); +} + +function formatSize(bytes) { + if (bytes === 0) return '0 B'; + const units = ['B', 'KB', 'MB', 'GB']; + const idx = Math.floor(Math.log(bytes) / Math.log(1024)); + return (bytes / Math.pow(1024, idx)).toFixed(1) + ' ' + units[idx]; +} + +displayTree(root); diff --git "a/\345\274\240\345\256\207\350\210\252/20260320-\347\254\224\350\256\260+\344\275\234\344\270\232.md" "b/\345\274\240\345\256\207\350\210\252/20260320-\347\254\224\350\256\260+\344\275\234\344\270\232.md" new file mode 100644 index 0000000000000000000000000000000000000000..cf14fd115209bc92f7a5941ecd5995099ab7161b --- /dev/null +++ "b/\345\274\240\345\256\207\350\210\252/20260320-\347\254\224\350\256\260+\344\275\234\344\270\232.md" @@ -0,0 +1,105 @@ +## 笔记 + +const http = require('http'); +const url = require('url'); + +const srv = http.createServer((request, response) => { +/_ 基础请求信息 _/ +console.log('------------------------'); +console.log('Method:', request.method); // GET/POST/PUT/DELETE +console.log('URL:', request.url); // /api/users?id=1&name=张三 +console.log('Version:', request.httpVersion); // HTTP/1.1 or HTTP/2 + + /* 请求头部 */ + console.log('Headers:', request.headers); + // host, user-agent, accept, content-type, content-length + + /* URL解析处理 */ + const urlObj = new URL(request.url, `http://${request.headers.host}`); + console.log('Path:', urlObj.pathname); // /api/users + console.log('Query:', urlObj.searchParams); // URLSearchParams + console.log('ID:', urlObj.searchParams.get('id')); // "1" + + /* 请求体接收 */ + let data = ''; + request.setEncoding('utf8'); + request.on('data', (segment) => { + data += segment; + console.log('Received:', segment.length, 'bytes'); + + // 防止过大请求 + if (data.length > 1000000) { + request.destroy(); + response.writeHead(413).end('Payload Too Large'); + } + }); + + request.on('end', () => { + console.log('Body:', data); + // JSON.parse(data) 解析数据 + response.end('Done'); + }); + + request.on('error', (error) => { + console.error('Error:', error); + }); + +}); + +## 作业 + +// main.js - 文章接口服务 +const http = require('http'); +const { blogHandler } = require('./blog-controller.js'); + +const SERVER_PORT = 3000; + +const app = http.createServer(async (request, response) => { +/_ CORS跨域设置 _/ +response.setHeader('Access-Control-Allow-Origin', '\*'); +response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS'); +response.setHeader('Access-Control-Allow-Headers', 'Content-Type'); + + if (request.method === 'OPTIONS') { + response.writeHead(204).end(); + return; + } + + /* 响应格式 */ + response.setHeader('Content-Type', 'application/json; charset=utf-8'); + + try { + /* 路由分发 */ + if (request.url.startsWith('/api/blogs')) { + await blogHandler(request, response); + } else { + response.writeHead(404); + response.end(JSON.stringify({ + success: false, + message: 'API not found, use /api/blogs' + })); + } + } catch (error) { + console.error('Server Error:', error); + if (!response.headersSent) { + response.writeHead(500); + response.end(JSON.stringify({ + success: false, + message: 'Internal Server Error' + })); + } + } + +}); + +app.listen(SERVER_PORT, () => { +console.log(`✅ Article API Server Running`); +console.log(`� http://localhost:${SERVER_PORT}`); +console.log(''); +console.log('Endpoints:'); +console.log(' GET /api/blogs List all articles'); +console.log(' GET /api/blogs/:id Get single article'); +console.log(' POST /api/blogs Create article'); +console.log(' PUT /api/blogs/:id Update article'); +console.log(' DELETE /api/blogs/:id Delete article'); +});