From fc577aadf1c49394eb34e06ea857cea63857a2f5 Mon Sep 17 00:00:00 2001 From: andreferraro Date: Tue, 11 Aug 2026 13:43:15 -0300 Subject: [PATCH] feat: migrate hello baseline from Python to TypeScript Replace the greenfield Python hello world with a Node.js 22/TypeScript/npm toolchain while preserving the existing greeting behavior. Co-authored-by: Cursor --- .gitignore | 2 ++ README.md | 12 +++++++++- hello.py | 14 ----------- package-lock.json | 50 ++++++++++++++++++++++++++++++++++++++++ package.json | 19 +++++++++++++++ sonar-project.properties | 7 +++--- src/hello.test.ts | 13 +++++++++++ src/hello.ts | 20 ++++++++++++++++ tsconfig.json | 16 +++++++++++++ 9 files changed, 135 insertions(+), 18 deletions(-) delete mode 100644 hello.py create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 src/hello.test.ts create mode 100644 src/hello.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore index 76b4e60..365f839 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ .env *.pem *.key +node_modules/ +dist/ diff --git a/README.md b/README.md index 1179509..e96d00b 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,19 @@ Hello world — repositório de testes MCP do TicketLab. ## Quick start ```bash -python hello.py +npm ci +npm start ``` +Requires Node.js 22+. + +## Scripts + +- `npm run build` — compile TypeScript to `dist/` +- `npm start` — run the compiled hello program +- `npm run typecheck` — type-check without emitting +- `npm test` — build and run tests + ## CI / quality gate Pushes and PRs into `develop`, `release/**` and `main` run SonarQube via Gitea Actions. Merge is blocked until the Quality Gate passes. diff --git a/hello.py b/hello.py deleted file mode 100644 index d876492..0000000 --- a/hello.py +++ /dev/null @@ -1,14 +0,0 @@ -"""Hello world for TicketLab_MCP.""" - - -def greet(name: str = "TicketLab MCP") -> str: - """Return a greeting for the given name.""" - return f"Hello, {name}!" - - -def main() -> None: - print(greet()) - - -if __name__ == "__main__": - main() diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..fd05137 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,50 @@ +{ + "name": "ticketlab-mcp", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "ticketlab-mcp", + "version": "0.1.0", + "devDependencies": { + "@types/node": "^22.13.10", + "typescript": "^5.8.2" + }, + "engines": { + "node": ">=22" + } + }, + "node_modules/@types/node": { + "version": "22.20.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.1.tgz", + "integrity": "sha512-EANqOCF9QFyra+4pfxUcX9STKJpCLjMbObVzljIJomAWSnuSIEAvyzEU53GaajbXJEgdh0iEcPL+DGvpUd4k1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..e09c6f0 --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "ticketlab-mcp", + "version": "0.1.0", + "private": true, + "type": "module", + "engines": { + "node": ">=22" + }, + "scripts": { + "build": "tsc", + "start": "node dist/hello.js", + "typecheck": "tsc --noEmit", + "test": "npm run build && node --test dist/hello.test.js" + }, + "devDependencies": { + "@types/node": "^22.13.10", + "typescript": "^5.8.2" + } +} diff --git a/sonar-project.properties b/sonar-project.properties index 262ae87..4aa1f79 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,7 @@ sonar.projectKey=TicketLab_MCP sonar.projectName=TicketLab_MCP -sonar.sources=. -sonar.exclusions=**/.gitea/**,**/.git/**,**/.cursor/** +sonar.sources=src +sonar.tests=src +sonar.test.inclusions=**/*.test.ts +sonar.exclusions=**/*.test.ts sonar.sourceEncoding=UTF-8 -sonar.python.version=3 diff --git a/src/hello.test.ts b/src/hello.test.ts new file mode 100644 index 0000000..440d5df --- /dev/null +++ b/src/hello.test.ts @@ -0,0 +1,13 @@ +import assert from "node:assert/strict"; +import { describe, it } from "node:test"; +import { greet } from "./hello.js"; + +describe("greet", () => { + it("returns the default greeting", () => { + assert.equal(greet(), "Hello, TicketLab MCP!"); + }); + + it("returns a greeting for a custom name", () => { + assert.equal(greet("World"), "Hello, World!"); + }); +}); diff --git a/src/hello.ts b/src/hello.ts new file mode 100644 index 0000000..ea657ed --- /dev/null +++ b/src/hello.ts @@ -0,0 +1,20 @@ +import { pathToFileURL } from "node:url"; + +/** Hello world for TicketLab_MCP. */ + +/** Return a greeting for the given name. */ +export function greet(name: string = "TicketLab MCP"): string { + return `Hello, ${name}!`; +} + +export function main(): void { + console.log(greet()); +} + +const entry = process.argv[1]; +const isMain = + entry !== undefined && import.meta.url === pathToFileURL(entry).href; + +if (isMain) { + main(); +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..9d6caf5 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "rootDir": "src", + "outDir": "dist", + "strict": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "declaration": true, + "sourceMap": true + }, + "include": ["src/**/*.ts"] +} -- 2.54.0