UNPKG

@rivetkit/framework-base

Version:

Base framework utilities for RivetKit client integrations

235 lines (233 loc) 6.85 kB
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } }// src/mod.ts var _store = require('@tanstack/store'); var _fastdeepequal = require('fast-deep-equal'); var _fastdeepequal2 = _interopRequireDefault(_fastdeepequal); require('rivetkit/client'); function createRivetKit(client, createOpts = {}) { const store = new (0, _store.Store)({ actors: {} }); const cache = /* @__PURE__ */ new Map(); return { getOrCreateActor: (actorOpts) => getOrCreateActor(client, createOpts, store, cache, actorOpts), store }; } function updateActor(store, key, updates) { store.setState((prev) => ({ ...prev, actors: { ...prev.actors, [key]: { ...prev.actors[key], ...updates } } })); } function getOrCreateActor(client, createOpts, store, cache, actorOpts) { const hash = createOpts.hashFunction || defaultHashFunction; const normalizedOpts = { ...actorOpts, enabled: _nullishCoalesce(actorOpts.enabled, () => ( true)) }; const key = hash(normalizedOpts); const existing = store.state.actors[key]; if (!existing) { store.setState((prev) => ({ ...prev, actors: { ...prev.actors, [key]: { hash: key, connStatus: "idle", connection: null, handle: null, error: null, opts: normalizedOpts } } })); } else if (!optsEqual(existing.opts, normalizedOpts)) { queueMicrotask(() => { updateActor(store, key, { opts: normalizedOpts }); }); } const cached = cache.get(key); if (cached) { return { ...cached, state: cached.state }; } const derived = new (0, _store.Derived)({ fn: ({ currDepVals: [store2] }) => { const actor = store2.actors[key]; return { ...actor, /** @deprecated Use `connStatus === "connected"` instead */ isConnected: actor.connStatus === "connected" }; }, deps: [store] }); const effect = new (0, _store.Effect)({ fn: () => { const actor = store.state.actors[key]; if (!actor) { throw new Error( `Actor with key "${key}" not found in store. This indicates a bug in cleanup logic.` ); } if (!actor.opts.enabled && actor.connection) { actor.connection.dispose(); updateActor(store, key, { connection: null, handle: null, connStatus: "idle" }); return; } if (actor.connStatus === "idle" && actor.opts.enabled) { queueMicrotask(() => { const currentActor = store.state.actors[key]; if (currentActor && currentActor.connStatus === "idle" && currentActor.opts.enabled) { create(client, store, key); } }); } }, deps: [derived] }); let unsubscribeDerived = null; let unsubscribeEffect = null; const mount = () => { const cached2 = cache.get(key); if (!cached2) { throw new Error( `Actor with key "${key}" not found in cache. This indicates a bug in cleanup logic.` ); } if (cached2.cleanupTimeout !== null) { clearTimeout(cached2.cleanupTimeout); cached2.cleanupTimeout = null; } cached2.refCount++; if (cached2.refCount === 1) { unsubscribeDerived = derived.mount(); unsubscribeEffect = effect.mount(); const actor = store.state.actors[key]; if (actor && actor.opts.enabled && actor.connStatus === "idle") { create(client, store, key); } } return () => { cached2.refCount--; if (cached2.refCount === 0) { cached2.cleanupTimeout = setTimeout(() => { cached2.cleanupTimeout = null; if (cached2.refCount > 0) return; unsubscribeDerived == null ? void 0 : unsubscribeDerived(); unsubscribeEffect == null ? void 0 : unsubscribeEffect(); unsubscribeDerived = null; unsubscribeEffect = null; const actor = store.state.actors[key]; if (actor == null ? void 0 : actor.connection) { actor.connection.dispose(); } store.setState((prev) => { const { [key]: _, ...rest } = prev.actors; return { ...prev, actors: rest }; }); cache.delete(key); }, 0); } }; }; cache.set(key, { state: derived, key, mount, create: create.bind(void 0, client, store, key), refCount: 0, cleanupTimeout: null }); return { mount, state: derived, key }; } function create(client, store, key) { const actor = store.state.actors[key]; if (!actor) { throw new Error( `Actor with key "${key}" not found in store. This indicates a bug in cleanup logic.` ); } updateActor(store, key, { connStatus: "connecting", error: null }); try { const handle = client.getOrCreate( actor.opts.name, actor.opts.key, { params: actor.opts.params, createInRegion: actor.opts.createInRegion, createWithInput: actor.opts.createWithInput } ); const connection = handle.connect(); updateActor(store, key, { handle, connection }); connection.onStatusChange((status) => { store.setState((prev) => { var _a; const isActiveConnection = ((_a = prev.actors[key]) == null ? void 0 : _a.connection) === connection; if (!isActiveConnection) return prev; return { ...prev, actors: { ...prev.actors, [key]: { ...prev.actors[key], connStatus: status, // Only clear error when successfully connected ...status === "connected" ? { error: null } : {} } } }; }); }); connection.onError((error) => { store.setState((prev) => { var _a; if (((_a = prev.actors[key]) == null ? void 0 : _a.connection) !== connection) return prev; return { ...prev, actors: { ...prev.actors, [key]: { ...prev.actors[key], error } } }; }); }); } catch (error) { console.error("Failed to create actor connection", error); updateActor(store, key, { connStatus: "disconnected", error }); } } function defaultHashFunction({ name, key, params }) { return JSON.stringify({ name, key, params }); } function optsEqual(a, b) { return _fastdeepequal2.default.call(void 0, a, b); } exports.createRivetKit = createRivetKit; //# sourceMappingURL=mod.js.map