@majikah/majik-message 0.3.5 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +7 -3
  2. package/dist/core/client-state-manager.d.ts +105 -0
  3. package/dist/core/client-state-manager.js +250 -0
  4. package/dist/core/contacts/majik-contact-directory.d.ts +0 -5
  5. package/dist/core/contacts/majik-contact-directory.js +0 -12
  6. package/dist/core/contacts/majik-contact-groups.d.ts +1 -0
  7. package/dist/core/contacts/majik-contact-groups.js +5 -0
  8. package/dist/core/contacts/majik-contact-manager.d.ts +92 -184
  9. package/dist/core/contacts/majik-contact-manager.js +368 -288
  10. package/dist/core/crypto/keystore-manager.d.ts +166 -0
  11. package/dist/core/crypto/keystore-manager.js +371 -0
  12. package/dist/core/storage/chats/_types.d.ts +8 -0
  13. package/dist/core/storage/chats/_types.js +1 -0
  14. package/dist/core/storage/chats/adapter-idb.d.ts +3 -0
  15. package/dist/core/storage/chats/adapter-idb.js +5 -0
  16. package/dist/core/storage/chats/adapter-memory.d.ts +23 -0
  17. package/dist/core/storage/chats/adapter-memory.js +44 -0
  18. package/dist/core/storage/chats/adapter-sql.d.ts +17 -0
  19. package/dist/core/storage/chats/adapter-sql.js +84 -0
  20. package/dist/core/storage/client-state/_types.d.ts +37 -0
  21. package/dist/core/storage/client-state/_types.js +16 -0
  22. package/dist/core/storage/client-state/adapter-idb.d.ts +17 -0
  23. package/dist/core/storage/client-state/adapter-idb.js +19 -0
  24. package/dist/core/storage/client-state/adapter-memory.d.ts +20 -0
  25. package/dist/core/storage/client-state/adapter-memory.js +44 -0
  26. package/dist/core/storage/client-state/adapter-sql.d.ts +41 -0
  27. package/dist/core/storage/client-state/adapter-sql.js +104 -0
  28. package/dist/core/storage/contact-directory/contacts/_types.d.ts +3 -0
  29. package/dist/core/storage/contact-directory/contacts/_types.js +1 -0
  30. package/dist/core/storage/contact-directory/contacts/adapter-idb.d.ts +3 -0
  31. package/dist/core/storage/contact-directory/contacts/adapter-idb.js +5 -0
  32. package/dist/core/storage/contact-directory/contacts/adapter-memory.d.ts +14 -0
  33. package/dist/core/storage/contact-directory/contacts/adapter-memory.js +32 -0
  34. package/dist/core/storage/contact-directory/contacts/adapter-sql.d.ts +16 -0
  35. package/dist/core/storage/contact-directory/contacts/adapter-sql.js +73 -0
  36. package/dist/core/storage/contact-directory/groups/_types.d.ts +3 -0
  37. package/dist/core/storage/contact-directory/groups/_types.js +1 -0
  38. package/dist/core/storage/contact-directory/groups/adapter-idb.d.ts +3 -0
  39. package/dist/core/storage/contact-directory/groups/adapter-idb.js +5 -0
  40. package/dist/core/storage/contact-directory/groups/adapter-memory.d.ts +14 -0
  41. package/dist/core/storage/contact-directory/groups/adapter-memory.js +32 -0
  42. package/dist/core/storage/contact-directory/groups/adapter-sql.d.ts +16 -0
  43. package/dist/core/storage/contact-directory/groups/adapter-sql.js +71 -0
  44. package/dist/core/storage/idb-adapter.d.ts +21 -0
  45. package/dist/core/storage/idb-adapter.js +107 -0
  46. package/dist/core/storage/index.d.ts +24 -0
  47. package/dist/core/storage/index.js +19 -0
  48. package/dist/core/storage/keystore/_types.d.ts +3 -0
  49. package/dist/core/storage/keystore/_types.js +1 -0
  50. package/dist/core/storage/keystore/adapter-idb.d.ts +3 -0
  51. package/dist/core/storage/keystore/adapter-idb.js +5 -0
  52. package/dist/core/storage/keystore/adapter-memory.d.ts +14 -0
  53. package/dist/core/storage/keystore/adapter-memory.js +32 -0
  54. package/dist/core/storage/keystore/adapter-sql.d.ts +16 -0
  55. package/dist/core/storage/keystore/adapter-sql.js +69 -0
  56. package/dist/core/storage/sql-db-manager.d.ts +13 -0
  57. package/dist/core/storage/sql-db-manager.js +59 -0
  58. package/dist/core/storage/sql-schema.d.ts +10 -0
  59. package/dist/core/storage/sql-schema.js +108 -0
  60. package/dist/core/storage/storage-adapter.d.ts +14 -0
  61. package/dist/core/storage/storage-adapter.js +1 -0
  62. package/dist/index.d.ts +2 -4
  63. package/dist/index.js +2 -4
  64. package/dist/majik-message.d.ts +109 -174
  65. package/dist/majik-message.js +428 -677
  66. package/package.json +5 -6
@@ -0,0 +1,71 @@
1
+ export class SQLiteContactGroupAdapter {
2
+ db;
3
+ constructor(db) {
4
+ this.db = db;
5
+ }
6
+ async save(group) {
7
+ await this.db.run(`INSERT OR REPLACE INTO majik_contact_groups
8
+ (id, json, name, created_at, updated_at, is_system)
9
+ VALUES (?, ?, ?, ?, ?, ?)`, [
10
+ group.id,
11
+ JSON.stringify(group),
12
+ group.meta?.name ?? null,
13
+ group.meta?.createdAt ?? null,
14
+ group.meta?.updatedAt ?? null,
15
+ group.isSystem ? 1 : 0,
16
+ ]);
17
+ }
18
+ async getById(id) {
19
+ const row = await this.db.get("SELECT json FROM majik_contact_groups WHERE id = ?", [id]);
20
+ return row ? JSON.parse(row.json) : null;
21
+ }
22
+ async list() {
23
+ const rows = await this.db.all("SELECT json FROM majik_contact_groups");
24
+ return rows.map((r) => JSON.parse(r.json));
25
+ }
26
+ async remove(id) {
27
+ const exists = await this.exists(id);
28
+ if (!exists)
29
+ return false;
30
+ await this.db.run("DELETE FROM majik_contact_groups WHERE id = ?", [id]);
31
+ return true;
32
+ }
33
+ async clear() {
34
+ await this.db.run("DELETE FROM majik_contact_groups");
35
+ }
36
+ async count() {
37
+ const row = await this.db.get("SELECT COUNT(*) as n FROM majik_contact_groups");
38
+ return row?.n ?? 0;
39
+ }
40
+ async exists(id) {
41
+ const row = await this.db.get("SELECT 1 FROM majik_contact_groups WHERE id = ?", [id]);
42
+ return !!row;
43
+ }
44
+ async bulkSave(groups) {
45
+ if (groups.length === 0)
46
+ return;
47
+ await this.db.transaction(async (tx) => {
48
+ for (const g of groups) {
49
+ await tx.run(`INSERT OR REPLACE INTO majik_contact_groups
50
+ (id, json, name, created_at, updated_at, is_system)
51
+ VALUES (?, ?, ?, ?, ?, ?)`, [
52
+ g.id,
53
+ JSON.stringify(g),
54
+ g.meta?.name ?? null,
55
+ g.meta?.createdAt ?? null,
56
+ g.meta?.updatedAt ?? null,
57
+ g.isSystem ? 1 : 0,
58
+ ]);
59
+ }
60
+ });
61
+ }
62
+ async bulkRemove(ids) {
63
+ if (ids.length === 0)
64
+ return;
65
+ await this.db.transaction(async (tx) => {
66
+ for (const id of ids) {
67
+ await tx.run("DELETE FROM majik_contact_groups WHERE id = ?", [id]);
68
+ }
69
+ });
70
+ }
71
+ }
@@ -0,0 +1,21 @@
1
+ import { MajikStorageAdapter } from "./storage-adapter";
2
+ export declare class IDBGenericAdapter<T extends {
3
+ id: string;
4
+ }> implements MajikStorageAdapter<T> {
5
+ private dbName;
6
+ private storeName;
7
+ private version;
8
+ constructor(dbName: string, storeName: string, version?: number);
9
+ private db;
10
+ private open;
11
+ private tx;
12
+ save(item: T): Promise<void>;
13
+ getById(id: string): Promise<T | null>;
14
+ list(): Promise<T[]>;
15
+ remove(id: string): Promise<boolean>;
16
+ clear(): Promise<void>;
17
+ count(): Promise<number>;
18
+ exists(id: string): Promise<boolean>;
19
+ bulkSave(items: T[]): Promise<void>;
20
+ bulkRemove(ids: string[]): Promise<void>;
21
+ }
@@ -0,0 +1,107 @@
1
+ export class IDBGenericAdapter {
2
+ dbName;
3
+ storeName;
4
+ version;
5
+ constructor(dbName, storeName, version = 1) {
6
+ this.dbName = dbName;
7
+ this.storeName = storeName;
8
+ this.version = version;
9
+ }
10
+ db = null;
11
+ async open() {
12
+ if (this.db)
13
+ return this.db;
14
+ return new Promise((resolve, reject) => {
15
+ const req = indexedDB.open(this.dbName, this.version);
16
+ req.onupgradeneeded = () => {
17
+ const db = req.result;
18
+ const stores = [this.storeName]; // or pass array if you want
19
+ for (const name of stores) {
20
+ if (!db.objectStoreNames.contains(name)) {
21
+ db.createObjectStore(name, { keyPath: "id" });
22
+ }
23
+ }
24
+ };
25
+ req.onsuccess = () => {
26
+ this.db = req.result;
27
+ resolve(this.db);
28
+ };
29
+ req.onerror = () => reject(req.error);
30
+ });
31
+ }
32
+ async tx(mode, fn) {
33
+ const db = await this.open();
34
+ return new Promise((resolve, reject) => {
35
+ const tx = db.transaction(this.storeName, mode);
36
+ const store = tx.objectStore(this.storeName);
37
+ const req = fn(store);
38
+ if (req) {
39
+ req.onsuccess = () => resolve(req.result);
40
+ req.onerror = () => reject(req.error);
41
+ tx.onabort = () => reject(tx.error); // 👈 ADD THIS
42
+ }
43
+ else {
44
+ tx.oncomplete = () => resolve(undefined);
45
+ tx.onerror = () => reject(tx.error);
46
+ tx.onabort = () => reject(tx.error); // 👈 ADD THIS
47
+ }
48
+ });
49
+ }
50
+ async save(item) {
51
+ await this.tx("readwrite", (s) => s.put(item));
52
+ }
53
+ async getById(id) {
54
+ const result = await this.tx("readonly", (s) => s.get(id));
55
+ return result ?? null;
56
+ }
57
+ async list() {
58
+ return await this.tx("readonly", (s) => s.getAll());
59
+ }
60
+ async remove(id) {
61
+ const exists = await this.exists(id);
62
+ if (!exists)
63
+ return false;
64
+ await this.tx("readwrite", (s) => s.delete(id));
65
+ return true;
66
+ }
67
+ async clear() {
68
+ await this.tx("readwrite", (s) => s.clear());
69
+ }
70
+ async count() {
71
+ return await this.tx("readonly", (s) => s.count());
72
+ }
73
+ async exists(id) {
74
+ const key = await this.tx("readonly", (s) => s.getKey(id));
75
+ return key != null;
76
+ }
77
+ async bulkSave(items) {
78
+ if (items.length === 0)
79
+ return;
80
+ const db = await this.open();
81
+ return new Promise((resolve, reject) => {
82
+ const tx = db.transaction(this.storeName, "readwrite");
83
+ const store = tx.objectStore(this.storeName);
84
+ for (const item of items) {
85
+ store.put(item);
86
+ }
87
+ tx.oncomplete = () => resolve();
88
+ tx.onerror = () => reject(tx.error);
89
+ tx.onabort = () => reject(tx.error);
90
+ });
91
+ }
92
+ async bulkRemove(ids) {
93
+ if (ids.length === 0)
94
+ return;
95
+ const db = await this.open();
96
+ return new Promise((resolve, reject) => {
97
+ const tx = db.transaction(this.storeName, "readwrite");
98
+ const store = tx.objectStore(this.storeName);
99
+ for (const id of ids) {
100
+ store.delete(id);
101
+ }
102
+ tx.oncomplete = () => resolve();
103
+ tx.onerror = () => reject(tx.error);
104
+ tx.onabort = () => reject(tx.error);
105
+ });
106
+ }
107
+ }
@@ -0,0 +1,24 @@
1
+ export * from "./sql-schema";
2
+ export * from "./sql-db-manager";
3
+ export * from "./storage-adapter";
4
+ export * from "./idb-adapter";
5
+ export * from "./client-state/adapter-idb";
6
+ export * from "./client-state/adapter-sql";
7
+ export * from "./client-state/adapter-memory";
8
+ export type * from "./client-state/_types";
9
+ export * from "./contact-directory/contacts/adapter-idb";
10
+ export * from "./contact-directory/contacts/adapter-sql";
11
+ export * from "./contact-directory/contacts/adapter-memory";
12
+ export type * from "./contact-directory/contacts/_types";
13
+ export * from "./contact-directory/groups/adapter-idb";
14
+ export * from "./contact-directory/groups/adapter-sql";
15
+ export * from "./contact-directory/groups/adapter-memory";
16
+ export type * from "./contact-directory/groups/_types";
17
+ export * from "./chats/adapter-idb";
18
+ export * from "./chats/adapter-sql";
19
+ export * from "./chats/adapter-memory";
20
+ export type * from "./chats/_types";
21
+ export * from "./keystore/adapter-idb";
22
+ export * from "./keystore/adapter-sql";
23
+ export * from "./keystore/adapter-memory";
24
+ export type * from "./keystore/_types";
@@ -0,0 +1,19 @@
1
+ export * from "./sql-schema";
2
+ export * from "./sql-db-manager";
3
+ export * from "./storage-adapter";
4
+ export * from "./idb-adapter";
5
+ export * from "./client-state/adapter-idb";
6
+ export * from "./client-state/adapter-sql";
7
+ export * from "./client-state/adapter-memory";
8
+ export * from "./contact-directory/contacts/adapter-idb";
9
+ export * from "./contact-directory/contacts/adapter-sql";
10
+ export * from "./contact-directory/contacts/adapter-memory";
11
+ export * from "./contact-directory/groups/adapter-idb";
12
+ export * from "./contact-directory/groups/adapter-sql";
13
+ export * from "./contact-directory/groups/adapter-memory";
14
+ export * from "./chats/adapter-idb";
15
+ export * from "./chats/adapter-sql";
16
+ export * from "./chats/adapter-memory";
17
+ export * from "./keystore/adapter-idb";
18
+ export * from "./keystore/adapter-sql";
19
+ export * from "./keystore/adapter-memory";
@@ -0,0 +1,3 @@
1
+ import { MajikKeyJSON } from "@majikah/majik-key";
2
+ import { MajikStorageAdapter } from "../storage-adapter";
3
+ export type MajikKeyStorageAdapter = MajikStorageAdapter<MajikKeyJSON>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import { MajikKeyJSON } from "@majikah/majik-key";
2
+ import { IDBGenericAdapter } from "../idb-adapter";
3
+ export declare const IDB_ADAPTER_KEYSTORE: IDBGenericAdapter<MajikKeyJSON>;
@@ -0,0 +1,5 @@
1
+ import { IDBGenericAdapter } from "../idb-adapter";
2
+ const IDB_DB_NAME = "majik-keys";
3
+ const IDB_STORE_NAME = "identities";
4
+ const IDB_VERSION = 1;
5
+ export const IDB_ADAPTER_KEYSTORE = new IDBGenericAdapter(IDB_DB_NAME, IDB_STORE_NAME, IDB_VERSION);
@@ -0,0 +1,14 @@
1
+ import { MajikKeyJSON } from "@majikah/majik-key";
2
+ import { MajikKeyStorageAdapter } from "./_types";
3
+ export declare class InMemoryKeystoreAdapter implements MajikKeyStorageAdapter {
4
+ private _store;
5
+ save(invoice: MajikKeyJSON): Promise<void>;
6
+ getById(id: string): Promise<MajikKeyJSON | null>;
7
+ list(): Promise<MajikKeyJSON[]>;
8
+ remove(id: string): Promise<boolean>;
9
+ clear(): Promise<void>;
10
+ count(): Promise<number>;
11
+ exists(id: string): Promise<boolean>;
12
+ bulkSave(invoices: MajikKeyJSON[]): Promise<void>;
13
+ bulkRemove(ids: string[]): Promise<void>;
14
+ }
@@ -0,0 +1,32 @@
1
+ export class InMemoryKeystoreAdapter {
2
+ _store = new Map();
3
+ async save(invoice) {
4
+ this._store.set(invoice.id, invoice);
5
+ }
6
+ async getById(id) {
7
+ return this._store.get(id) ?? null;
8
+ }
9
+ async list() {
10
+ return Array.from(this._store.values());
11
+ }
12
+ async remove(id) {
13
+ return this._store.delete(id);
14
+ }
15
+ async clear() {
16
+ this._store.clear();
17
+ }
18
+ async count() {
19
+ return this._store.size;
20
+ }
21
+ async exists(id) {
22
+ return this._store.has(id);
23
+ }
24
+ async bulkSave(invoices) {
25
+ for (const inv of invoices)
26
+ this._store.set(inv.id, inv);
27
+ }
28
+ async bulkRemove(ids) {
29
+ for (const id of ids)
30
+ this._store.delete(id);
31
+ }
32
+ }
@@ -0,0 +1,16 @@
1
+ import { MajikKeyJSON } from "@majikah/majik-key";
2
+ import { MajikKeyStorageAdapter } from "./_types";
3
+ import { SQLiteDatabase } from "../sql-db-manager";
4
+ export declare class SQLiteKeystoreAdapter implements MajikKeyStorageAdapter {
5
+ private db;
6
+ constructor(db: SQLiteDatabase);
7
+ save(key: MajikKeyJSON): Promise<void>;
8
+ getById(id: string): Promise<MajikKeyJSON | null>;
9
+ list(): Promise<MajikKeyJSON[]>;
10
+ remove(id: string): Promise<boolean>;
11
+ clear(): Promise<void>;
12
+ count(): Promise<number>;
13
+ exists(id: string): Promise<boolean>;
14
+ bulkSave(keys: MajikKeyJSON[]): Promise<void>;
15
+ bulkRemove(ids: string[]): Promise<void>;
16
+ }
@@ -0,0 +1,69 @@
1
+ export class SQLiteKeystoreAdapter {
2
+ db;
3
+ constructor(db) {
4
+ this.db = db;
5
+ }
6
+ async save(key) {
7
+ await this.db.run(`INSERT OR REPLACE INTO majik_keys
8
+ (id, json, timestamp, public_key)
9
+ VALUES (?, ?, ?, ?)`, [
10
+ key.id,
11
+ JSON.stringify(key),
12
+ key.timestamp ?? new Date().toISOString(),
13
+ key.publicKey,
14
+ ]);
15
+ }
16
+ async getById(id) {
17
+ const row = await this.db.get("SELECT json FROM majik_keys WHERE id = ?", [id]);
18
+ return row ? JSON.parse(row.json) : null;
19
+ }
20
+ async list() {
21
+ const rows = await this.db.all("SELECT json FROM majik_keys");
22
+ return rows.map((r) => JSON.parse(r.json));
23
+ }
24
+ async remove(id) {
25
+ const exists = await this.exists(id);
26
+ if (!exists)
27
+ return false;
28
+ await this.db.run("DELETE FROM majik_keys WHERE id = ?", [id]);
29
+ return true;
30
+ }
31
+ async clear() {
32
+ await this.db.run("DELETE FROM majik_keys");
33
+ }
34
+ async count() {
35
+ const row = await this.db.get("SELECT COUNT(*) as n FROM majik_keys");
36
+ return row?.n ?? 0;
37
+ }
38
+ async exists(id) {
39
+ const row = await this.db.get("SELECT 1 FROM majik_keys WHERE id = ?", [
40
+ id,
41
+ ]);
42
+ return !!row;
43
+ }
44
+ async bulkSave(keys) {
45
+ if (keys.length === 0)
46
+ return;
47
+ await this.db.transaction(async (tx) => {
48
+ for (const g of keys) {
49
+ await tx.run(`INSERT OR REPLACE INTO majik_keys
50
+ (id, json, timestamp, public_key)
51
+ VALUES (?, ?, ?, ?)`, [
52
+ g.id,
53
+ JSON.stringify(g),
54
+ g.timestamp ?? new Date().toISOString(),
55
+ g.publicKey,
56
+ ]);
57
+ }
58
+ });
59
+ }
60
+ async bulkRemove(ids) {
61
+ if (ids.length === 0)
62
+ return;
63
+ await this.db.transaction(async (tx) => {
64
+ for (const id of ids) {
65
+ await tx.run("DELETE FROM majik_keys WHERE id = ?", [id]);
66
+ }
67
+ });
68
+ }
69
+ }
@@ -0,0 +1,13 @@
1
+ export declare class SQLiteDatabase {
2
+ private worker;
3
+ constructor(worker: Worker);
4
+ private call;
5
+ run(sql: string, params?: any[]): Promise<void>;
6
+ get<T = any>(sql: string, params?: any[]): Promise<T | null>;
7
+ all<T = any>(sql: string, params?: any[]): Promise<T[]>;
8
+ exec(sql: string): Promise<void>;
9
+ optimize(): Promise<void>;
10
+ vacuum(): Promise<void>;
11
+ checkpoint(mode?: "PASSIVE" | "FULL"): Promise<void>;
12
+ transaction(fn: (tx: SQLiteDatabase) => Promise<void>): Promise<void>;
13
+ }
@@ -0,0 +1,59 @@
1
+ export class SQLiteDatabase {
2
+ worker;
3
+ constructor(worker) {
4
+ this.worker = worker;
5
+ }
6
+ call(message) {
7
+ const id = crypto.randomUUID();
8
+ return new Promise((resolve, reject) => {
9
+ const handler = (e) => {
10
+ if (e.data.id !== id)
11
+ return;
12
+ this.worker.removeEventListener("message", handler);
13
+ if (e.data.ok)
14
+ resolve(e.data.result);
15
+ else
16
+ reject(new Error(e.data.error));
17
+ };
18
+ this.worker.addEventListener("message", handler);
19
+ this.worker.postMessage({
20
+ ...message,
21
+ id,
22
+ });
23
+ });
24
+ }
25
+ async run(sql, params = []) {
26
+ await this.call({ type: "run", sql, params });
27
+ }
28
+ async get(sql, params = []) {
29
+ return this.call({ type: "get", sql, params });
30
+ }
31
+ async all(sql, params = []) {
32
+ return this.call({ type: "all", sql, params });
33
+ }
34
+ async exec(sql) {
35
+ await this.call({ type: "exec", sql });
36
+ }
37
+ async optimize() {
38
+ await this.run("PRAGMA optimize;");
39
+ await this.run("ANALYZE;");
40
+ await this.run("PRAGMA wal_checkpoint(FULL);");
41
+ }
42
+ async vacuum() {
43
+ await this.exec("VACUUM;");
44
+ }
45
+ async checkpoint(mode = "PASSIVE") {
46
+ await this.run(`PRAGMA wal_checkpoint(${mode});`);
47
+ }
48
+ async transaction(fn) {
49
+ await this.run("BEGIN");
50
+ try {
51
+ await fn(this);
52
+ await this.run("COMMIT");
53
+ }
54
+ catch (err) {
55
+ await this.run("ROLLBACK");
56
+ throw err;
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,10 @@
1
+ type MajikahSQLSchema = string;
2
+ export declare function buildSchemaSQL(schemas: MajikahSQLSchema[]): MajikahSQLSchema;
3
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_CLIENT_STATE: MajikahSQLSchema;
4
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_KEYS: MajikahSQLSchema;
5
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_CHATS: MajikahSQLSchema;
6
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_FILES: MajikahSQLSchema;
7
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_CONTACTS: MajikahSQLSchema;
8
+ export declare const MAJIKAH_SQL_SCHEMA_MAJIK_CONTACT_GROUPS: MajikahSQLSchema;
9
+ export declare const MAJIKAH_SQL_SCHEMA_FULL: MajikahSQLSchema;
10
+ export {};
@@ -0,0 +1,108 @@
1
+ function normalizeSQL(sql) {
2
+ return sql
3
+ .trim()
4
+ .replace(/\s+/g, " ") // collapse all whitespace
5
+ .toLowerCase();
6
+ }
7
+ export function buildSchemaSQL(schemas) {
8
+ const seen = new Set();
9
+ return schemas
10
+ .map((schema) => schema.trim())
11
+ .filter(Boolean)
12
+ .filter((schema) => {
13
+ const normalized = normalizeSQL(schema);
14
+ if (seen.has(normalized))
15
+ return false; // silently skip
16
+ seen.add(normalized);
17
+ return true;
18
+ })
19
+ .join("\n\n");
20
+ }
21
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_CLIENT_STATE = `
22
+ CREATE TABLE IF NOT EXISTS majik_client_state (
23
+ key TEXT PRIMARY KEY,
24
+ value TEXT NOT NULL,
25
+ updated_at TEXT DEFAULT (datetime('now'))
26
+ );
27
+ `;
28
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_KEYS = `
29
+ CREATE TABLE IF NOT EXISTS majik_keys (
30
+ id TEXT PRIMARY KEY,
31
+ json TEXT NOT NULL,
32
+ timestamp TEXT NOT NULL,
33
+ public_key TEXT NOT NULL
34
+ );
35
+
36
+ CREATE INDEX IF NOT EXISTS idx_majik_keys_timestamp
37
+ ON majik_keys(timestamp);
38
+
39
+ CREATE INDEX IF NOT EXISTS idx_majik_keys_public_key
40
+ ON majik_keys(public_key);
41
+ `;
42
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_CHATS = `
43
+ CREATE TABLE IF NOT EXISTS majik_message_chats (
44
+ id TEXT PRIMARY KEY,
45
+ json TEXT NOT NULL,
46
+ created_at TEXT NOT NULL,
47
+ source TEXT NOT NULL DEFAULT 'local'
48
+ CHECK(source IN ('local', 'cloud'))
49
+ );
50
+
51
+ CREATE INDEX IF NOT EXISTS idx_majik_message_chats_created_at
52
+ ON majik_message_chats(created_at);
53
+
54
+
55
+ CREATE INDEX IF NOT EXISTS idx_majik_message_chats_source
56
+ ON majik_message_chats(source);
57
+ `;
58
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_FILES = `
59
+ CREATE TABLE IF NOT EXISTS majik_message_files (
60
+ id TEXT PRIMARY KEY,
61
+ json TEXT NOT NULL,
62
+ created_at TEXT NOT NULL,
63
+ binary BLOB,
64
+ source TEXT NOT NULL DEFAULT 'local'
65
+ CHECK(source IN ('local', 'cloud'))
66
+ );
67
+
68
+ CREATE INDEX IF NOT EXISTS idx_majik_message_files_created_at
69
+ ON majik_message_files(created_at);
70
+
71
+
72
+ CREATE INDEX IF NOT EXISTS idx_majik_message_files_source
73
+ ON majik_message_files(source);
74
+ `;
75
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_CONTACTS = `
76
+ CREATE TABLE IF NOT EXISTS majik_contacts (
77
+ id TEXT PRIMARY KEY,
78
+ json TEXT NOT NULL,
79
+ fingerprint TEXT,
80
+ label TEXT,
81
+ created_at TEXT,
82
+ updated_at TEXT
83
+ );
84
+
85
+ CREATE INDEX IF NOT EXISTS idx_majik_contacts_created_at
86
+ ON majik_contacts(created_at);
87
+ `;
88
+ export const MAJIKAH_SQL_SCHEMA_MAJIK_CONTACT_GROUPS = `
89
+ CREATE TABLE IF NOT EXISTS majik_contact_groups (
90
+ id TEXT PRIMARY KEY,
91
+ json TEXT NOT NULL,
92
+ name TEXT,
93
+ created_at TEXT,
94
+ updated_at TEXT,
95
+ is_system INTEGER DEFAULT 0 CHECK(is_system IN (0,1))
96
+ );
97
+
98
+ CREATE INDEX IF NOT EXISTS idx_majik_contact_groups_created_at
99
+ ON majik_contact_groups(created_at);
100
+ `;
101
+ export const MAJIKAH_SQL_SCHEMA_FULL = buildSchemaSQL([
102
+ MAJIKAH_SQL_SCHEMA_MAJIK_CLIENT_STATE,
103
+ MAJIKAH_SQL_SCHEMA_MAJIK_KEYS,
104
+ MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_CHATS,
105
+ MAJIKAH_SQL_SCHEMA_MAJIK_CONTACTS,
106
+ MAJIKAH_SQL_SCHEMA_MAJIK_CONTACT_GROUPS,
107
+ MAJIKAH_SQL_SCHEMA_MAJIK_MESSAGE_FILES,
108
+ ]);
@@ -0,0 +1,14 @@
1
+ export type StorageSource = "local" | "cloud";
2
+ export interface MajikStorageAdapter<T extends {
3
+ id: string;
4
+ }> {
5
+ save(item: T, source?: StorageSource): Promise<void>;
6
+ getById(id: string, source?: StorageSource): Promise<T | null>;
7
+ list(source?: StorageSource): Promise<T[]>;
8
+ remove(id: string, source?: StorageSource): Promise<boolean>;
9
+ clear(source?: StorageSource): Promise<void>;
10
+ count(source?: StorageSource): Promise<number>;
11
+ exists(id: string, source?: StorageSource): Promise<boolean>;
12
+ bulkSave(items: T[], source?: StorageSource): Promise<void>;
13
+ bulkRemove(ids: string[], source?: StorageSource): Promise<void>;
14
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -5,13 +5,11 @@ export * from "./core/contacts/majik-contact-directory";
5
5
  export * from "./core/contacts/majik-contact-groups";
6
6
  export * from "./core/crypto/constants";
7
7
  export * from "./core/crypto/crypto-provider";
8
- export * from "./core/crypto/encryption-engine";
9
- export * from "./core/crypto/keystore";
10
8
  export * from "./core/messages/message-envelope";
11
9
  export * from "./core/messages/envelope-cache";
12
- export * from "./core/scanner/scanner-engine";
13
- export * from "./core/utils/APITranscoder";
14
10
  export * from "./core/utils/utilities";
11
+ export * from "./core/crypto/keystore-manager";
12
+ export * from "./core/storage";
15
13
  export * from "./core/database/chat/majik-message-chat";
16
14
  export type * from "./core/database/chat/types";
17
15
  export * from "./core/database/system/identity";
package/dist/index.js CHANGED
@@ -4,13 +4,11 @@ export * from "./core/contacts/majik-contact-directory";
4
4
  export * from "./core/contacts/majik-contact-groups";
5
5
  export * from "./core/crypto/constants";
6
6
  export * from "./core/crypto/crypto-provider";
7
- export * from "./core/crypto/encryption-engine";
8
- export * from "./core/crypto/keystore";
9
7
  export * from "./core/messages/message-envelope";
10
8
  export * from "./core/messages/envelope-cache";
11
- export * from "./core/scanner/scanner-engine";
12
- export * from "./core/utils/APITranscoder";
13
9
  export * from "./core/utils/utilities";
10
+ export * from "./core/crypto/keystore-manager";
11
+ export * from "./core/storage";
14
12
  export * from "./core/database/chat/majik-message-chat";
15
13
  export * from "./core/database/system/identity";
16
14
  export * from "./core/compressor/majik-compressor";