{"id":51541818,"url":"https://github.com/microlinkhq/n8n-nodes-microlink","last_synced_at":"2026-07-09T14:01:55.280Z","repository":{"id":365698143,"uuid":"1178697316","full_name":"microlinkhq/n8n-nodes-microlink","owner":"microlinkhq","description":"Official-like n8n integration for Microlink API. Screenshots, metadata extraction, and more.","archived":false,"fork":false,"pushed_at":"2026-06-18T12:51:07.000Z","size":316,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-18T14:15:59.071Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/microlinkhq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-11T09:23:23.000Z","updated_at":"2026-06-18T12:51:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/microlinkhq/n8n-nodes-microlink","commit_stats":null,"previous_names":["microlinkhq/n8n-nodes-microlink"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/microlinkhq/n8n-nodes-microlink","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fn8n-nodes-microlink","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fn8n-nodes-microlink/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fn8n-nodes-microlink/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fn8n-nodes-microlink/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/microlinkhq","download_url":"https://codeload.github.com/microlinkhq/n8n-nodes-microlink/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/microlinkhq%2Fn8n-nodes-microlink/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35301501,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-09T02:00:07.329Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-09T14:01:55.192Z","updated_at":"2026-07-09T14:01:55.266Z","avatar_url":"https://github.com/microlinkhq.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# n8n-nodes-microlink\n\n\u003e Microlink.io integration for n8n — fetch metadata, screenshots, PDFs, Markdown, plain text, audio/video sources, performance insights, logo data (including `logo.palette`), and more from any URL.\n\n\u003ca href=\"https://microlink.io\"\u003e\u003cimg src=\"https://img.shields.io/badge/powered_by-microlink.io-blue?style=flat-square\u0026color=%23EA407B\" alt=\"Powered by microlink.io\"\u003e\u003c/a\u003e\n\u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-purple?style=flat-square\u0026color=%237C3AED\" alt=\"License: MIT\"\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/n8n-nodes-microlink\"\u003e\u003cimg src=\"https://img.shields.io/badge/n8n-community%20node-teal?style=flat-square\u0026color=%230EA5A0\" alt=\"n8n community node\"\u003e\u003c/a\u003e\n\n---\n\n- [Installation](#installation)\n  - [In n8n (recommended)](#in-n8n-recommended)\n  - [Local development](#local-development)\n- [Credentials](#credentials)\n- [Operations](#operations)\n  - [Extract](#extract)\n  - [Screenshot](#screenshot)\n  - [PDF](#pdf)\n  - [Markdown](#markdown)\n  - [Text](#text)\n  - [Audio](#audio)\n  - [Video](#video)\n  - [Insights](#insights)\n  - [Logo](#logo)\n- [Parameters Reference](#parameters-reference)\n  - [Top-level Parameters](#top-level-parameters)\n  - [Response Mode](#response-mode)\n  - [Options](#options)\n  - [Viewport Options](#viewport-options)\n  - [PDF Options](#pdf-options)\n  - [Screenshot Options](#screenshot-options)\n  - [JSON Options](#json-options)\n  - [Additional Query Parameters](#additional-query-parameters)\n- [Internal Utilities](#internal-utilities)\n  - [isPlainObject](#isplainobject)\n  - [flattenObject](#flattenobject)\n  - [parseLooseValue](#parseloosevalue)\n  - [OBJECT\\_PARAMS](#object_params)\n- [Testing](#testing)\n  - [Transpiling TypeScript](#transpiling-typescript)\n  - [Running Tests](#running-tests)\n  - [Test Architecture](#test-architecture)\n  - [Why These Tests](#why-these-tests)\n  - [Coverage](#coverage)\n- [Publishing to n8n](#publishing-to-n8n)\n- [License](#license)\n\n---\n\n## Installation\n\n### In n8n (recommended)\n\n1. Open your n8n instance.\n2. Go to **Settings \u003e Community Nodes**.\n3. Enter `n8n-nodes-microlink` and click **Install**.\n4. The **Microlink** node will appear in the node panel.\n\n### Local development\n\n```bash\ngit clone https://github.com/microlinkhq/n8n-nodes-microlink.git\ncd n8n-nodes-microlink\nnpm install\nnpm run build\n```\n\nTo link the node into a local n8n instance for testing:\n\n```bash\n# From this project's root\nnpm link\n\n# From your n8n installation directory\nnpm link n8n-nodes-microlink\n\n# Start n8n\nnpx n8n start\n```\n\nWhen developing locally, rebuild after source changes:\n\n```bash\nnpm run build\n```\n\n---\n\n## Credentials\n\nCreate **Microlink API** credentials inside n8n:\n\n| Field | Type | Required | Description |\n|-------|------|----------|-------------|\n| **API Key** | `string` (password) | No | Your Microlink Pro/Enterprise API key. Leave empty for free-tier usage. |\n| **Base URL** | `string` | No | Override the API endpoint. Leave empty to auto-select: `https://api.microlink.io` (free) or `https://pro.microlink.io` (when an API key is set). |\n\nThe node automatically selects the correct endpoint based on whether an API key is present. When a key is provided, every request includes an `x-api-key` header.\n\n---\n\n## Operations\n\nThe Microlink node exposes **nine operations**, each targeting a different capability of the [Microlink API](https://microlink.io/docs/api).\n\n### Extract\n\n**Default operation.** Returns metadata and structured data for any URL — title, description, author, image, logo, publisher, language, and more.\n\n```\nOperation: Extract\nURL: https://github.com\nResponse Mode: Auto\n```\n\nReturns the full Microlink API JSON response with `status` and `data` fields.\n\n### Screenshot\n\nGenerates a [browser-rendered screenshot](https://microlink.io/screenshot) of the target page. Combines with [viewport options](#viewport-options) and [screenshot options](#screenshot-options) for resolution, full-page captures, element targeting, overlays, and format control.\n\n```\nOperation: Screenshot\nURL: https://example.com\nOptions → Screenshot Full Page: true\nOptions → Screenshot Type: jpeg\n```\n\n### PDF\n\nGenerates a PDF document of the target page. Combines with [viewport options](#viewport-options) and [PDF options](#pdf-options) for rendering size, paper format, margins, landscape mode, and page ranges.\n\n```\nOperation: PDF\nURL: https://example.com\nOptions → PDF Format: A4\nOptions → PDF Landscape: true\n```\n\n### Markdown\n\nReturns the page content converted to Markdown. This operation uses a specialized configuration under the hood — it sets `force=true`, `meta=false`, `embed=markdown`, and extracts the markdown via Microlink's `data` + `embed` pattern.\n\n```\nOperation: Markdown\nURL: https://example.com/blog/post\n```\n\nReturns the Markdown string directly as `{ data: \"# Page Title\\n...\" }`.\n\n### Text\n\nReturns the page content converted to plain text. This operation mirrors Markdown behavior but uses text extraction under the hood — it sets `force=true`, `meta=false`, `embed=text`, and extracts text via Microlink's `data` + `embed` pattern.\n\n```\nOperation: Text\nURL: https://example.com/blog/post\n```\n\nReturns the plain text string directly as `{ data: \"Page Title ...\" }`.\n\n### Audio\n\nDetects and returns playable audio sources from the target page (e.g., podcasts, music embeds, audio players).\n\n```\nOperation: Audio\nURL: https://soundcloud.com/artist/track\n```\n\n### Video\n\nDetects and returns playable video sources from the target page (e.g., YouTube, Vimeo, embedded players).\n\n```\nOperation: Video\nURL: https://www.youtube.com/watch?v=dQw4w9WgXcQ\n```\n\n### Insights\n\nRetrieves performance metrics and technology stack information for the target URL — Lighthouse scores, technology detection, and more.\n\n```\nOperation: Insights\nURL: https://example.com\n```\n\n### Logo\n\nReturns logo metadata from the target page, including `logo.palette`.\n\n```\nOperation: Logo\nURL: https://example.com\n```\n\n---\n\n## Parameters Reference\n\n### Top-level Parameters\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|----------|---------|-------------|\n| **Operation** | `options` | Yes | `extract` | One of: `extract`, `screenshot`, `pdf`, `markdown`, `text`, `audio`, `video`, `insights`, `logo`. |\n| **URL** | `string` | Yes | — | The target URL to analyze. |\n| **Response Mode** | `options` | Yes | `auto` | How to return the response. See below. |\n| **Binary Property** | `string` | Only for `binary` mode | `data` | The output property name for binary data. |\n\n### Response Mode\n\n| Mode | Behavior |\n|------|----------|\n| **Auto** | Returns JSON by default. If `embed` is set in the query string (explicitly or via the Markdown operation), returns text instead. |\n| **JSON** | Always returns the full Microlink API JSON response. |\n| **Text** | Returns the raw response body as `{ data: \u003cresponse\u003e }`. |\n| **Binary** | Downloads the response as binary data (e.g., screenshot image, PDF file) and attaches it to the configured binary property. Sets `encoding: null` on the HTTP request. |\n\n### Options\n\nAll options are optional. Empty strings and zero values are automatically excluded from the request.\nFor `screenshot`, `pdf`, and `insights`, when nested options are present (e.g. `screenshot.fullPage`, `pdf.width`, `insights.lighthouse`), the node omits the top-level boolean (`screenshot=true`, `pdf=true`, `insights=true`) so nested values are not overridden.\n\n#### Browser \u0026 Rendering\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| Ad Block | `boolean` | `adblock` | Block ads during page load. |\n| Animations | `boolean` | `animations` | Enable/disable CSS animations. |\n| JavaScript | `boolean` | `javascript` | Enable/disable JavaScript execution (default: `true`). |\n| Prerender | `boolean` | `prerender` | Pre-render the page with a headless browser. |\n| Click | `string` | `click` | CSS selector to click before capture. |\n| Scroll | `string` | `scroll` | Scroll instructions — pixel value (`\"1000\"`) or CSS selector (`\"#footer\"`). |\n| Wait For Selector | `string` | `waitForSelector` | Wait until a CSS selector appears in the DOM. |\n| Wait For Timeout | `number` | `waitForTimeout` | Wait a fixed number of milliseconds. |\n| Wait Until | `string` | `waitUntil` | Navigation event: `load`, `domcontentloaded`, `networkidle0`, `networkidle2`. |\n| Device | `string` | `device` | Emulate a device (e.g., `\"iPhone X\"`, `\"Pixel 5\"`). |\n| Color Scheme | `options` | `colorScheme` | Force a preferred color scheme: `dark`, `light`, or `no-preference`. |\n| Media Type | `string` | `mediaType` | CSS media type: `\"screen\"` or `\"print\"`. |\n| Scripts | `string` | `scripts` | Inject external script URLs. |\n| Styles | `string` | `styles` | Inject CSS styles. |\n| Modules | `string` | `modules` | Inject ES module URLs. |\n| Function | `string` | `function` | Execute a custom function on the page. |\n\n#### Data \u0026 Response\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| Meta | `boolean` | `meta` | Include metadata in the response (default: `true`). |\n| Audio | `boolean` | `audio` | Include audio sources in the response. |\n| Video | `boolean` | `video` | Include video sources in the response. |\n| Insights | `boolean` | `insights` | Include performance insights in the response. |\n| Logo | `boolean` | `palette` | Include logo data (including `logo.palette`) in the response. |\n| PDF | `boolean` | `pdf` | Include PDF generation in the response. |\n| Screenshot | `boolean` | `screenshot` | Include screenshot in the response. |\n| Filter | `string` | `filter` | Filter response fields. |\n| Embed | `string` | `embed` | Return a specific field directly instead of the full JSON envelope. |\n| Filename | `string` | `filename` | Suggested filename for binary downloads. |\n\n#### Caching \u0026 Network\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| Force | `boolean` | `force` | Bypass the cache and generate a fresh response. |\n| Retry | `number` | `retry` | Number of retry attempts on failure. |\n| Timeout (Milliseconds) | `number` | `timeout` | Maximum time to wait for the page in milliseconds. |\n| TTL (Seconds) | `number` | `ttl` | Cache time-to-live in seconds. |\n| Stale TTL (Seconds) | `number` | `staleTtl` | Stale cache TTL in seconds. |\n| Ping | `boolean` | `ping` | Warm the cache without returning data. |\n| Proxy | `string` | `proxy` | Proxy mode or URL. |\n\n### Viewport Options\n\nThese options map to Microlink's `viewport.*` API parameters and are compatible with screenshot and PDF rendering.\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| Viewport Width | `number` | `viewport.width` | Page width in pixels. |\n| Viewport Height | `number` | `viewport.height` | Page height in pixels. |\n| Viewport Device Scale Factor | `number` | `viewport.deviceScaleFactor` | Device pixel ratio / scale factor. |\n| Viewport Is Mobile | `boolean` | `viewport.isMobile` | Whether to emulate a mobile viewport. |\n| Viewport Has Touch | `boolean` | `viewport.hasTouch` | Whether touch events are available. |\n| Viewport Is Landscape | `boolean` | `viewport.isLandscape` | Whether to emulate landscape orientation. |\n\n### PDF Options\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| PDF Format | `string` | `pdf.format` | Paper format: `A4`, `Letter`, `Legal`, etc. |\n| PDF Width | `string` | `pdf.width` | Custom page width (e.g., `\"210mm\"`). |\n| PDF Height | `string` | `pdf.height` | Custom page height (e.g., `\"297mm\"`). |\n| PDF Landscape | `boolean` | `pdf.landscape` | Landscape orientation. |\n| PDF Margin | `string` | `pdf.margin` | Page margin (e.g., `\"10mm\"`). |\n| PDF Page Ranges | `string` | `pdf.pageRanges` | Page range to print (e.g., `\"1-3\"`). |\n| PDF Scale | `number` | `pdf.scale` | Scale factor (e.g., `0.8`). |\n\n### Screenshot Options\n\n| Option | Type | API Parameter | Description |\n|--------|------|---------------|-------------|\n| Screenshot Type | `string` | `screenshot.type` | Image format: `\"png\"` or `\"jpeg\"`. |\n| Screenshot Full Page | `boolean` | `screenshot.fullPage` | Capture the entire scrollable page. |\n| Screenshot Element | `string` | `screenshot.element` | CSS selector to capture a specific element. |\n| Screenshot Omit Background | `boolean` | `screenshot.omitBackground` | Transparent background. |\n| Screenshot Overlay Background | `string` | `screenshot.overlay.background` | Overlay background. Default: `linear-gradient(225deg, #FF057C 0%, #8D0B93 50%, #321575 100%)`. |\n| Screenshot Overlay Browser | `string` | `screenshot.overlay.browser` | Overlay browser theme. Default: `dark`. |\n| Screenshot Code Scheme | `string` | `screenshot.codeScheme` | Syntax highlighting theme. |\n\n### JSON Options\n\nFor complex structured parameters, the node provides dedicated JSON fields that are automatically flattened into dot-notation query parameters.\n\n| Option | API Prefix | Description |\n|--------|------------|-------------|\n| Data (JSON) | `data.*` | Custom data extraction rules. Example: `{ \"author\": { \"selector\": \".author\", \"attr\": \"text\" } }` becomes `data.author.selector=.author\u0026data.author.attr=text`. |\n| Meta (JSON) | `meta.*` | Custom meta extraction rules. |\n| Headers (JSON) | `headers.*` | Custom HTTP headers to send with the request. |\n| Viewport (JSON) | `viewport.*` | Custom viewport dimensions and settings (advanced/nested form). |\n| Insights (JSON) | `insights.*` | Insights configuration object. |\n\n### Additional Query Parameters\n\nFor any Microlink API parameter not covered by the built-in options, use **Additional Query Parameters**. Each entry is a key-value pair.\n\n- Keys support dot-notation (e.g., `data.author.selector`).\n- Values are automatically parsed: `\"true\"` / `\"false\"` become booleans, numeric strings become numbers, and JSON strings are parsed and flattened.\n- Additional parameters are applied last and **override** any previously set options.\n\nThis is also how to pass fields that support boolean **or** object payloads:\n\n```\nKey:   screenshot\nValue: true\n\nKey:   screenshot\nValue: {\"fullPage\":true}\n```\n\n```\nKey:   data.price.selector\nValue: .product-price\n\nKey:   force\nValue: true\n```\n\n---\n\n## Internal Utilities\n\nThe node exports four internal utilities used to build query strings from the nested options structure. These are also available for import if you need to use them in other contexts.\n\n### isPlainObject\n\n```js\nisPlainObject(value) → boolean\n```\n\nReturns `true` if `value` is a non-null, non-array object. Used throughout the node to decide whether a value should be recursively flattened or passed as-is.\n\n### flattenObject\n\n```js\nflattenObject(prefix, obj, target) → void\n```\n\nRecursively flattens a nested object into dot-notation key-value pairs on the `target` object. Arrays are serialized to JSON strings.\n\n| Input | Output |\n|-------|--------|\n| `flattenObject('data', { author: { selector: '.a' } }, {})` | `{ 'data.author.selector': '.a' }` |\n| `flattenObject('data', { tags: ['a', 'b'] }, {})` | `{ 'data.tags': '[\"a\",\"b\"]' }` |\n| `flattenObject('', { key: 'val' }, {})` | `{ key: 'val' }` |\n\nThis is essential for the Microlink API, which accepts nested parameters as flat dot-notation query string keys.\n\n### parseLooseValue\n\n```js\nparseLooseValue(value) → boolean | number | object | array | string\n```\n\nCoerces string values from Additional Query Parameters into their natural JavaScript types:\n\n| Input | Output | Type |\n|-------|--------|------|\n| `\"true\"` | `true` | boolean |\n| `\"false\"` | `false` | boolean |\n| `\"42\"` | `42` | number |\n| `\"-3.14\"` | `-3.14` | number |\n| `'{\"a\":1}'` | `{ a: 1 }` | object |\n| `'[1,2]'` | `[1, 2]` | array |\n| `\"hello\"` | `\"hello\"` | string |\n| `\"1e5\"` | `\"1e5\"` | string (scientific notation is not parsed) |\n\nNon-string inputs are returned unchanged. Invalid JSON-like strings (e.g., `\"{ invalid }\"`) are kept as strings.\n\n### OBJECT_PARAMS\n\n```js\nOBJECT_PARAMS = new Set(['data', 'meta', 'headers', 'viewport', 'insights'])\n```\n\nThe set of parameter keys that, when their value is a plain object, should be flattened into dot-notation query parameters rather than passed directly. All other keys are passed as scalar values.\n\n---\n\n## Testing\n\n### Transpiling TypeScript\n\nThis project is authored in TypeScript and compiled to `dist/` for n8n runtime usage.\n\n```bash\n# Compile source into dist/\nnpm run build\n```\n\nGenerated artifacts:\n\n```\ndist/\n  credentials/MicrolinkApi.credentials.js\n  nodes/Microlink/Microlink.node.js\n  nodes/Microlink/microlink.svg\n```\n\n### Running Tests\n\n```bash\n# Run all tests\nnpm test\n\n# Run tests in watch mode\nnpm test -- --watch\n\n# Run with coverage report\nnpm run test:coverage\n\n# Run a specific test file\nnpx jest nodes/Microlink/Microlink.node.test.js\nnpx jest credentials/MicrolinkApi.credentials.test.js\n```\n\n### Test Architecture\n\nTests are colocated next to the source files they cover, following n8n's own convention:\n\n```\ncredentials/\n  MicrolinkApi.credentials.ts          # source\n  MicrolinkApi.credentials.test.js     # 12 tests\nnodes/Microlink/\n  Microlink.node.ts                    # source\n  Microlink.node.test.js               # 240 tests\n```\n\nThe `n8n-workflow` peer dependency is **fully mocked** — tests run without installing n8n itself. The mock provides `NodeConnectionTypes.Main` and a lightweight `NodeOperationError` class. The node's `execute()` method is tested by constructing a mock execution context that replicates n8n's runtime interface (`getInputData`, `getNodeParameter`, `getCredentials`, `helpers.httpRequest`, etc.) and calling `execute.call(mockContext)`.\n\n### Why These Tests\n\nThe test suite is organized into **focused layers**, each with a distinct purpose:\n\n| Layer | Tests | Why |\n|-------|-------|-----|\n| **Utility functions** (`isPlainObject`, `flattenObject`, `parseLooseValue`, `OBJECT_PARAMS`) | 27 | These pure functions are the foundation of query string construction. Testing them in isolation catches type-coercion bugs and edge cases (null, arrays, scientific notation, invalid JSON) before they propagate into API requests. |\n| **Credential structure** | 12 | Credentials are loaded by n8n based on their declared structure. Incorrect names, missing defaults, or wrong types cause silent failures at runtime. These tests lock down the contract. |\n| **Node description** | 17 | The description object is n8n's UI contract — operations, property types, defaults, and display conditions. A missing operation or wrong default can break the entire node in the n8n editor. Structural tests prevent regressions. |\n| **Operations** (9 operations) | 15 | Each operation maps to different query parameters. The markdown and text operations have special behavior (force, meta, embed, data extraction). Operation tests verify the correct flags reach the HTTP request. |\n| **Response modes** (auto, json, text, binary) | 11 | Response handling has four distinct code paths including buffer conversion, binary property naming, and automatic text detection via `embed`. These tests verify each path produces the correct output shape. |\n| **Credentials \u0026 base URL** | 7 | The node auto-selects between free (`api.microlink.io`) and pro (`pro.microlink.io`) endpoints, handles custom URLs, whitespace trimming, and null/undefined credentials. These tests cover every routing combination. |\n| **Simple options** (boolean, string, number) | 58 | Every option type has different inclusion/exclusion rules: booleans pass through even when `false`, strings are excluded when empty, numbers are excluded when zero. Parametric `it.each` tests cover all options in both included and excluded states. |\n| **JSON options** (data, meta, headers, viewport, insights) | 9 | JSON options are merged with existing values and flattened into dot-notation. The merge logic is subtle — markdown/text operations pre-set `data`, and `insights` can be a boolean that needs overwriting. These tests verify correct merging and flattening. |\n| **Additional parameters** | 7 | Additional params are the escape hatch for any API parameter. They support type coercion, JSON flattening, and override previously set values. Tests cover parsing, empty-key skipping, and override behavior. |\n| **Query string building** | 4 | Validates the final assembly: URL is always present, nulls are filtered, objects are flattened, scalars pass through. |\n| **Error handling** | 5 | Tests the three error paths: `NodeOperationError` wrapping, context preservation with `itemIndex`, and `continueOnFail` graceful degradation. |\n| **Multiple items** | 2 | n8n processes items in batches. Tests verify independent per-item processing and that errors in one item don't block others when `continueOnFail` is enabled. |\n| **Option overrides \u0026 combinations** | 6 | Real-world usage combines operations with options, credentials with additional params, and overrides at multiple levels. Integration-style tests verify these combinations work together correctly. |\n| **Request shape** | 6 | HTTP method, `json` flag, and `encoding` must be set correctly for every response mode. These tests are the final gate before the request leaves the node. |\n\n### Coverage\n\n```\n------------------------------|---------|----------|---------|---------|\nFile                          | % Stmts | % Branch | % Funcs | % Lines |\n------------------------------|---------|----------|---------|---------|\nAll files                     |   99.24 |    96.09 |     100 |     100 |\n MicrolinkApi.credentials.ts  |     100 |      100 |     100 |     100 |\n Microlink.node.ts            |   99.21 |    96.09 |     100 |     100 |\n------------------------------|---------|----------|---------|---------|\n```\n\n**254 tests** across 2 test suites. 100% line and function coverage.\n\n---\n\n## Publishing to n8n\n\nThis package is published to npm by GitHub Actions with a [provenance](https://docs.npmjs.com/generating-provenance-statements) statement. Since **2026-05-01**, n8n [verified community nodes](https://docs.n8n.io/integrations/community-nodes/) must be published from CI with provenance — nodes published from a local machine are rejected for verification. (A plain local `npm publish` still works for an unverified npm/community install, but it will not pass verification.)\n\nThe release pipeline lives in [`.github/workflows/publish.yml`](.github/workflows/publish.yml): on every published GitHub Release it runs lint, tests, and build, then `npm publish --provenance --access public`.\n\n### 1. Prerequisites\n\n- A [npm account](https://www.npmjs.com/signup) with publish rights to the package.\n- The `package.json` `name` field must start with `n8n-nodes-` (already set to `n8n-nodes-microlink`).\n- The `n8n` field in `package.json` must list all credential and node files (already configured).\n- The `keywords` array must include `\"n8n-community-node-package\"` (already present).\n\n### 2. One-time setup: `NPM_TOKEN` secret\n\n1. Create an npm **Automation** (or **Granular**) access token with publish rights.\n2. In the GitHub repo, open **Settings → Secrets and variables → Actions → New repository secret**.\n3. Name it `NPM_TOKEN` and paste the token.\n\n### 3. Verify locally before releasing\n\nCI re-runs these, but check them first to avoid a failed release:\n\n```bash\nnpm run lint\nnpm test\nnpm run build\n```\n\n### 4. Cut a release\n\n```bash\nnpm version patch   # 0.1.0 → 0.1.1 (bug fixes); use minor / major as appropriate\ngit push --follow-tags\n```\n\nThen create a **GitHub Release** for the new tag (**Releases → Draft a new release → choose the tag → Publish release**). Publishing the release triggers `publish.yml`, which publishes to npm with provenance.\n\n### 5. Verify the publish\n\n- Watch the **Actions** tab for the \"Publish to npm\" run to finish green.\n- Visit `https://www.npmjs.com/package/n8n-nodes-microlink` and confirm the **Provenance** badge appears on the new version.\n\n### 6. Install in n8n\n\nOnce published, any n8n user can install it:\n\n1. Open **Settings \u003e Community Nodes** in their n8n instance.\n2. Search for `n8n-nodes-microlink`.\n3. Click **Install**.\n\nThe node appears in the editor immediately — no restart required on n8n Cloud. Self-hosted instances may need a restart.\n\n### 7. Subsequent releases\n\nRepeat steps 3–5: bump the version, push the tag, and publish a GitHub Release. n8n Cloud picks up new versions automatically; self-hosted users update via **Settings \u003e Community Nodes \u003e Update**.\n\n---\n\n## License\n\n[MIT](LICENSE) \u0026copy; [Microlink](https://microlink.io)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fn8n-nodes-microlink","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicrolinkhq%2Fn8n-nodes-microlink","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicrolinkhq%2Fn8n-nodes-microlink/lists"}