Strict API contract validator built for Node.js test suites and CI pipelines.
Named after Red John from The Mentalist (A show you absolutely must watch... and beware, the links has spoilers!).
The smiley face is the mark that indicates the execution was perfect. Applied to backend development, this is a relentless tool that judges whether your API strictly complies with the established contract. If the API lies or breaches the contract, the test fails. When your specification passes perfectly, it signs the output with the Smiley Face. When it fails, it isolates and highlights the "crime scene".
It acts as both a static linter (checking your API specification for completeness) and a runtime validation engine (verifying that your live server's responses actually match the contract you wrote).
- Multi-format support: Auto-detects and validates OpenAPI 3.x, AsyncAPI 2.x & 3.x, JSON Schema, GraphQL SDL, gRPC (
.proto), and Postman Collections. - Official Integrations: Drop-in GitHub Action (
x-name15/smile-action@v1) and real-time VS Code Extension with inline contract diagnostics and autofixing. - Zero dependencies for the CLI: Run it via
npxinstantly in your CI pipelines. - Library API: Native Vitest/Jest integration. Import it directly into your tests with full TypeScript support (no subprocesses).
- The Breaching Detector (Runtime Smoke Test)
⚠️ WARNING:smile testperforms actual HTTP requests against the provided server. It will executeGET,POST,PUT,PATCH, andDELETErequests using auto-generated fake data if your spec defines them. This will create, modify, and delete real data. You should run this strictly against local, staging, or ephemeral environments. We are not responsible for accidental data loss in production.
smile test takes your spec and a base URL, fires a real HTTP requests against every documented endpoint, validating the runtime response body against the schema.
- Built-in Rule Engine: Opinionated, zero-configuration rules focused on documentation completeness and contract enforceability.
- Plugin System: Extend smile with your own custom rules written in plain JavaScript. Load them via
config.smile.jsonor the--pluginCLI flag. - Incremental Adoption: Customize rule severities (
error,warn,off) viaconfig.smile.jsonwithout breaking CI/CD. - Packaged Artifact Gate: The CI release gate packs and installs the npm artifact in a temporary consumer project, checking library imports, CLI versioning, valid/invalid exit codes, and AsyncAPI distribution compatibility.
Run the interactive setup wizard to instantly configure smile in your project. It will optionally generate a smart configuration file, a GitHub Actions CI workflow, and a sample API boilerplate.
npx @mrjacket/smile initLint any specification file instantly. smile exits with code 1 if violations are found, making it perfect for CI/CD.
# Lint current directory (defaults to .)
npx @mrjacket/smile lint
# Lint a specific file
npx @mrjacket/smile lint ./openapi.yaml
# Lint an entire directory (auto-discovers supported specification files)
npx @mrjacket/smile lint ./specs/
# Enforce strict warning limits in CI (exit code 1 if warnings > limit)
npx @mrjacket/smile lint --max-warnings 0
# Automatically fix safe contract issues (missing operationId, summary)
npx @mrjacket/smile lint --fixTip:
smileautomatically respects your repository's.gitignoreas well as standard build directories (dist/,build/,coverage/). You can also create a.smileignorefile in your root directory to define Smile-specific exclusions!
You can optionally output the results as raw JSON, Markdown, JUnit, or SARIF (for GitHub Code Scanning / Security tab):
npx @mrjacket/smile lint --format json
npx @mrjacket/smile lint --format markdown > report.md
npx @mrjacket/smile lint --format junit > junit.xml
npx @mrjacket/smile lint --format sarif > results.sarifTo suppress all CLI menus and art in CI environments, use the --quiet or -q flag:
npx @mrjacket/smile lint --quietSupported formats: .yaml, .yml, .json, .graphql, .gql, .proto
If you have a lot of missing summaries, operation IDs, or channel descriptions, you don't have to fix them manually. Smile Deduce will read your OpenAPI or AsyncAPI file, prompt you interactively in the terminal for the missing data, and safely save the YAML (preserving all your # comments and formatting!).
For GraphQL, it even acts as a smart naming assistant, automatically suggesting CamelCase and PascalCase corrections for your types and fields and safely injecting them!
npx @mrjacket/smile deduce ./openapi.yaml
⚠️ WARNING:smile testperforms destructive HTTP requests (POST,PUT,DELETE). Run strictly against local or ephemeral environments to avoid accidental data loss!
Verify that your live server actually honors the contract:
# Smoke test against a live environment
smile test ./openapi.yaml https://api.staging.myserver.com
# Validate live broker message payload against AsyncAPI channel contract
smile test-message ./asyncapi.yaml user/signedup -p '{"userId":"usr_123","email":"alice@example.com"}'
# Bundle a modular spec into a single JSON file
smile bundle ./openapi/main.yaml --out ./dist/api-bundle.jsonNote: OpenAPI runtime tests support
GET,POST,PUT,PATCH, andDELETE. Path parameters need anexampleordefaultvalue to be auto-tested. Postman Collections are traversed recursively, and absolute request URLs are preserved. AsyncAPI runtime validation checks live JSON event payloads against channel schemas.
Install it as a dev dependency to use inside your integration tests:
npm install --save-dev @mrjacket/smileimport {
lintSpec,
validateResponseAgainstSchema,
renderSmileReport,
renderMarkdownReport,
renderAggregateJunitReport
} from "@mrjacket/smile";
it("GET /users returns a valid payload according to the spec", async () => {
const response = await fetch("http://localhost:3000/users");
const body = await response.json();
const violations = validateResponseAgainstSchema(userSchema, body, "GET /users");
expect(violations).toHaveLength(0);
});Extend smile with custom organizational rules using the interactive rule generator:
# Interactive wizard
npx @mrjacket/smile create-rule
# Non-interactive CLI flags
npx @mrjacket/smile create-rule require-team-tag --format openapi --lang tsProtect your repository from broken contracts before bad code is committed:
# Install native pre-commit hook
npx @mrjacket/smile install-hook
# Remove pre-commit hook
npx @mrjacket/smile uninstall-hookBy default, smile is extremely strict—all rules emit an Error and break the CI build.
For enterprise adoption, you can downgrade or disable rules by creating a configuration file in your project root.
The CLI supports the following filenames: config.smile.json, smile.config.json, .smilerc.json, or smile.json.
{
"requestTimeoutMs": 10000,
"maxWarnings": 0,
"rules": {
"missing-operation-id": "warn",
"untyped-property": "off"
}
}Rules set to "warn" will print yellow alerts in the CLI and will exit with code 0 unless --max-warnings threshold is exceeded.
requestTimeoutMs controls the maximum duration of each smile test request.
It must be a positive finite number; invalid or missing values fall back to
30000 milliseconds.
If you need to bypass rules on specific lines without changing the global configuration, you can use inline comment directives directly in your .yaml or .yml specifications:
# smile-ignore-next-line <ruleId>— ignores the specified rule on the next line.# smile-ignore-next-line rule-1, rule-2— ignores multiple comma- or space-separated rules on the next line.# smile-ignore-next-line all— ignores all contract violations on the next line.# smile-ignore-line <ruleId>— ignores the specified rule on the current line.
paths:
/users:
# smile-ignore-next-line missing-summary, missing-operation-id
get:
responses: {}
delete: # smile-ignore-line require-security
responses: {}Full documentation is available in the docs/ directory:
- Getting Started — CLI usage, basic commands, and exit codes.
- CI/CD & DevOps — GitHub Actions, GitLab CI, JUnit, and Webhooks.
- GitHub Action: smile-api-linter on GitHub Marketplace (
x-name15/smile-action@v1).
- GitHub Action: smile-api-linter on GitHub Marketplace (
- VS Code Extension: vscode-smile — Real-time editor diagnostics, Visual Rules Manager, and contract inspection.
- Writing Plugins — How to write and inject custom JavaScript/TypeScript rules.
- Library API — Programmatic usage, Vitest integration, and working with violations.
- Configuration — Complete guide to customizing rules, webhooks, and test headers in your config.smile.json.
- Rules Reference:
- Use at least Node.js v22.12.0+.
- This tool assumes you are parsing JSON or YAML.
- GitHub Action: Drop-in composite action (
x-name15/smile-action@v1) for CI pipelines and GitHub Code Scanning. - VS Code Extension: Official extension with inline diagnostics, AST autofixing, and Visual Rules Manager.
We are keeping the roadmap deliberately small and focused on predictable behavior in libraries and CI/CD pipelines:
- SARIF Autofix Suggestions: Embed machine-readable fix hints inside the SARIF output so GitHub Code Scanning can offer one-click fixes.
If you liked this library or want to support my work, I'd be eternally grateful for a warm coffee! ☕ <3
This project is licensed under the GPL-3.0 License. See the LICENSE file for details.
Author: Mr Jacket / Felix Manrique / x-name15 (we are all the same person)
