@fatagnus/dink-sdk
v2.9.1
Published
TypeScript SDK for Dink edge mesh platform
Maintainers
Readme
@fatagnus/dink-sdk
TypeScript SDK for the Dink edge mesh platform.
This SDK is for Lite Edge - edges that require constant connectivity. For offline-first applications, use @fatagnus/dink-sync instead.
| Edge Type | SDK | Use Case |
|-----------|-----|----------|
| Lite Edge | ✅ This SDK | Always-connected IoT, RPC services |
| Offline-First Edge | @fatagnus/dink-sync | Offline data with auto-sync |
| Full Edge | Not yet available | Local NATS services (planned) |
Installation
npm install @fatagnus/dink-sdkQuick Start
Edge Client
Connect an edge device to the Dink platform:
import { EdgeClient } from '@fatagnus/dink-sdk';
// With embedded URL keys (recommended), no serverUrl needed!
const edge = new EdgeClient({
apiKey: process.env.DINK_API_KEY!, // Contains embedded URL + credentials
});
// Edge ID and App ID are extracted from the API key
console.log(`Edge ID: ${edge.getEdgeId()}`); // e.g., "my-edge-device"
console.log(`App ID: ${edge.getAppId()}`); // e.g., "my-app"
await edge.connect();
// Expose a service
await edge.exposeService({
name: 'sensor',
version: '1.0.0',
definition: {
name: 'sensor',
version: '1.0.0',
handleRequest: async (method, data) => {
if (method === 'read') {
return { temperature: 22.5 };
}
throw new Error(`Unknown method: ${method}`);
},
},
});Center Client
Connect from a center/cloud service to discover and call edge services:
import { CenterClient } from '@fatagnus/dink-sdk';
const center = new CenterClient({
serverUrl: 'nats://localhost:4222',
apiKey: process.env.DINK_API_KEY,
});
await center.connect();
// Discover edges
const edges = await center.discoverEdges();
// Call a service on an edge (edge ID comes from discovery)
const result = await center.call({
edgeId: edges[0].id, // e.g., "my-edge-device"
service: 'sensor',
method: 'read',
data: {},
});
console.log(result); // { temperature: 22.5 }API Key Formats
Dink supports two API key formats for edge authentication:
Embedded URL Format (Recommended)
The new format embeds the dinkd server URL directly in the key, enabling easier onboarding where edge agents only need a single API key to connect:
import { EdgeClient } from '@fatagnus/dink-sdk';
// No serverUrl needed - it's embedded in the key!
const edge = new EdgeClient({
apiKey: process.env.DINK_API_KEY!,
});The embedded key format is a base64-encoded JSON object:
base64({"url": "nats://dinkd.example.com:4222", "secret": "dk_..."})Keys created via the Convex SDK (createEdgeKey) or the test utilities automatically use this format.
Legacy Format
The legacy format is a plain string without embedded URL:
dk_<env>_ed_<appID>_<edgeID>_<random>For legacy keys, you must provide serverUrl explicitly:
const edge = new EdgeClient({
serverUrl: 'nats://localhost:4222',
apiKey: 'dk_prod_ed_myapp_myedge_abc123',
});Parsing Keys
Use parseEdgeKey to inspect a key and extract its components:
import { parseEdgeKey } from '@fatagnus/dink-sdk';
// Parse an embedded URL key
const parsed = parseEdgeKey(embeddedKey);
console.log(parsed.serverUrl); // 'nats://dinkd.example.com:4222'
console.log(parsed.secret); // 'dk_prod_ed_myapp_myedge_abc123'
console.log(parsed.appId); // 'myapp'
console.log(parsed.edgeId); // 'myedge'
// Parse a legacy key
const legacy = parseEdgeKey('dk_prod_ed_myapp_myedge_abc123');
console.log(legacy.serverUrl); // undefined (no embedded URL)
console.log(legacy.secret); // 'dk_prod_ed_myapp_myedge_abc123'URL Override
Even with embedded URL keys, you can override the URL in the config:
// Override the embedded URL (e.g., for local development)
const edge = new EdgeClient({
apiKey: productionKey,
serverUrl: 'nats://localhost:4222', // Takes precedence over embedded URL
});Handling Kick Commands
Edges can be forcibly disconnected by the server (e.g., for key revocation, maintenance, or security). Register a callback to handle kick events:
import { EdgeClient } from '@fatagnus/dink-sdk';
const edge = new EdgeClient({ apiKey: process.env.DINK_API_KEY! });
await edge.connect();
// Register kick handler (optional but recommended)
const unsubscribe = edge.onKick((reason: string) => {
console.log(`Received kick command: ${reason}`);
// Clean up resources, save state, etc.
// The edge will automatically disconnect after this callback
});
// Later, if you want to stop listening:
unsubscribe();When kicked, the edge client will:
- Call your
onKickcallback (if registered) - Gracefully disconnect from the server
- Clean up all service subscriptions
Note: To kick an edge from your Convex backend, use kickEdge from @fatagnus/dink-convex.
Subpath Exports
You can also import specific clients directly:
import { EdgeClient } from '@fatagnus/dink-sdk/edge';
import { CenterClient } from '@fatagnus/dink-sdk/center';Naming Rules
App IDs, edge IDs, app names, and service names must follow these rules to ensure compatibility with NATS subjects:
Allowed characters:
- Alphanumeric:
a-z,A-Z,0-9 - Hyphens:
- - Colons:
:
Not allowed:
- Underscore
_(used as key delimiter) - Dot
.(NATS hierarchy separator) - Asterisk
*(NATS wildcard) - Greater than
>(NATS tail wildcard) - Dollar sign
$(NATS system subjects) - Spaces and whitespace
Examples:
// ✓ Valid names
'my-app'
'sensor-42'
'namespace:service'
'MyApp123'
// ✗ Invalid names
'my_app' // underscore not allowed
'my.app' // dot not allowed
'my app' // space not allowed
'sensor*' // asterisk not allowedRequirements
- Node.js >= 18.0.0
- A running dinkd server
Documentation
For full documentation, visit https://github.com/ozanturksever/dink
License
MIT
