git » sdk » commit 3d7aba8

Make npm package even more ESM compatible

author Stephen Paul Weber
2025-11-23 19:50:28 UTC
committer Stephen Paul Weber
2025-11-23 19:52:22 UTC
parent 8e5cdb72f3afd901447a3ac663c836a415e83f0e

Make npm package even more ESM compatible

Would even support tree shaking except for the mutations...
https://github.com/HaxeFoundation/haxe/issues/12409

.gitignore +2 -8
Makefile +5 -30
borogove/calls/Session.hx +3 -1
borogove/persistence/IDB.js +48 -33
browserjs.hxml +2 -3
nodejs.hxml +2 -3
npm/calls.ts +7 -0
npm/index.ts +44 -50
npm/persistence.ts +9 -0

diff --git a/.gitignore b/.gitignore
index 737d41f..2cae8da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,16 +1,10 @@
 npm/package-lock.json
 npm/*.d.ts
+npm/*.js
+npm/*.mjs
 npm/*.map
-npm/MediaStoreCache.js
-npm/sqlite-worker1.mjs
-npm/IDB.js
-npm/borogove.js
 npm/borogove-enums.ts
-npm/borogove-enums.js
-npm/borogove-browser.js
 npm/borogove-browser-enums.ts
-npm/borogove-browser-enums.js
-npm/index.js
 node_modules
 site
 haxedoc.xml
diff --git a/Makefile b/Makefile
index f1f2a26..92e5dc7 100644
--- a/Makefile
+++ b/Makefile
@@ -21,40 +21,16 @@ hx-build-dep:
 	haxelib --quiet install utest
 	haxelib --quiet git hxcpp https://github.com/HaxeFoundation/hxcpp
 
-
 npm/borogove-browser.js:
 	haxe browserjs.hxml
-	sed -i 's/import { borogove }/import { borogove as enums }/' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.UiState/enums.UiState/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.MessageStatus/enums.MessageStatus/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.MessageDirection/enums.MessageDirection/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.MessageType/enums.MessageType/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.UserState/enums.UserState/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.ChatMessageEvent/enums.ChatMessageEvent/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.ReactionUpdateKind/enums.ReactionUpdateKind/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.calls\.CallStatus/enums.calls.CallStatus/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.EncryptionMode/enums.EncryptionMode/g' npm/borogove-browser.d.ts
-	sed -i 's/borogove\.EncryptionStatus/enums.EncryptionStatus/g' npm/borogove-browser.d.ts
-	sed -i '1ivar exports = {};' npm/borogove-browser.js
-	sed -i '$$i export const borogove = exports.borogove;' npm/borogove-browser.js
+	sed -i '/;var $$hx_exports = typeof exports != "undefined" ? exports : globalThis;/{N;N;N;d;}' npm/borogove-browser.js
+	sed -i 's/^$$hx_exports[^=]*=\(.*\);$$/export {\1 };/g' npm/borogove-browser.js
 
 npm/borogove.js:
 	haxe nodejs.hxml
-	sed -i 's/import { borogove }/import { borogove as enums }/' npm/borogove.d.ts
-	sed -i 's/borogove\.UiState/enums.UiState/g' npm/borogove.d.ts
-	sed -i 's/borogove\.MessageStatus/enums.MessageStatus/g' npm/borogove.d.ts
-	sed -i 's/borogove\.MessageDirection/enums.MessageDirection/g' npm/borogove.d.ts
-	sed -i 's/borogove\.MessageType/enums.MessageType/g' npm/borogove.d.ts
-	sed -i 's/borogove\.UserState/enums.UserState/g' npm/borogove.d.ts
-	sed -i 's/borogove\.ChatMessageEvent/enums.ChatMessageEvent/g' npm/borogove.d.ts
-	sed -i 's/borogove\.ReactionUpdateKind/enums.ReactionUpdateKind/g' npm/borogove.d.ts
-	sed -i 's/borogove\.calls\.CallStatus/enums.calls.CallStatus/g' npm/borogove.d.ts
-	sed -i 's/borogove\.EncryptionMode/enums.EncryptionMode/g' npm/borogove.d.ts
-	sed -i 's/borogove\.EncryptionStatus/enums.EncryptionStatus/g' npm/borogove.d.ts
-	sed -i '1iimport { createRequire } from "module";' npm/borogove.js
-	sed -i '1iglobal.require = createRequire(import.meta.url);' npm/borogove.js
-	sed -i '1ivar exports = {};' npm/borogove.js
-	sed -i '$$i export const borogove = exports.borogove;' npm/borogove.js
+	sed -i '/;var $$hx_exports = typeof exports != "undefined" ? exports : globalThis;/{N;N;N;d;}' npm/borogove.js
+	sed -i 's/^$$hx_exports[^=]*=\(.*\);$$/export {\1 };/g' npm/borogove.js
+	cd npm && npx cjstoesm borogove.js
 
 npm: npm/borogove-browser.js npm/borogove.js borogove/persistence/IDB.js borogove/persistence/MediaStoreCache.js borogove/persistence/sqlite-worker1.mjs
 	cp borogove/persistence/IDB.js npm
@@ -62,7 +38,6 @@ npm: npm/borogove-browser.js npm/borogove.js borogove/persistence/IDB.js borogov
 	cp borogove/persistence/sqlite-worker1.mjs npm
 	-cd npm && npx tsc --esModuleInterop --lib esnext,dom --target esnext --preserveConstEnums --allowJs --checkJs -d index.ts > /dev/null
 	cd npm && npx tsc --esModuleInterop --lib esnext,dom --target esnext --preserveConstEnums --allowJs --checkJs -d index.ts
-	sed -i '1iimport { borogove as enums } from "./borogove-enums.js";' npm/index.js
 
 cpp/output.dso:
 	haxe cpp.hxml
diff --git a/borogove/calls/Session.hx b/borogove/calls/Session.hx
index dcd1f81..6d8b0a5 100644
--- a/borogove/calls/Session.hx
+++ b/borogove/calls/Session.hx
@@ -25,6 +25,7 @@ enum abstract CallStatus(Int) {
 #if cpp
 @:build(HaxeSwiftBridge.expose())
 #end
+@:expose
 interface Session {
 	public var sid (get, null): String;
 	public var chatId (get, null): String;
@@ -324,6 +325,7 @@ class OutgoingProposedSession implements Session {
 @:build(HaxeCBridge.expose())
 @:build(HaxeSwiftBridge.expose())
 #end
+@:expose
 class InitiatedSession implements Session {
 	public var sid (get, null): String;
 	public var chatId (get, null): String;
@@ -700,7 +702,7 @@ class OutgoingSession extends InitiatedSession {
 		remoteDescription = SessionDescription.fromStanza(stanza, true);
 		peerDtlsSetup = remoteDescription.getDtlsSetup();
 		pc.setRemoteDescription({ type: SdpType.ANSWER, sdp: remoteDescription.toSdp() })
-		  .then((_) -> transportInfo(stanza));
+			.then((_) -> transportInfo(stanza));
 		return this;
 	}
 
diff --git a/borogove/persistence/IDB.js b/borogove/persistence/IDB.js
index 0354467..86a7a62 100644
--- a/borogove/persistence/IDB.js
+++ b/borogove/persistence/IDB.js
@@ -1,8 +1,23 @@
 // This example persistence driver is written in JavaScript
 // so that SDK users can easily see how to write their own
 
-import { borogove as enums } from "./borogove-enums.js";
-import { borogove } from "./borogove.js";
+// Importing internals not the public interface
+import {
+	borogove_Caps,
+	borogove_Channel,
+	borogove_ChatMessageBuilder,
+	borogove_CustomEmojiReaction,
+	borogove_DirectChat,
+	borogove_Hash,
+	borogove_Identity,
+	borogove_JID,
+	borogove_Presence,
+	borogove_Reaction,
+	borogove_ReactionUpdate,
+	borogove_SerializedChat,
+	borogove_Stanza,
+} from "./borogove.js";
+import * as enums from "./borogove-enums.js";
 
 export default async (dbname, media, tokenize, stemmer) => {
 	if (!tokenize) tokenize = function(s) { return s.split(" "); }
@@ -97,17 +112,17 @@ export default async (dbname, media, tokenize, stemmer) => {
 
 	function hydrateStringReaction(r, senderId, timestamp) {
 		if (r.startsWith("ni://")){
-			return new borogove.CustomEmojiReaction(senderId, timestamp, "", r);
+			return new borogove_CustomEmojiReaction(senderId, timestamp, "", r);
 		} else {
-			return new borogove.Reaction(senderId, timestamp, r);
+			return new borogove_Reaction(senderId, timestamp, r);
 		}
 	}
 
 	function hydrateObjectReaction(r) {
 		if (r.uri) {
-			return new borogove.CustomEmojiReaction(r.senderId, r.timestamp, r.text, r.uri, r.envelopeId);
+			return new borogove_CustomEmojiReaction(r.senderId, r.timestamp, r.text, r.uri, r.envelopeId);
 		} else {
-			return new borogove.Reaction(r.senderId, r.timestamp, r.text, r.envelopeId, r.key);
+			return new borogove_Reaction(r.senderId, r.timestamp, r.text, r.envelopeId, r.key);
 		}
 	}
 
@@ -131,7 +146,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 		const tx = db.transaction(["messages"], "readonly");
 		const store = tx.objectStore("messages");
 
-		const message = new borogove.ChatMessageBuilder();
+		const message = new borogove_ChatMessageBuilder();
 		message.localId = value.localId ? value.localId : null;
 		message.serverId = value.serverId ? value.serverId : null;
 		message.serverIdBy = value.serverIdBy ? value.serverIdBy : null;
@@ -141,20 +156,20 @@ export default async (dbname, media, tokenize, stemmer) => {
 		message.status = value.status;
 		message.statusText = value.statusText;
 		message.timestamp = value.timestamp && value.timestamp.toISOString();
-		message.from = value.from && borogove.JID.parse(value.from);
-		message.sender = value.sender && borogove.JID.parse(value.sender);
+		message.from = value.from && borogove_JID.parse(value.from);
+		message.sender = value.sender && borogove_JID.parse(value.sender);
 		message.senderId = value.senderId;
-		message.recipients = value.recipients.map((r) => borogove.JID.parse(r));
-		message.to = value.to ? borogove.JID.parse(value.to) : message.recipients[0];
-		message.replyTo = value.replyTo.map((r) => borogove.JID.parse(r));
+		message.recipients = value.recipients.map((r) => borogove_JID.parse(r));
+		message.to = value.to ? borogove_JID.parse(value.to) : message.recipients[0];
+		message.replyTo = value.replyTo.map((r) => borogove_JID.parse(r));
 		message.threadId = value.threadId;
 		message.attachments = value.attachments;
 		message.reactions = hydrateReactions(value.reactions, message.timestamp);
 		message.text = value.text;
 		message.lang = value.lang;
-		message.type = value.type || (value.isGroupchat || value.groupchat ? enums.MessageType.Channel : enums.MessageType.Chat);
-		message.payloads = (value.payloads || []).map(borogove.Stanza.parse);
-		message.stanza = value.stanza && borogove.Stanza.parse(value.stanza);
+		message.type = value.type || (value.isGroupchat || value.groupchat ? enums.borogove_MessageType.Channel : enums.borogove_MessageType.Chat);
+		message.payloads = (value.payloads || []).map(borogove_Stanza.parse);
+		message.stanza = value.stanza && borogove_Stanza.parse(value.stanza);
 		if (!message.localId && !message.serverId) message.localId = "NO_ID"; // bad data
 		return message.build();
 	}
@@ -210,7 +225,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 		head.versions = versions;
 		head.reactions = result.value.reactions; // Preserve these, edit doesn't touch them
 		// Calls can "edit" from multiple senders, but the original direction and sender holds
-		if (result.value.type === enums.MessageType.MessageCall) {
+		if (result.value.type === enums.borogove_MessageType.MessageCall) {
 			head.direction = result.value.direction;
 			head.senderId = result.value.senderId;
 			head.from = result.value.from;
@@ -283,7 +298,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 					notificationSettings: chat.notificationsFiltered() ? { mention: chat.notifyMention(), reply: chat.notifyReply() } : null,
 					disco: { ...chat.disco, data: chat.disco?.data?.map(d => d.toString()) },
 					omemoDevices: chat.omemoContactDeviceIDs,
-					class: chat instanceof borogove.DirectChat ? "DirectChat" : (chat instanceof borogove.Channel ? "Channel" : "Chat")
+					class: chat instanceof borogove_DirectChat ? "DirectChat" : (chat instanceof borogove_Channel ? "Channel" : "Chat")
 				});
 			}
 		},
@@ -293,12 +308,12 @@ export default async (dbname, media, tokenize, stemmer) => {
 			const store = tx.objectStore("chats");
 			const range = IDBKeyRange.bound([account], [account, []]);
 			const result = await promisifyRequest(store.getAll(range));
-			return await Promise.all(result.map(async (r) => new borogove.SerializedChat(
+			return await Promise.all(result.map(async (r) => new borogove_SerializedChat(
 				r.chatId,
 				r.trusted,
 				r.avatarSha1,
 				new Map(await Promise.all((r.presence instanceof Map ? [...r.presence.entries()] : Object.entries(r.presence)).map(
-					async ([k, p]) => [k, new borogove.Presence(p.caps && await this.getCaps(p.caps), p.mucUser && borogove.Stanza.parse(p.mucUser), p.avatarHash && borogove.Hash.fromUri(p.avatarHash))]
+					async ([k, p]) => [k, new borogove_Presence(p.caps && await this.getCaps(p.caps), p.mucUser && borogove_Stanza.parse(p.mucUser), p.avatarHash && borogove_Hash.fromUri(p.avatarHash))]
 				))),
 				r.displayName,
 				r.uiState,
@@ -309,11 +324,11 @@ export default async (dbname, media, tokenize, stemmer) => {
 				r.notificationSettings === undefined ? null : r.notificationSettings != null,
 				r.notificationSettings?.mention,
 				r.notificationSettings?.reply,
-				r.disco ? new borogove.Caps(
+				r.disco ? new borogove_Caps(
 					r.disco.node,
-					(r.disco.identities || []).map((identity) => new borogove.Identity(identity.category, identity.type, identity.name)),
+					(r.disco.identities || []).map((identity) => new borogove_Identity(identity.category, identity.type, identity.name)),
 					r.disco.features || [],
-					(r.disco.data || []).map(s => borogove.Stanza.parse(s))
+					(r.disco.data || []).map(s => borogove_Stanza.parse(s))
 				) : null,
 				r.omemoDevices || [],
 				r.class
@@ -342,7 +357,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 							result[value.chatId] = result[value.chatId].then((details) => {
 								if (!details.foundAll) {
 									const readUpTo = chats[value.chatId]?.readUpTo();
-									if (readUpTo === value.serverId || readUpTo === value.localId || value.direction == enums.MessageDirection.MessageSent) {
+									if (readUpTo === value.serverId || readUpTo === value.localId || value.direction == enums.borogove_MessageDirection.MessageSent) {
 										details.foundAll = true;
 									} else {
 										details.unreadCount++;
@@ -352,7 +367,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 							});
 						} else {
 							const readUpTo = chats[value.chatId]?.readUpTo();
-							const haveRead = readUpTo === value.serverId || readUpTo === value.localId || value.direction == enums.MessageDirection.MessageSent;
+							const haveRead = readUpTo === value.serverId || readUpTo === value.localId || value.direction == enums.borogove_MessageDirection.MessageSent;
 							result[value.chatId] = hydrateMessage(value).then((m) => ({ chatId: value.chatId, message: m, unreadCount: haveRead ? 0 : 1, foundAll: haveRead }));
 						}
 					}
@@ -392,7 +407,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 				[account, update.chatId, update.serverId || update.localId, update.senderId, []]
 			), "prev"));
 			const reactions = update.getReactions(hydrateReactionsArray(lastFromSender?.value?.reactions));
-			await promisifyRequest(reactionStore.put({...update, reactions: reactions, append: (update.kind === enums.ReactionUpdateKind.AppendReactions ? update.reactions : null), messageId: update.serverId || update.localId, timestamp: new Date(update.timestamp), account: account}));
+			await promisifyRequest(reactionStore.put({...update, reactions: reactions, append: (update.kind === enums.borogove_ReactionUpdateKind.AppendReactions ? update.reactions : null), messageId: update.serverId || update.localId, timestamp: new Date(update.timestamp), account: account}));
 			if (!result || !result.value) return null;
 			if (lastFromSender?.value && lastFromSender.value.timestamp > new Date(update.timestamp)) return;
 			const message = result.value;
@@ -433,13 +448,13 @@ export default async (dbname, media, tokenize, stemmer) => {
 									if (react.senderId === message.senderId && !previouslyAppended.includes(k)) reactions.push(react);
 								}
 							}
-							this.storeReaction(account, new borogove.ReactionUpdate(message.localId, reactionResult.value.serverId, reactionResult.value.serverIdBy, reactionResult.value.localId, message.chatId(), message.senderId, message.timestamp, reactions, enums.ReactionUpdateKind.CompleteReactions), callback);
+							this.storeReaction(account, new borogove_ReactionUpdate(message.localId, reactionResult.value.serverId, reactionResult.value.serverIdBy, reactionResult.value.localId, message.chatId(), message.senderId, message.timestamp, reactions, enums.borogove_ReactionUpdateKind.CompleteReactions), callback);
 						});
 						return true;
-					} else if (result?.value && !message.isIncoming() && result?.value.direction === enums.MessageDirection.MessageSent && message.versions.length < 1) {
+					} else if (result?.value && !message.isIncoming() && result?.value.direction === enums.borogove_MessageDirection.MessageSent && message.versions.length < 1) {
 						// Duplicate, we trust our own sent ids
 						return promisifyRequest(result.delete());
-					} else if (result?.value && (result.value.senderId == message.senderId || result.value.type == enums.MessageType.MessageCall) && (message.versions.length > 0 || (result.value.versions || []).length > 0)) {
+					} else if (result?.value && (result.value.senderId == message.senderId || result.value.type == enums.borogove_MessageType.MessageCall) && (message.versions.length > 0 || (result.value.versions || []).length > 0)) {
 						hydrateMessage(correctMessage(account, message, result)).then(callback);
 						return true;
 					}
@@ -485,7 +500,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 			const tx = db.transaction(["messages"], "readwrite");
 			const store = tx.objectStore("messages");
 			const result = await promisifyRequest(store.index("localId").openCursor(IDBKeyRange.bound([account, localId], [account, localId, []])));
-			if (result?.value && result.value.direction === enums.MessageDirection.MessageSent && ![enums.MessageStatus.MessageDeliveredToDevice, enums.MessageStatus.MessageFailedToSend].includes(result.value.status)) {
+			if (result?.value && result.value.direction === enums.borogove_MessageDirection.MessageSent && ![enums.borogove_MessageStatus.MessageDeliveredToDevice, enums.borogove_MessageStatus.MessageFailedToSend].includes(result.value.status)) {
 				const newStatus = { ...result.value, status, statusText };
 				result.update(newStatus);
 				return await hydrateMessage(newStatus);
@@ -502,7 +517,7 @@ export default async (dbname, media, tokenize, stemmer) => {
 				if (!cresult) break;
 
 				const value = cresult.value;
-				if (value?.versions?.[0]?.localId === localId && value?.direction === enums.MessageDirection.MessageSent && ![enums.MessageStatus.MessageDeliveredToDevice, enums.MessageStatus.MessageFailedToSend].includes(result.value.status)) {
+				if (value?.versions?.[0]?.localId === localId && value?.direction === enums.borogove_MessageDirection.MessageSent && ![enums.borogove_MessageStatus.MessageDeliveredToDevice, enums.borogove_MessageStatus.MessageFailedToSend].includes(result.value.status)) {
 					const newStatus = { ...value, versions: [{ ...value.versions[0], status, statusText }, ...value.versions.slice(1)], status, statusText };
 					cresult.update(newStatus);
 					return await hydrateMessage(newStatus);
@@ -638,11 +653,11 @@ export default async (dbname, media, tokenize, stemmer) => {
 			const store = tx.objectStore("keyvaluepairs");
 			const raw = await promisifyRequest(store.get("caps:" + ver));
 			if (raw) {
-				return new borogove.Caps(
+				return new borogove_Caps(
 					raw.node,
-					raw.identities.map((identity) => new borogove.Identity(identity.category, identity.type, identity.name)),
+					raw.identities.map((identity) => new borogove_Identity(identity.category, identity.type, identity.name)),
 					raw.features,
-					(raw.data || []).map(s => borogove.Stanza.parse(s))
+					(raw.data || []).map(s => borogove_Stanza.parse(s))
 				);
 			}
 
diff --git a/browserjs.hxml b/browserjs.hxml
index 6646135..fd448c5 100644
--- a/browserjs.hxml
+++ b/browserjs.hxml
@@ -16,9 +16,8 @@ borogove.persistence.Sqlite
 
 -D analyzer-optimize
 -D js-es=6
--D source-map
--D source-map-content
 -D hxtsdgen_enums_ts
--D hxtsdgen_namespaced
+-D js_global=globalThis
+-D js-classic
 -D NO_OMEMO
 --js npm/borogove-browser.js
diff --git a/nodejs.hxml b/nodejs.hxml
index 9d36c8f..d34e603 100644
--- a/nodejs.hxml
+++ b/nodejs.hxml
@@ -17,9 +17,8 @@ borogove.persistence.Sqlite
 
 -D analyzer-optimize
 -D js-es=6
--D source-map
--D source-map-content
 -D hxtsdgen_enums_ts
--D hxtsdgen_namespaced
+-D js_global=globalThis
+-D js-classic
 -D NO_OMEMO
 --js npm/borogove.js
diff --git a/npm/calls.ts b/npm/calls.ts
new file mode 100644
index 0000000..2aa2a21
--- /dev/null
+++ b/npm/calls.ts
@@ -0,0 +1,7 @@
+export {
+	borogove_calls_CallStatus as CallStatus,
+} from "./borogove-enums";
+export {
+	borogove_calls_Session as Session,
+	borogove_calls_InitiatedSession as InitiatedSession,
+} from "./borogove.js";
diff --git a/npm/index.ts b/npm/index.ts
index a6d7d5a..286bc83 100644
--- a/npm/index.ts
+++ b/npm/index.ts
@@ -1,53 +1,47 @@
-import IDBjs from "./IDB.js";
-import MediaStoreCachejs from "./MediaStoreCache.js";
-import { borogove as enums } from "./borogove-enums.js";
-import { borogove } from "./borogove.js";
+export {
+	borogove_ChatMessageEvent as ChatMessageEvent,
+	borogove_MessageDirection as MessageDirection,
+	borogove_MessageStatus as MessageStatus,
+	borogove_MessageType as MessageType,
+	borogove_ReactionUpdateKind as ReactionUpdateKind,
+	borogove_UiState as UiState,
+	borogove_UserState as UserState,
+} from "./borogove-enums";
+export {
+    borogove_AvailableChat as AvailableChat,
+    borogove_Channel as Channel,
+    borogove_Chat as Chat,
+    borogove_ChatAttachment as ChatAttachment,
+    borogove_ChatMessage as ChatMessage,
+    borogove_ChatMessageBuilder as ChatMessageBuilder,
+    borogove_Client as Client,
+    borogove_Command as Command,
+    borogove_CommandSession as CommandSession,
+    borogove_Config as Config,
+    borogove_CustomEmojiReaction as CustomEmojiReaction,
+    borogove_DirectChat as DirectChat,
+    borogove_EventEmitter as EventEmitter,
+    borogove_Form as Form,
+    borogove_FormSection as FormSection,
+    borogove_FormItem as FormItem,
+    borogove_FormField as FormField,
+    borogove_FormOption as FormOption,
+    borogove_Hash as Hash,
+    borogove_Identicon as Identicon,
+    borogove_Notification as Notification,
+    borogove_Participant as Participant,
+    borogove_Persistence as Persistence,
+    borogove_Push as Push,
+    borogove_Reaction as Reaction,
+    borogove_Register as Register,
+    borogove_SerializedChat as SerializedChat,
+} from "./borogove.js";
 
-// TODO: should we autogenerate this?
-export import AvailableChat = borogove.AvailableChat;
-export import Channel = borogove.Channel;
-export import Chat = borogove.Chat;
-export import ChatAttachment = borogove.ChatAttachment;
-export import ChatMessage = borogove.ChatMessage;
-export import ChatMessageBuilder = borogove.ChatMessageBuilder;
-export import Client = borogove.Client;
-export import Command = borogove.Command;
-export import CommandSession = borogove.CommandSession;
-export import Config = borogove.Config;
-export import CustomEmojiReaction = borogove.CustomEmojiReaction;
-export import DirectChat = borogove.DirectChat;
-export import EventEmitter = borogove.EventEmitter;
-export import Form = borogove.Form;
-export import FormSection = borogove.FormSection;
-export import FormItem = borogove.FormItem;
-export import FormField = borogove.FormField;
-export import FormOption = borogove.FormOption;
-export import Hash = borogove.Hash;
-export import Identicon = borogove.Identicon;
-export import Notification = borogove.Notification;
-export import Participant = borogove.Participant;
-export import Persistence = borogove.Persistence;
-export import Push = borogove.Push;
-export import Reaction = borogove.Reaction;
-export import Register = borogove.Register;
-export import SerializedChat = borogove.SerializedChat;
-export const VERSION = borogove.Version.HUMAN;
-export import calls = borogove.calls;
+import * as persistence from "./persistence";
+export { persistence };
 
-export import CallStatus = enums.calls.CallStatus;
-export import ChatMessageEvent = enums.ChatMessageEvent;
-export import MessageDirection = enums.MessageDirection;
-export import MessageStatus = enums.MessageStatus;
-export import MessageType = enums.MessageType;
-export import ReactionUpdateKind = enums.ReactionUpdateKind;
-export import UiState = enums.UiState;
-export import UserState = enums.UserState;
+import * as calls from "./calls";
+export { calls };
 
-export namespace persistence {
-	export const IDB = IDBjs;
-	export import KeyValueStore = borogove.persistence.KeyValueStore;
-	export import MediaStore = borogove.persistence.MediaStore;
-	export const MediaStoreCache = MediaStoreCachejs;
-	export import Dummy = borogove.persistence.Dummy;
-	export import Sqlite = borogove.persistence.Sqlite;
-}
+import { borogove_Version } from "./borogove.js";
+export const VERSION = borogove_Version.HUMAN;
diff --git a/npm/persistence.ts b/npm/persistence.ts
new file mode 100644
index 0000000..8f3f7ff
--- /dev/null
+++ b/npm/persistence.ts
@@ -0,0 +1,9 @@
+export { default as IDB } from "./IDB.js";
+export { default as MediaStoreCache } from "./MediaStoreCache.js";
+
+export {
+	borogove_persistence_KeyValueStore as KeyValueStore,
+	borogove_persistence_MediaStore as MediaStore,
+	borogove_persistence_Dummy as Dummy,
+	borogove_persistence_Sqlite as Sqlite,
+} from "./borogove.js";