{"id":50973624,"url":"https://github.com/node-opcua/node-i3x","last_synced_at":"2026-06-19T05:03:19.211Z","repository":{"id":363681001,"uuid":"1264436105","full_name":"node-opcua/node-i3x","owner":"node-opcua","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-13T13:11:22.000Z","size":1222,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T13:15:47.667Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/node-opcua.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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-06-09T22:09:31.000Z","updated_at":"2026-06-13T13:11:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/node-opcua/node-i3x","commit_stats":null,"previous_names":["node-opcua/i3x2ua-node","node-opcua/node-i3x"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/node-opcua/node-i3x","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-opcua%2Fnode-i3x","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-opcua%2Fnode-i3x/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-opcua%2Fnode-i3x/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-opcua%2Fnode-i3x/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/node-opcua","download_url":"https://codeload.github.com/node-opcua/node-i3x/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/node-opcua%2Fnode-i3x/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34517752,"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-06-19T02:00:06.005Z","response_time":61,"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-06-19T05:03:18.393Z","updated_at":"2026-06-19T05:03:19.202Z","avatar_url":"https://github.com/node-opcua.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# node-i3x\n\n\u003e TypeScript implementation of the i3X Beta specification — bridging OPC UA industrial automation to a modern REST API\n\n\u003c!-- Badges --\u003e\n[![CI](https://github.com/node-opcua/node-i3x/actions/workflows/ci.yml/badge.svg)](https://github.com/node-opcua/node-i3x/actions/workflows/ci.yml)\n[![Coverage Status](https://coveralls.io/repos/github/node-opcua/node-i3x/badge.svg?branch=main)](https://coveralls.io/github/node-opcua/node-i3x?branch=main)\n[![npm downloads/month](https://img.shields.io/npm/dm/@node-i3x/app?label=downloads%2Fmonth\u0026logo=npm)](https://www.npmjs.com/package/@node-i3x/app)\n[![npm downloads](https://img.shields.io/npm/dt/@node-i3x/app?label=total%20downloads\u0026logo=npm)](https://www.npmjs.com/package/@node-i3x/app)\n[![License: AGPL-3.0 OR Commercial](https://img.shields.io/badge/license-AGPL--3.0%20%7C%20Commercial-blue)](LICENSE)\n[![Node.js \u003e= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen?logo=node.js)](https://nodejs.org)\n[![TypeScript 5.7](https://img.shields.io/badge/TypeScript-5.7-blue?logo=typescript)](https://typescriptlang.org)\n[![Biome](https://img.shields.io/badge/linter-Biome-60a5fa?logo=biome)](https://biomejs.dev)\n[![Built by Sterfive](https://img.shields.io/badge/built%20by-Sterfive-ff6600)](https://sterfive.com)\n\n---\n\n## Overview\n\n**node-i3x** converts OPC UA address spaces into [i3X](https://i3x.dev)-compliant REST/JSON endpoints. It exposes industrial automation data through a clean HTTP API with:\n\n- **Stable element IDs** — deterministic, namespace-URI-based identifiers that survive server restarts\n- **Real-time subscriptions** — long-poll and Server-Sent Events (SSE) for live value updates\n- **Historical data access** — query time-series history for any monitored variable\n- **Two connector modes** — connect to a remote OPC UA server over TCP, or embed one in-process with zero network overhead\n\nBuilt with [node-opcua](https://node-opcua.github.io/), [Fastify](https://fastify.dev/), and a hexagonal (ports \u0026 adapters) architecture.\n\n---\n\n## Architecture\n\n\u003c!-- mermaid-img --\u003e\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"https://mermaid.ink/svg/Z3JhcGggVEIKICAgIENsaWVudChbIuKYgSBIVFRQIENsaWVudCJdKQoKICAgIHN1YmdyYXBoIEFQUFsiQG5vZGUtaTN4L2FwcCDigJQgQ29tcG9zaXRpb24gUm9vdCJdCiAgICAgICAgZGlyZWN0aW9uIFRCCgogICAgICAgIHN1YmdyYXBoIElOQk9VTkRbIklOQk9VTkQgQURBUFRFUiJdCiAgICAgICAgICAgIFJFU1RbIkBub2RlLWkzeC9yZXN0LXNlcnZlcjxici8+RmFzdGlmeSByb3V0ZXMg4oCUIGkzWCBCZXRhIEFQSSJdCiAgICAgICAgZW5kCgogICAgICAgIHN1YmdyYXBoIENPUkVbIkRPTUFJTiBDT1JFIOKAlCBaRVJPIERFUEVOREVOQ0lFUyJdCiAgICAgICAgICAgIENvcmVbIkBub2RlLWkzeC9jb3JlPGJyLz5Eb21haW4gTW9kZWxzIMK3IFNlcnZpY2VzIMK3IFBvcnQgSW50ZXJmYWNlczxici8+U3RhYmxlIElEcyDCtyBTdWJzY3JpcHRpb25zIMK3IEhpc3RvcnkiXQogICAgICAgIGVuZAoKICAgICAgICBzdWJncmFwaCBPVVRCT1VORFsiT1VUQk9VTkQgQURBUFRFUlMiXQogICAgICAgICAgICBPUENbIkBub2RlLWkzeC9vcGN1YS1jb25uZWN0b3I8YnIvPm5vZGUtb3BjdWEgY2xpZW50IChyZW1vdGUpIl0KICAgICAgICAgICAgUHNldWRvWyJAbm9kZS1pM3gvcHNldWRvLXNlc3Npb24tY29ubmVjdG9yPGJyLz5Qc2V1ZG9TZXNzaW9uIChlbWJlZGRlZCkiXQogICAgICAgIGVuZAogICAgZW5kCgogICAgT1BDVUEoWyLimqkgT1BDIFVBIFNlcnZlciJdKQoKICAgIENsaWVudCA8LS0+fCJIVFRQIC8gSlNPTiJ8IFJFU1QKICAgIFJFU1QgLS0+fCJ1c2VzIHBvcnRzInwgQ29yZQogICAgQ29yZSAtLT58IklEYXRhU291cmNlUG9ydCJ8IE9QQwogICAgQ29yZSAtLT58IklEYXRhU291cmNlUG9ydCJ8IFBzZXVkbwogICAgT1BDIDwtLT58Ik9QQyBVQSBUQ1AiPHwgT1BDVUEKICAgIFBzZXVkbyA8LS0+fCJJbi1wcm9jZXNzInwgT1BDVUE=\" alt=\"node-i3x architecture\" /\u003e\n\u003c/p\u003e\n\n\u003cdetails\u003e\u003csummary\u003eDiagram source (mermaid)\u003c/summary\u003e\n\n```mermaid\ngraph TB\n    Client([\"☁ HTTP Client\"])\n\n    subgraph APP[\"@node-i3x/app — Composition Root\"]\n        direction TB\n\n        subgraph INBOUND[\"INBOUND ADAPTER\"]\n            REST[\"@node-i3x/rest-server\u003cbr/\u003eFastify routes — i3X Beta API\"]\n        end\n\n        subgraph CORE[\"DOMAIN CORE — ZERO DEPENDENCIES\"]\n            Core[\"@node-i3x/core\u003cbr/\u003eDomain Models · Services · Port Interfaces\u003cbr/\u003eStable IDs · Subscriptions · History\"]\n        end\n\n        subgraph OUTBOUND[\"OUTBOUND ADAPTERS\"]\n            OPC[\"@node-i3x/opcua-connector\u003cbr/\u003enode-opcua client (remote)\"]\n            Pseudo[\"@node-i3x/pseudo-session-connector\u003cbr/\u003ePseudoSession (embedded)\"]\n        end\n    end\n\n    OPCUA([\"⚙ OPC UA Server\"])\n\n    Client \u003c--\u003e|\"HTTP / JSON\"| REST\n    REST --\u003e|\"uses ports\"| Core\n    Core --\u003e|\"IDataSourcePort\"| OPC\n    Core --\u003e|\"IDataSourcePort\"| Pseudo\n    OPC \u003c--\u003e|\"OPC UA TCP\"| OPCUA\n    Pseudo \u003c--\u003e|\"In-process\"| OPCUA\n```\n\n\u003c/details\u003e\n\n### Hexagonal Layers\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"docs/architecture.svg\" alt=\"Hexagonal architecture layers\" width=\"720\" /\u003e\n\u003c/p\u003e\n\n---\n\n## Packages\n\n| Package | Description | Status |\n|---------|-------------|--------|\n| [`@node-i3x/core`](./packages/core) | Domain core: models, ports (`IDataSourcePort`, `ILogger`), services (`ModelService`, `ValueService`, `HistoryService`, `SubscriptionService`), stable ID mapper | ✅ Stable |\n| [`@node-i3x/opcua-connector`](./packages/opcua-connector) | OPC UA client adapter — implements `IDataSourcePort` using `node-opcua` (remote TCP/binary transport) | ✅ Stable |\n| [`@node-i3x/pseudo-session-connector`](./packages/pseudo-session-connector) | PseudoSession adapter — implements `IDataSourcePort` using `node-opcua` PseudoSession (embedded in-process, zero network) | ✅ Stable |\n| [`@node-i3x/rest-server`](./packages/rest-server) | Fastify REST routes implementing the i3X Beta API surface | ✅ Stable |\n| [`@node-i3x/app`](./packages/app) | Composition root — wires all packages together, entry point | ✅ Stable |\n| [`@node-i3x/demo-embedded`](./packages/demo-embedded) | Embedded demo with live dashboard — OPC UA server + i3X API wired via PseudoSession | 🧪 Demo |\n\n---\n\n## Quick Start\n\n```bash\n# Clone the repository\ngit clone https://github.com/node-opcua/node-i3x.git\ncd node-i3x\n\n# Install dependencies\nnpm install\n\n# Configure environment\ncp .env.example .env\n# Edit .env — set NODE_I3X_OPCUA_ENDPOINT to your OPC UA server\n\n# Start in development mode (remote OPC UA)\nnpm run dev\n\n# Or run the embedded demo (no external OPC UA server needed)\nnpm run demo -w packages/demo-embedded\n```\n\nThe server starts on `http://127.0.0.1:8000` by default. Verify with:\n\n```bash\ncurl http://127.0.0.1:8000/health\n# → { \"status\": \"ok\" }\n```\n\n---\n\n## Configuration\n\nAll configuration is via environment variables (or `.env` file):\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `NODE_I3X_OPCUA_ENDPOINT` | `opc.tcp://localhost:4840` | OPC UA server endpoint URL |\n| `NODE_I3X_OPCUA_SECURITY_MODE` | `None` | Security mode (`None`, `Sign`, `SignAndEncrypt`) |\n| `NODE_I3X_OPCUA_OPTIMIZED_CLIENT` | `auto` | `auto` = detect @sterfive module, `disabled` = skip |\n| `NODE_I3X_PUBLISH_INTERVAL_MS` | `1000` | OPC UA publishing interval (milliseconds) |\n| `NODE_I3X_SAMPLING_INTERVAL_MS` | `250` | OPC UA sampling interval (milliseconds) |\n| `NODE_I3X_PRELOAD` | `true` | Preload the OPC UA model on startup |\n| `NODE_I3X_PRELOAD_STRICT` | `false` | Exit if model preload fails |\n| `NODE_I3X_PORT` | `8000` | HTTP server port |\n| `NODE_I3X_HOST` | `127.0.0.1` | HTTP server bind address |\n| `NODE_I3X_LOG_LEVEL` | `info` | Log level (`debug`, `info`, `warn`, `error`) |\n\n---\n\n## Development\n\n```bash\n# Run all tests (vitest)\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# TypeScript type checking\nnpm run typecheck\n\n# Lint + format check (Biome)\nnpm run lint\n\n# Auto-fix lint and format issues\nnpm run lint:fix\n\n# Build all packages (tsup — minified ESM + .d.ts)\nnpm run build\n```\n\n### Tech Stack\n\n| Tool | Purpose |\n|------|---------|\n| [TypeScript](https://www.typescriptlang.org/) | Language (ESM-only) |\n| [tsup](https://tsup.egoist.dev/) | Build (esbuild, minified ESM + `.d.ts`) |\n| [Vitest](https://vitest.dev/) | Testing |\n| [Biome](https://biomejs.dev/) | Lint + Format |\n| [Fastify](https://fastify.dev/) | HTTP framework |\n| [node-opcua](https://node-opcua.github.io/) | OPC UA client SDK |\n\n---\n\n## Key Concepts\n\n### 🔑 Stable Element IDs\n\nOPC UA `NodeId` values are volatile — namespace indices can shuffle across server restarts. node-i3x generates **stable, deterministic element IDs** by:\n\n1. Computing the full **namespace-URI browse path** for each node (e.g., `nsu=http://example.org;s=Sensor1/Temperature`)\n2. Hashing the path with a deterministic hash function\n3. Producing a fixed-length hex ID that remains constant regardless of namespace index changes\n\nThis ensures that REST clients can bookmark and cache element IDs across server lifecycles.\n\n### 🔷 Hexagonal Architecture (Ports \u0026 Adapters)\n\nThe codebase follows a strict **hexagonal / ports \u0026 adapters** pattern:\n\n- **`@node-i3x/core`** defines domain models and **port interfaces** (`IDataSourcePort`, `ILogger`) with zero external dependencies\n- **Outbound adapters** (`opcua-connector`, `pseudo-session-connector`) implement `IDataSourcePort`\n- **Inbound adapter** (`rest-server`) translates HTTP requests into domain service calls\n- **`@node-i3x/app`** is the composition root that wires adapters to ports\n\n### 🔌 Two Connector Modes\n\n| Mode | Package | Transport | Use Case |\n|------|---------|-----------|----------|\n| **Remote** | `@node-i3x/opcua-connector` | OPC UA TCP/Binary | Connect to any standard OPC UA server on the network |\n| **Embedded** | `@node-i3x/pseudo-session-connector` | In-process (zero network) | Run an OPC UA server and the i3X API in the same process — ideal for demos, testing, and edge deployments |\n\n---\n\n## API Endpoints\n\nThe i3X Beta REST API surface:\n\n### System\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/health` | Health check |\n| `GET` | `/ready` | Readiness check (data source connected?) |\n| `GET` | `/v1/info` | Server info, spec version, capabilities |\n\n### Namespaces\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/v1/namespaces` | List all OPC UA namespaces |\n\n### Objects\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/v1/objects` | List all objects (optional: `?root=true`, `?typeElementId=...`) |\n| `POST` | `/v1/objects/list` | Bulk-fetch objects by element IDs |\n| `POST` | `/v1/objects/value` | Bulk-read current values |\n| `POST` | `/v1/objects/related` | Bulk-fetch related objects (children / parent) |\n| `POST` | `/v1/objects/history` | Bulk-read historical values |\n| `PUT` | `/v1/objects/:elementId/value` | Write a value to a single element |\n\n### Object Types\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/v1/objecttypes` | List all object types (optional: `?namespaceUri=...`) |\n\n### Relationship Types\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `GET` | `/v1/relationshiptypes` | List relationship types *(stub — 501)* |\n\n### Subscriptions\n\n| Method | Endpoint | Description |\n|--------|----------|-------------|\n| `POST` | `/v1/subscriptions` | Create a new subscription |\n| `POST` | `/v1/subscriptions/register` | Register element IDs for monitoring |\n| `POST` | `/v1/subscriptions/unregister` | Unregister element IDs |\n| `POST` | `/v1/subscriptions/sync` | Poll for value updates (long-poll) |\n| `POST` | `/v1/subscriptions/stream` | Stream value updates via SSE |\n| `POST` | `/v1/subscriptions/list` | List subscription details |\n| `POST` | `/v1/subscriptions/delete` | Delete subscriptions |\n\n\u003e 📘 Full OpenAPI specification: [`openapi.json`](./openapi.json)\n\n---\n\n## Docker\n\n```bash\ndocker build -t node-i3x .\ndocker run -p 8000:8000 \\\n  -e NODE_I3X_OPCUA_ENDPOINT=opc.tcp://host.docker.internal:4840 \\\n  node-i3x\n```\n\n---\n\n## 🚀 @sterfive/opcua-optimized-client\n\nFor production deployments, install the optional **[@sterfive/opcua-optimized-client](https://support.sterfive.com)** module for up to **200% performance improvement**:\n\n- Intelligent transaction batching\n- Automatic server-limit handling\n- Advanced auto-healing connection logic\n\nThe module is detected automatically at startup — no code changes needed. It is listed as an `optionalDependency` in `@node-i3x/opcua-connector`.\n\n\u003e Contact [Sterfive Support](https://support.sterfive.com) for access.\n\n---\n\n## i3X Specification\n\n- **Official site**: [https://i3x.dev](https://i3x.dev)\n- **GitHub**: [https://github.com/cesmii/i3X](https://github.com/cesmii/i3X)\n- **CESMII**: [https://cesmii.org](https://cesmii.org)\n\n---\n\n## License\n\nThis project is dual-licensed:\n\n| License | Use Case |\n|---------|----------|\n| **[AGPL-3.0-or-later](https://www.gnu.org/licenses/agpl-3.0.html)** | Open-source use — you must share your source code if you deploy this as a network service |\n| **[Commercial](https://sterfive.com)** | Proprietary / closed-source use — no copyleft obligations |\n\n\u003e **The AGPL-3.0 restrictions can be lifted by acquiring a commercial\n\u003e license at [sterfive.com](https://sterfive.com).**\n\u003e\n\u003e Contact [contact@sterfive.com](mailto:contact@sterfive.com) for\n\u003e pricing and terms.\n\nSee [LICENSE](./LICENSE) for full details.\n\n---\n\n## Credits\n\nBuilt by [Sterfive](https://sterfive.com) — Industrial-grade OPC UA solutions for the modern web.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://sterfive.com\"\u003e\n    \u003cstrong\u003esterfive.com\u003c/strong\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-opcua%2Fnode-i3x","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnode-opcua%2Fnode-i3x","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnode-opcua%2Fnode-i3x/lists"}