@nanolink/operational-model
v0.1.47
Published
TypeScript utility package.
Readme
operational-model
TypeScript package providing read-only repository interfaces and implementations for the tracker operational domain (state links, trips, RSSI, GPS, etc.).
Data is retrieved via NATS aegateway or Scylla/Cassandra — there is no direct Aerospike dependency.
Install
npm install @nanolink/operational-modelTransports
| Transport | Supported repositories |
|---|---|
| Aegateway (NATS) | stateLinks, stateTrips, stateContained, stateRefLinks |
| Scylla (Cassandra) | closedLinks, contained, gps, rssi, deltaRssi, trips |
Usage
Aegateway (NATS)
import { connect } from 'nats';
import { Aegateway, Models } from '@nanolink/operational-model';
const nc = await connect({ servers: 'nats://localhost:4222' });
const client = new Aegateway.AegatewayClient(nc, { prefix: 'aegw', timeoutMs: 30_000 });
const repos = Aegateway.createAegatewayRepositories({ client, namespace: 'oper' });
// Stream state links for a PID
for await (const link of repos.stateLinks.streamAll('pid-123')) {
console.log(link);
}
// Query state trips by receiver
const trips: Models.StateTripWithId[] = await repos.stateTrips.queryByReceiver('receiver-1');
await nc.drain();Scylla / Cassandra
import { ScyllaConnectionFactory, Scylla } from '@nanolink/operational-model';
const factory = new ScyllaConnectionFactory();
factory.register('default', {
contactPoints: ['127.0.0.1:9042'],
localDataCenter: 'datacenter1',
keyspace: 'oper',
});
const client = await factory.get('default');
const repos = Scylla.createScyllaRepositories({ client, keyspace: 'oper' });
// GPS positions for a device
const positions = await repos.gps.queryByKey('device-123');
// Stream RSSI history without buffering
for await (const r of repos.rssi.streamAll()) {
console.log(r);
}
await factory.closeAll();NATS subscriber utility
import { connect } from 'nats';
import { NatsSubscriber } from '@nanolink/operational-model';
const nc = await connect({ servers: 'nats://localhost:4222' });
const sub = new NatsSubscriber<{ foo: string }>(nc, 'events');
for await (const { topic, data } of sub.subscribeGenerator()) {
console.log(topic, data);
}Exports
| Export | Contents |
|---|---|
| Models | All domain types (StateLinkWithId, GPSPosition, etc.) |
| Repositories | Repository interfaces + RepositoryBundle type |
| Aegateway | AegatewayClient, createAegatewayRepositories, filter helpers |
| Scylla | createScyllaRepositories, ScyllaRepositoryBundle |
| ScyllaConnectionFactory | Scylla connection pool |
| NatsSubscriber | Generic msgpack-decoded NATS subscriber |
Scripts
npm run build # compile TypeScript
npm run lint # ESLint
npm run format # PrettierNotes
- All repository implementations are read-only — no writes or event emission.
- Aegateway automatically chunks large filter sets (≤ 100 filters per request) to avoid overwhelming the server.
- See
spec.mdfor the full data model and bin layout.
