chat / client / test / helpers / load.mjs
  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
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
 * Module loader for the black-box tests, in the shape rooms-kit established.
 *
 * Default: the ClojureScript build (`test-dist/testlib.js`, produced by
 * `shadow-cljs release testlib`) — the tests run against compiled output, never
 * against src/.
 *
 * With `SUETA_TS=1` it instead loads the TypeScript implementation through
 * harness/ts.mjs. That mode is the suite's own regression harness: a test that
 * passes on the CLJS build but was never checked against the TS one cannot tell
 * "the port is right" from "the assertion is wrong". Every assertion in
 * test/*.test.mjs was run green in BOTH modes before the TypeScript was retired,
 * and the mode stays wired so the record is reproducible from git history.
 *
 * Both modes are normalised to one flat module map, so no test knows which
 * implementation it is driving.
 */
import { readFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";

const HERE = dirname(fileURLToPath(import.meta.url));
export const CLIENT = join(HERE, "..", "..");
export const TS_MODE = process.env.SUETA_TS === "1";

/** CLJS keeps "private" members as `_name` string keys (peer-kit's idiom). */
export const priv = TS_MODE ? (o, n) => o.__t[n] : (o, n) => o[`_${n}`].bind(o);

let cached = null;

export async function mods() {
  if (cached) return cached;
  if (TS_MODE) {
    const { loadTs } = await import("../harness/ts.mjs");
    const m = await loadTs();
    cached = {
      // config
      APP_SALT: m.APP_SALT,
      NS: m.NS,
      nsKey: m.nsKey,
      nsDb: m.nsDb,
      // lib/crypto
      RoomCrypto: m.RoomCrypto,
      Sealer: m.Sealer,
      AtRestCipher: m.AtRestCipher,
      toB64: m.toB64,
      fromB64: m.fromB64,
      toB64url: m.toB64url,
      fromB64url: m.fromB64url,
      randomBytes: m.randomBytes,
      newPeerId: m.newPeerId,
      newRoomSecret: m.newRoomSecret,
      // lib/encryption
      makeLogEncryption: m.encryption.makeLogEncryption,
      // lib/access
      signerMatchesIdentity: m.access.signerMatchesIdentity,
      HardenedIPFSAccessController: m.access.HardenedIPFSAccessController,
      // lib/orbit-identity
      SuetaIdentityProvider: m.orbitIdentity.SuetaIdentityProvider,
      registerSuetaProvider: m.orbitIdentity.registerSuetaProvider,
      // lib/descriptor, lib/turn
      resolveRelayConfig: m.descriptor.resolveRelayConfig,
      IceConfig: m.turn.IceConfig,
      // lib/log, lib/net
      openHelia: m.log.openHelia,
      RoomLog: m.log.RoomLog,
      Net: m.net.Net,
      newSessionKey: m.net.newSessionKey,
      // lib/mailbox
      MailboxAuth: m.mailbox.MailboxAuth,
      MailboxClient: m.mailbox.MailboxClient,
      MailboxSync: m.mailbox.MailboxSync,
      // lib/selftest
      runSelfTest: m.selftest.runSelfTest,
      // app
      loadHistory: m.history.loadHistory,
      trustObserve: m.trust.observe,
      trustSetVerified: m.trust.setVerified,
      trustIsVerified: m.trust.isVerified,
      loadRooms: m.rooms.loadRooms,
      touchRoom: m.rooms.touchRoom,
      renameRoom: m.rooms.renameRoom,
      forgetRoom: m.rooms.forgetRoom,
      buildRoomSync: m.rooms.buildRoomSync,
      mergeRooms: m.rooms.mergeRooms,
      setOnRoomsChanged: m.rooms.setOnRoomsChanged,
      migrateLegacyHistory: m.migrate.migrateLegacyHistory,
      migrateStorageNS: m.migrateStorage.migrateStorageNS,
      ChatStore: m.chat.ChatStore,
      CallManager: m.call.CallManager,
      // i18n
      catalogKeys: (lang) => Object.keys({ en: m.en, ro: m.ro, hu: m.hu }[lang]).sort(),
      // the FULL message under a key: a string, or the plural-variant object.
      // catalogMsg below reports only the variant NAMES, which would leave the
      // Romanian and Hungarian plural TEXT unsnapshotted.
      catalogRaw: (lang, k) => {
        const msg = { en: m.en, ro: m.ro, hu: m.hu }[lang][k];
        return typeof msg === "string" ? msg : msg === undefined ? undefined : { ...msg };
      },
      catalogMsg: (lang, k) => {
        const msg = { en: m.en, ro: m.ro, hu: m.hu }[lang][k];
        return typeof msg === "string" ? msg : msg === undefined ? undefined : Object.keys(msg).sort();
      },
      t: m.i18n.t,
      tn: m.i18n.tn,
    };
    return cached;
  }
  cached = await import(pathToFileURL(join(CLIENT, "test-dist", "testlib.js")).href);
  return cached;
}

export const readVector = (name) =>
  JSON.parse(readFileSync(join(HERE, "..", "vectors", `${name}.json`), "utf8"));

export const hex = (u8) => [...u8].map((b) => b.toString(16).padStart(2, "0")).join("");

export const fromHex = (s) => {
  const out = new Uint8Array(s.length / 2);
  for (let i = 0; i < out.length; i++) out[i] = parseInt(s.slice(i * 2, i * 2 + 2), 16);
  return out;
};

export const json = (x) => JSON.parse(JSON.stringify(x));

static mirror of HEAD · about · clone: git clone https://git.ardegazu.ro/chat.git