{"_id":"@afixt/wave-node","_rev":"4-e4423b8631f1733f777c937a9e3fbef4","name":"@afixt/wave-node","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@afixt/wave-node","version":"0.1.0","keywords":["accessibility","a11y","wave","webaim","wcag","testing","api"],"author":{"name":"Karl Groves","email":"karl.groves@afixt.com"},"license":"MIT","_id":"@afixt/wave-node@0.1.0","maintainers":[{"name":"karlgroves","email":"karlgroves@gmail.com"}],"dist":{"shasum":"e154ac90578b49c7dbbf20a56939ad5771d6144c","tarball":"https://registry.npmjs.org/@afixt/wave-node/-/wave-node-0.1.0.tgz","fileCount":19,"integrity":"sha512-aSoPiU/pmdzvNBMh5e/EtEey1AxCQ/u9hv9BWYrxpEQrUnRGfo2vKK0ZMSe4XAL9Oaaug9SZcj5H9B9A88KRMA==","signatures":[{"sig":"MEUCIQDOZqTmiU3jiWgGLWiV56RH1ZYuy1b6I5jkp9O76stCPQIgTfaQCWUp6yxQw5S1jV480DisSm55DmJmqOR1HYGmJ7s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35469},"main":"dist/index.js","types":"dist/index.d.ts","engines":{"node":">=14.0.0"},"gitHead":"1b007ec50c7ae2c8e6bdf24cd41cd44a41370bfa","scripts":{"dev":"tsc --watch","lint":"eslint src --ext .ts","test":"jest","build":"tsc","lint:fix":"eslint src --ext .ts --fix","test:unit":"jest --testPathIgnorePatterns=integration","test:watch":"jest --watch","test:coverage":"jest --coverage","prepublishOnly":"npm run build","test:integration":"jest --testPathPattern=integration"},"_npmUser":{"name":"karlgroves","email":"karlgroves@gmail.com"},"_npmVersion":"10.9.2","description":"Node.js client for the WAVE (WebAIM) accessibility testing API","directories":{},"_nodeVersion":"22.16.0","dependencies":{"axios":"^1.7.2","@ngrok/ngrok":"^1.5.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^8.57.0","ts-jest":"^29.1.5","typescript":"^5.4.5","@types/jest":"^29.5.12","@types/node":"^20.14.0","@typescript-eslint/parser":"^7.13.0","@typescript-eslint/eslint-plugin":"^7.13.0"},"_npmOperationalInternal":{"tmp":"tmp/wave-node_0.1.0_1749299255805_0.16462768981122577","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-06-07T12:27:35.804Z","modified":"2026-03-10T18:09:22.596Z","0.1.0":"2025-06-07T12:27:36.002Z"},"author":{"name":"Karl Groves","email":"karl.groves@afixt.com"},"license":"MIT","keywords":["accessibility","a11y","wave","webaim","wcag","testing","api"],"description":"Node.js client for the WAVE (WebAIM) accessibility testing API","maintainers":[{"email":"marko.macmilan@gmail.com","name":"macmilan"},{"email":"john.watts@afixt.com","name":"jw1982"},{"email":"karlgroves@gmail.com","name":"karlgroves"}],"readme":"# wave-node\n\nNode.js client for the WAVE (WebAIM) accessibility testing API. Written in TypeScript with full type definitions included.\n\n## Features\n\n* **URL Analysis** - Test any public website for accessibility issues\n* **Source Analysis** - Test HTML source code without deploying (uses ngrok)\n* **TypeScript Support** - Full type definitions included\n* **Error Handling** - Comprehensive error messages with status codes\n* **Promise-based** - Modern async/await API\n* **Configurable** - Timeout, viewport size, authentication options\n* **Detailed Reports** - Get errors, alerts, features, structure, ARIA, and contrast information\n* **Demo Scripts** - Example implementations included\n\n## Installation\n\n```bash\nnpm install @afixt/wave-node\n```\n\n## Prerequisites\n\n* Node.js 14.0.0 or higher\n* A WAVE API key - register at [https://wave.webaim.org/api/](https://wave.webaim.org/api/)\n* Internet connection (required for ngrok tunneling when using `analyzeSource`)\n* (Optional) ngrok account for `analyzeSource` - free tier available at [https://ngrok.com/](https://ngrok.com/)\n\n## Quick Start\n\n```javascript\nconst { WaveClient } = require('@afixt/wave-node');\n\nconst wave = new WaveClient({ apiKey: 'your-api-key' });\n\n// Analyze a URL\nconst result = await wave.analyze('https://example.com');\nconsole.log(`Found ${Object.keys(result.categories.error || {}).length} accessibility errors`);\n\n// Analyze HTML source (requires ngrok)\nconst htmlResult = await wave.analyzeSource('<html>...</html>');\nconsole.log(`Credits remaining: ${htmlResult.statistics.creditsremaining}`);\n```\n\n## Usage\n\n### Basic Usage\n\n```javascript\nconst { WaveClient } = require('@afixt/wave-node');\n// or\nimport { WaveClient } from '@afixt/wave-node';\n\nconst wave = new WaveClient({\n  apiKey: 'your-api-key'\n});\n\n// Analyze a URL\nconst result = await wave.analyze('https://example.com');\n\nconsole.log(`Errors: ${Object.keys(result.categories.error || {}).length}`);\nconsole.log(`Alerts: ${Object.keys(result.categories.alert || {}).length}`);\nconsole.log(`Features: ${Object.keys(result.categories.feature || {}).length}`);\n```\n\n### Demo Files\n\nThe package includes two demo files that show practical examples of using the WAVE API:\n\n#### test-url.js - Analyze a Public URL\n\nTo run the demos, first clone the repository:\n\n```bash\ngit clone https://github.com/karlgroves/wave-node.git\ncd wave-node\nnpm install\nnpm run build\n\n# Set your API key\nexport WAVE_API_KEY=your_api_key_here\n\n# Run the URL analysis demo\nnode src/demo/test-url.js                    # Analyzes example.com\nnode src/demo/test-url.js https://google.com # Analyzes any public URL\n```\n\nThis demo:\n\n* Analyzes any public URL for accessibility issues\n* Displays a comprehensive report with error counts, alerts, and features\n* Shows detailed error information including WCAG guidelines\n* Highlights contrast issues with color values and ratios\n* Provides actionable feedback and links to the full WAVE report\n\n#### test-source.js - Analyze HTML Source Code\n\n```bash\n# Set your credentials\nexport WAVE_API_KEY=your_api_key_here\nexport NGROK_AUTHTOKEN=your_ngrok_token_here\n\n# Run the demo\nnode src/demo/test-source.js                      # Uses sample HTML\nnode src/demo/test-source.js path/to/file.html   # Analyzes your HTML file\n```\n\nThis demo:\n\n* Analyzes HTML source code without needing a public URL\n* Creates a temporary ngrok tunnel for WAVE API access\n* Includes sample HTML with both good and bad accessibility practices\n* Shows how to analyze local development files\n* Demonstrates the full `analyzeSource()` workflow\n\nBoth demos include comprehensive error handling and helpful messages for common issues like missing API keys or insufficient credits.\n\n### TypeScript Usage\n\n```typescript\nimport { WaveClient, WaveAnalysisResult } from '@afixt/wave-node';\n\nconst wave = new WaveClient({\n  apiKey: process.env.WAVE_API_KEY!,\n  timeout: 60000 // 60 seconds\n});\n\ntry {\n  const result: WaveAnalysisResult = await wave.analyze('https://example.com', {\n    reporttype: 1,\n    viewportwidth: 1200,\n    viewportheight: 800\n  });\n\n  // Process errors\n  if (result.categories.error) {\n    for (const [errorType, errorData] of Object.entries(result.categories.error)) {\n      console.log(`${errorType}: ${errorData.count} instances`);\n      console.log(`Description: ${errorData.description}`);\n    }\n  }\n} catch (error) {\n  console.error('Analysis failed:', error.message);\n}\n```\n\n### Analyzing HTML Source\n\nYou can analyze HTML source code directly without needing a public URL:\n\n```javascript\nconst htmlSource = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <title>Test Page</title>\n</head>\n<body>\n    <h1>Welcome</h1>\n    <img src=\"logo.png\">\n    <p>This is a test page.</p>\n</body>\n</html>\n`;\n\nconst result = await wave.analyzeSource(htmlSource);\nconsole.log(`Errors found: ${Object.keys(result.categories.error || {}).length}`);\n```\n\n#### ngrok Configuration\n\n`analyzeSource` uses ngrok to create a temporary public URL for the WAVE API. While ngrok works without authentication for basic usage, you may want to set up an authtoken for:\n\n* Higher rate limits\n* Longer session times\n* Custom domains (paid plans)\n\nTo configure ngrok with an authtoken:\n\n1. Sign up for a free ngrok account at [https://ngrok.com/](https://ngrok.com/)\n2. Get your authtoken from the ngrok dashboard\n3. Set it using one of these methods:\n\n##### Option 1: Environment Variable\n\n```bash\nexport NGROK_AUTHTOKEN=your_authtoken_here\n```\n\n##### Option 2: ngrok Configuration File\n\n```bash\nngrok config add-authtoken your_authtoken_here\n```\n\n##### Option 3: Programmatically\n\n```javascript\nimport { setAuthtoken } from '@ngrok/ngrok';\n\n// Set authtoken before using analyzeSource\nawait setAuthtoken('your_authtoken_here');\n\n// Then use wave.analyzeSource as normal\nconst result = await wave.analyzeSource(htmlSource);\n```\n\n**Note**: The module will work without an authtoken, but you may encounter rate limits with heavy usage. This is especially true if using as part of CI/ CD or running a large set of automated functional testing\n\n### Advanced Options\n\n```javascript\nconst result = await wave.analyze('https://example.com', {\n  reporttype: 2,        // 1-4, controls level of detail\n  format: 'json',       // 'json' or 'xml'\n  viewportwidth: 1920,  // Viewport width for analysis (default: 1200)\n  viewportheight: 1080, // Viewport height for analysis\n  evaldelay: 2000,      // Delay before evaluation in ms (default: 250)\n  username: 'user',     // Username for authenticated pages\n  password: 'pass',     // Password for authenticated pages\n  useragent: 'Mozilla/5.0...' // Custom user agent string\n});\n\n// Options work the same way with analyzeSource\nconst sourceResult = await wave.analyzeSource(htmlSource, {\n  reporttype: 2,\n  viewportwidth: 1920\n});\n```\n\n#### Report Types\n\n* **Type 1** (1 credit): Basic statistics only\n* **Type 2** (2 credits): Includes detailed error/alert/feature listings\n* **Type 3** (3 credits): Adds XPath selectors for elements\n* **Type 4** (3 credits): Adds CSS selectors for elements\n\n## API Reference\n\n### WaveClient\n\n#### Constructor\n\n```typescript\nnew WaveClient(options: WaveOptions)\n```\n\nOptions:\n\n* `apiKey` (required): Your WAVE API key\n* `baseUrl` (optional): API base URL (default: `https://wave.webaim.org/api`)\n* `timeout` (optional): Request timeout in milliseconds (default: 30000)\n\n#### Methods\n\n##### analyze(url: string, options?: WaveAnalysisOptions): Promise&lt;WaveAnalysisResult&gt;\n\nAnalyzes a URL for accessibility issues.\n\nParameters:\n\n* `url`: The URL to analyze (must be publicly accessible)\n* `options`: Optional analysis parameters (see below)\n\n##### analyzeSource(source: string, options?: WaveAnalysisOptions): Promise&lt;WaveAnalysisResult&gt;\n\nAnalyzes HTML source code for accessibility issues by creating a temporary public URL via ngrok.\n\nParameters:\n\n* `source`: HTML source code as a string (can include inline CSS and JavaScript)\n* `options`: Optional analysis parameters (see below)\n\n###### How it works\n\n1. Creates a local HTTP server serving your HTML source\n2. Establishes an ngrok tunnel to make it publicly accessible\n3. Sends the ngrok URL to WAVE API for analysis\n4. Automatically cleans up the server and tunnel after completion\n\n###### Requirements\n\n* Active internet connection\n* Port availability for local server (uses random port)\n* Optional: ngrok authtoken for extended usage\n\n#### Analysis Options\n\nBoth `analyze` and `analyzeSource` accept the following options:\n\n* `reporttype`: Level of report detail (1-4, default: 1)\n* `format`: Response format ('json' or 'xml', default: 'json')\n* `viewportwidth`: Browser viewport width in pixels (default: 1200)\n* `viewportheight`: Browser viewport height in pixels\n* `evaldelay`: Delay before evaluation in milliseconds (default: 250)\n* `username`: Username for HTTP authentication\n* `password`: Password for HTTP authentication\n* `useragent`: Custom user agent string for browser simulation\n\n### Response Structure\n\nThe analysis result includes:\n\n* `status`: Success status and HTTP status code\n* `statistics`: Page statistics including title, URL, credits remaining\n* `categories`: Accessibility findings organized by type\n  * `error`: Accessibility errors\n  * `alert`: Accessibility alerts\n  * `feature`: Accessibility features\n  * `structure`: Structural elements\n  * `aria`: ARIA usage\n  * `contrast`: Contrast issues\n\n## Error Handling\n\nThe client throws `WaveApiError` for API-related errors:\n\n```javascript\ntry {\n  const result = await wave.analyze('https://example.com');\n} catch (error) {\n  if (error.code === 'INVALID_KEY') {\n    console.error('Invalid API key');\n  } else if (error.statusCode === 429) {\n    console.error('Rate limit exceeded');\n  } else {\n    console.error('Error:', error.message);\n  }\n}\n```\n\n## Credits and Pricing\n\nEach API request consumes credits:\n\n* Basic page analysis: 1 credit\n* Advanced features: 2-3 credits\n\nMonitor your remaining credits:\n\n```javascript\nconst result = await wave.analyze('https://example.com');\nconsole.log(`Credits remaining: ${result.statistics.creditsremaining}`);\n```\n\n## License\n\nMIT\n\n## Troubleshooting\n\n### analyzeSource Issues\n\n#### Error: \"Failed to connect to ngrok\"\n\n* Ensure you have an active internet connection\n* Check if your firewall is blocking ngrok\n* Try setting an authtoken (see ngrok Configuration above)\n\n#### Error: \"ngrok tunnel expired\"\n\n* Free ngrok accounts have session limits\n* Consider setting up an authtoken for longer sessions\n* The module automatically retries once on tunnel errors\n\n#### Timeout errors\n\n* Increase the timeout in WaveClient options\n* Check if the HTML contains external resources that are slow to load\n* Consider using the `evaldelay` option to give the page more time to render\n\n## Security Considerations\n\nWhen using `analyzeSource`:\n\n* The HTML content is temporarily exposed via a public ngrok URL\n* The server and tunnel are automatically cleaned up after analysis\n* Consider the sensitivity of your HTML content before using this feature\n* For highly sensitive content, use the standard `analyze()` method with your own secure hosting\n\n## Testing\n\nThe module includes comprehensive test coverage with both unit and integration tests.\n\n### Running Tests\n\n```bash\n# All tests\nnpm test\n\n# Unit tests only\nnpm run test:unit\n\n# Integration tests only (requires API keys)\nnpm run test:integration\n\n# Watch mode\nnpm run test:watch\n\n# Coverage report\nnpm run test:coverage\n```\n\n### Integration Tests\n\nIntegration tests require environment variables:\n\n```bash\nexport WAVE_API_KEY=your_wave_api_key\nexport NGROK_AUTHTOKEN=your_ngrok_token  # Optional, for analyzeSource tests\nnpm run test:integration\n```\n\n## Contributing\n\nContributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details on the process for submitting pull requests.\n\nAll contributions are expected to abide by our [Code of Conduct](CODE_OF_CONDUCT.md).\n\n### Development Scripts\n\n```bash\nnpm run build       # Build TypeScript to JavaScript\nnpm run dev         # Build in watch mode\nnpm run lint        # Run ESLint\nnpm run lint:fix    # Fix linting issues\nnpm test            # Run all tests\nnpm run test:unit   # Run unit tests only\nnpm run test:integration # Run integration tests (requires API keys)\n```\n\n## Additional Resources\n\n### WAVE Documentation API\n\nTo get detailed information about specific WAVE issue types, you can use the documentation API:\n\n```text\nhttps://wave.webaim.org/api/docs?id={item_id}\n```\n\nFor a full list of all WAVE issue types and their descriptions:\n\n```text\nhttps://wave.webaim.org/api/docs\n```\n\n## Links\n\n* [GitHub Repository](https://github.com/karlgroves/wave-node)\n* [NPM Package](https://www.npmjs.com/package/@afixt/wave-node)\n* [WAVE API Documentation](https://wave.webaim.org/api/)\n* [WAVE API Details](https://wave.webaim.org/api/details)\n* [WAVE Web Interface](https://wave.webaim.org/)\n* [WebAIM](https://webaim.org/)\n","readmeFilename":"README.md"}