import { connect as connectNats, jwtAuthenticator, type NatsConnection } from 'nats'; import { MatrixActor, MatrixRuntime, NatsTransport, TopicRouter, exchangeHiveCastActorCredential, } from '@open-matrix/sdk'; class FreshServerEchoActor extends MatrixActor { static accepts = { echo: {}, getStatus: {}, }; onEcho(payload: { message?: string }) { return { ok: true, message: payload.message ?? null, actor: 'FreshServerEchoActor', }; } onGetStatus() { return { ok: true, actor: 'FreshServerEchoActor', mode: 'server', }; } } function env(name: string): string | undefined { const value = process.env[name]; return typeof value === 'string' && value.trim() ? value.trim() : undefined; } function requiredEnv(name: string): string { const value = env(name); if (!value) throw new Error(`${name}_REQUIRED`); return value; } function connectWithJwt(input: { readonly natsUrl: string; readonly root: string; readonly jwt: string; readonly seed: string; }): Promise { const encoder = new TextEncoder(); return connectNats({ servers: [input.natsUrl], name: `matrix-sdk-fresh-server-${input.root}-${process.pid}`, timeout: 5000, authenticator: jwtAuthenticator( () => input.jwt, () => encoder.encode(input.seed), ), }); } async function request( transport: NatsTransport, mount: string, op: string, payload: unknown, ): Promise { const correlationId = `fresh-server-${Date.now()}-${Math.random().toString(16).slice(2)}`; const replyTo = `$replies.${correlationId}`; let unsubscribe = () => {}; const response = new Promise((resolve, reject) => { const timeout = setTimeout(() => { unsubscribe(); reject(new Error(`REQUEST_TIMEOUT: ${mount}.${op}`)); }, 5000); unsubscribe = transport.subscribe(replyTo, (value) => { clearTimeout(timeout); unsubscribe(); resolve(value); }); }); transport.publish(TopicRouter.inbox(mount), { op, payload, replyTo, correlationId, }); return response; } async function main(): Promise { const check = process.argv.includes('--check'); const cloud = requiredEnv('MATRIX_CLOUD'); const apiKey = requiredEnv('MATRIX_API_KEY'); const space = requiredEnv('MATRIX_SPACE'); const mount = env('MATRIX_MOUNT') ?? 'fresh.server.echo'; const exchanged = await exchangeHiveCastActorCredential({ cloud, apiKey, space, }, { mount, actorId: 'FreshServerEchoActor', packageId: 'matrix-sdk-example-fresh-server-actor', runtimeId: `fresh-server-${process.pid}`, accepts: FreshServerEchoActor.accepts, ttlSeconds: 300, }); if (!exchanged.transport.natsUrl) { throw new Error('HiveCast actor credential response did not include transport.natsUrl'); } const connection = await connectWithJwt({ natsUrl: exchanged.transport.natsUrl, root: exchanged.root, jwt: exchanged.credentials.jwt, seed: exchanged.credentials.seed, }); const transport = new NatsTransport(connection, { root: exchanged.root }); const runtime = new MatrixRuntime({ transport, logging: false }); try { await runtime.create(FreshServerEchoActor, mount); await connection.flush(); const result = check ? await request(transport, mount, 'echo', { message: 'hello-from-fresh-server-demo' }) : undefined; console.log(JSON.stringify({ ok: true, demo: 'fresh-server-actor', cloud, space, root: exchanged.root, mount, natsUrl: exchanged.transport.natsUrl, credentialPipeline: exchanged.credentialPipeline, ...(result ? { check: result } : {}), }, null, 2)); if (!check) { process.once('SIGINT', () => { void runtime.shutdown().finally(() => process.exit(0)); }); process.once('SIGTERM', () => { void runtime.shutdown().finally(() => process.exit(0)); }); await new Promise(() => undefined); } } finally { if (check) { await runtime.shutdown(); if (!connection.isClosed()) await connection.close(); } } } main().catch((error) => { console.error(error instanceof Error ? error.stack : error); process.exit(1); });