All files / rpc-server/src/__demos__/json-crdt-server/__tests__ setup.ts

100% Statements 51/51
100% Branches 9/9
100% Functions 8/8
100% Lines 44/44

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 694x 4x 4x 4x 4x 4x 4x 4x 4x 4x     4x 237545x 198728x 159599x 79786x 158906x 79786x   79813x     4x 69x 69x 69x 69x 1426x 69x 69x 69x   69x     4x 19x 19x     4x 19x       19x 19x     4x       19x 19x 19x 19x 19x 19x 19x 19x              
import {mkdtempSync, rmSync} from 'fs';
import {tmpdir} from 'os';
import {join} from 'path';
import {MemoryLevel} from 'memory-level';
import {CalleeCaller} from '@jsonjoy.com/rpc-calls/lib/caller/CalleeCaller';
import {createCaller} from '../routes';
import {LevelStore} from '../services/blocks/store/level/LevelStore';
import {Services} from '../services/Services';
import {ClassicLevel} from 'classic-level';
import {MemoryStore} from '../services/blocks/store/MemoryStore';
import type {Store} from '../services/blocks/store/types';
 
const deepClone = (val: unknown): unknown => {
  if (val instanceof Uint8Array) return new Uint8Array(val);
  if (Array.isArray(val)) return val.map(deepClone);
  if (val !== null && typeof val === 'object') {
    const out: Record<string, unknown> = {};
    for (const k of Object.keys(val)) out[k] = deepClone((val as Record<string, unknown>)[k]);
    return out;
  }
  return val;
};
 
export const setup = async (store: Store = new MemoryStore(), close?: () => Promise<void>) => {
  const services = new Services({store});
  const {caller} = createCaller(services);
  const client = new CalleeCaller(caller.rpc as any, {} as any);
  const call = async (method: string, req?: unknown): Promise<any> =>
    deepClone(await client.call(method as any, req as any));
  const call$ = client.call$.bind(client);
  const stop = async (): Promise<void> => {
    await close?.();
  };
  return {call, call$, stop};
};
 
export const setupMemory = async () => {
  const store = new MemoryStore();
  return setup(store);
};
 
export const setupLevelMemory = async () => {
  const kv = new MemoryLevel<string, Uint8Array>({
    keyEncoding: 'utf8',
    valueEncoding: 'view',
  });
  const store = new LevelStore(<any>kv);
  return setup(store);
};
 
export const setupLevelClassic = async () => {
  // Use a unique temp directory per setup so each test is fully isolated: no
  // shared state or leftover data across tests/runs, and no `LOCK already held`
  // contention if one test fails before it can close its database.
  const dir = mkdtempSync(join(tmpdir(), 'json-crdt-server-level-'));
  const kv = new ClassicLevel<string, Uint8Array>(dir, {valueEncoding: 'view'});
  await kv.open();
  const store = new LevelStore(<any>kv);
  return setup(store, async () => {
    await kv.close();
    try {
      rmSync(dir, {recursive: true, force: true});
    } catch {}
  });
};
 
export type JsonCrdtTestSetup = typeof setup;
export type ApiTestSetup = typeof setupMemory;