import { strict as assert } from 'node:assert'; import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { describe, it } from 'node:test'; import { saveHiveCastHostLink } from '../../src/utils/hivecast-link-store.js'; describe('HiveCast link store', () => { it('keeps a normal linked Device on local NATS when the saved local-owner snapshot is missing', () => { const root = mkdtempSync(join(tmpdir(), 'mx-hivecast-link-store-')); try { const matrixHome = join(root, '.matrix'); const hostConfigPath = join(matrixHome, 'host.json'); mkdirSync(matrixHome, { recursive: true }); writeFileSync(hostConfigPath, `${JSON.stringify({ kind: 'MatrixHostConfig', version: 1, home: matrixHome, transport: { root: 'richard-santomauro-nimbletec-com', authorityRoot: 'richard-santomauro-nimbletec-com', addressRoot: 'richard-santomauro-nimbletec-com', nats: { mode: 'external', url: 'nats://local.hivecast.ai:4222', wsUrl: 'wss://local.hivecast.ai/nats-ws', credentialsRef: 'file:/var/lib/hivecast/credentials/hivecast-nats.json', }, }, }, null, 2)}\n`); saveHiveCastHostLink({ cwd: root, matrixHome, cloudUrl: 'https://local.hivecast.ai', authorityRoot: 'richard-santomauro-nimbletec-com', deviceRegistryRoot: 'richard-santomauro-nimbletec-com', hostLinkId: 'hostlink_test', hostId: 'install_test', principalId: 'principal_test', hostName: 'test-device', deviceSlug: 'test-device', routeKey: 'richard-santomauro-nimbletec-com', publicNamespace: 'richard-santomauro-nimbletec-com', spaceId: 'space_test', authorityCoordinator: false, nats: { url: 'nats://local.hivecast.ai:4222', wsUrl: 'wss://local.hivecast.ai/nats-ws', }, natsCredentials: { jwt: 'jwt', seed: 'seed', }, }); const hostConfig = JSON.parse(readFileSync(hostConfigPath, 'utf8')) as { readonly transport?: { readonly root?: string; readonly authorityRoot?: string; readonly nats?: { readonly url?: string; readonly wsUrl?: string; readonly credentialsRef?: string; readonly binaryPath?: string; }; }; }; assert.equal(hostConfig.transport?.root, 'richard-santomauro-nimbletec-com'); assert.equal(hostConfig.transport?.authorityRoot, 'richard-santomauro-nimbletec-com'); assert.equal(hostConfig.transport?.nats?.url, 'nats://127.0.0.1:4222'); assert.equal(hostConfig.transport?.nats?.wsUrl, 'ws://127.0.0.1:4223'); assert.equal(hostConfig.transport?.nats?.credentialsRef, undefined); assert.equal(hostConfig.transport?.nats?.binaryPath, undefined); assert.equal(Object.prototype.hasOwnProperty.call(hostConfig, 'natsTopology'), false); assert.equal(existsSync(join(matrixHome, 'credentials', 'hivecast-nats.creds')), false); } finally { rmSync(root, { recursive: true, force: true }); } }); it('configures linked Device leaf-node transport when the platform exchange advertises it', () => { const root = mkdtempSync(join(tmpdir(), 'mx-hivecast-link-store-leaf-')); try { const matrixHome = join(root, '.matrix'); const hostConfigPath = join(matrixHome, 'host.json'); mkdirSync(matrixHome, { recursive: true }); writeFileSync(hostConfigPath, `${JSON.stringify({ kind: 'MatrixHostConfig', version: 1, home: matrixHome, transport: { root: 'local-install-test', authorityRoot: 'local-install-test', addressRoot: 'local-install-test', nats: { mode: 'external', url: 'nats://127.0.0.1:4222', wsUrl: 'ws://127.0.0.1:4223', }, }, }, null, 2)}\n`); saveHiveCastHostLink({ cwd: root, matrixHome, cloudUrl: 'https://local.hivecast.ai', authorityRoot: 'richard-santomauro-nimbletec-com', deviceRegistryRoot: 'richard-santomauro-nimbletec-com', hostLinkId: 'hostlink_test', hostId: 'install_test', principalId: 'principal_test', hostName: 'test-device', deviceSlug: 'test-device', routeKey: 'richard-santomauro-nimbletec-com', publicNamespace: 'richard-santomauro-nimbletec-com', spaceId: 'space_test', authorityCoordinator: false, nats: { url: 'nats://local.hivecast.ai:4222', wsUrl: 'wss://local.hivecast.ai/nats-ws', leafnodeUrl: 'nats://local.hivecast.ai:7422', }, natsCredentials: { jwt: 'jwt', seed: 'seed', }, }); const hostConfig = JSON.parse(readFileSync(hostConfigPath, 'utf8')) as { readonly transport?: { readonly root?: string; readonly authorityRoot?: string; readonly nats?: { readonly url?: string; readonly wsUrl?: string; readonly credentialsRef?: string; readonly binaryPath?: string; }; }; readonly natsTopology?: { readonly mode?: string; readonly clientUrl?: string; readonly wsUrl?: string; readonly leafnodes?: readonly { readonly url?: string; readonly credentialsRef?: string; }[]; }; }; const link = JSON.parse(readFileSync(join(matrixHome, 'credentials', 'hivecast-link.json'), 'utf8')) as { readonly credentials?: { readonly natsLeafnodeCredentialRef?: string; }; }; const leafCredentials = readFileSync(join(matrixHome, 'credentials', 'hivecast-nats.creds'), 'utf8'); assert.equal(hostConfig.transport?.root, 'richard-santomauro-nimbletec-com'); assert.equal(hostConfig.transport?.authorityRoot, 'richard-santomauro-nimbletec-com'); assert.equal(hostConfig.transport?.nats?.url, 'nats://127.0.0.1:4222'); assert.equal(hostConfig.transport?.nats?.wsUrl, 'ws://127.0.0.1:4223'); assert.equal(hostConfig.transport?.nats?.credentialsRef, undefined); assert.equal(hostConfig.transport?.nats?.binaryPath, undefined); assert.equal(hostConfig.natsTopology?.mode, 'leafnode'); assert.equal(hostConfig.natsTopology?.clientUrl, 'nats://127.0.0.1:4222'); assert.equal(hostConfig.natsTopology?.wsUrl, 'ws://127.0.0.1:4223'); assert.equal(hostConfig.natsTopology?.leafnodes?.[0]?.url, 'nats://local.hivecast.ai:7422'); assert.equal(hostConfig.natsTopology?.leafnodes?.[0]?.credentialsRef, 'file:credentials/hivecast-nats.creds'); assert.equal(link.credentials?.natsLeafnodeCredentialRef, 'file:credentials/hivecast-nats.creds'); assert.match(leafCredentials, /-----BEGIN NATS USER JWT-----\njwt\n------END NATS USER JWT------/); assert.match(leafCredentials, /-----BEGIN USER NKEY SEED-----\nseed\n------END USER NKEY SEED------/); } finally { rmSync(root, { recursive: true, force: true }); } }); });