hyperbook 0.84.2 → 0.84.4

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.
@@ -29,145 +29,13 @@ store.version(2).stores({
29
29
  learningmap: `id,nodes,x,y,zoom`,
30
30
  textinput: `id,text`,
31
31
  custom: `id,payload`,
32
+ onlineide: `scriptId,script`,
33
+ sqlideScripts: `scriptId,script`,
34
+ sqlideDatabases: `databaseId,database`,
32
35
  multievent: `id,state`,
33
36
  typst: `id,code`,
34
37
  });
35
38
 
36
- /**
37
- * Read all data from an external IndexedDB database using the raw API.
38
- * Returns a Dexie-export-compatible object, or null if the DB doesn't exist.
39
- */
40
- function exportExternalDB(dbName) {
41
- return new Promise((resolve) => {
42
- const request = indexedDB.open(dbName);
43
- request.onerror = () => resolve(null);
44
- request.onsuccess = (event) => {
45
- const db = event.target.result;
46
- const storeNames = Array.from(db.objectStoreNames);
47
- if (storeNames.length === 0) {
48
- db.close();
49
- resolve(null);
50
- return;
51
- }
52
- const result = {
53
- formatName: "dexie",
54
- formatVersion: 1,
55
- data: {
56
- databaseName: dbName,
57
- databaseVersion: db.version,
58
- tables: [],
59
- },
60
- };
61
- const tx = db.transaction(storeNames, "readonly");
62
- let pending = storeNames.length;
63
- storeNames.forEach((name) => {
64
- const objectStore = tx.objectStore(name);
65
- const tableInfo = {
66
- name: name,
67
- schema: objectStore.keyPath ? `${objectStore.keyPath}` : "++id",
68
- rowCount: 0,
69
- rows: [],
70
- };
71
- const cursorReq = objectStore.openCursor();
72
- cursorReq.onsuccess = (e) => {
73
- const cursor = e.target.result;
74
- if (cursor) {
75
- tableInfo.rows.push(cursor.value);
76
- cursor.continue();
77
- } else {
78
- tableInfo.rowCount = tableInfo.rows.length;
79
- result.data.tables.push(tableInfo);
80
- pending--;
81
- if (pending === 0) {
82
- db.close();
83
- resolve(result);
84
- }
85
- }
86
- };
87
- cursorReq.onerror = () => {
88
- pending--;
89
- if (pending === 0) {
90
- db.close();
91
- resolve(result);
92
- }
93
- };
94
- });
95
- };
96
- });
97
- }
98
-
99
- /**
100
- * Import data into an external IndexedDB database using the raw API.
101
- * Accepts a Dexie-export-compatible object. Clears existing data before importing.
102
- */
103
- function importExternalDB(dbName, exportData) {
104
- return new Promise((resolve, reject) => {
105
- const tables = exportData?.data?.tables;
106
- if (!tables || tables.length === 0) { resolve(); return; }
107
-
108
- // Determine the version the external tool uses (keep it in sync)
109
- const request = indexedDB.open(dbName);
110
- request.onerror = () => reject(request.error);
111
-
112
- request.onupgradeneeded = (event) => {
113
- // DB didn't exist yet — create the object stores from the export data
114
- const db = event.target.result;
115
- tables.forEach((table) => {
116
- if (!db.objectStoreNames.contains(table.name)) {
117
- const keyPath = table.schema && !table.schema.startsWith('++')
118
- ? table.schema.split(',')[0].trim()
119
- : null;
120
- db.createObjectStore(table.name, keyPath ? { keyPath } : { autoIncrement: true });
121
- }
122
- });
123
- };
124
-
125
- request.onsuccess = (event) => {
126
- const db = event.target.result;
127
- const storeNames = tables
128
- .map((t) => t.name)
129
- .filter((n) => db.objectStoreNames.contains(n));
130
- if (storeNames.length === 0) { db.close(); resolve(); return; }
131
-
132
- const tx = db.transaction(storeNames, "readwrite");
133
- // Clear then re-populate each store
134
- storeNames.forEach((name) => {
135
- const objectStore = tx.objectStore(name);
136
- objectStore.clear();
137
- const table = tables.find((t) => t.name === name);
138
- if (table && table.rows) {
139
- table.rows.forEach((row) => objectStore.put(row));
140
- }
141
- });
142
- tx.oncomplete = () => { db.close(); resolve(); };
143
- tx.onerror = () => { db.close(); reject(tx.error); };
144
- };
145
- });
146
- }
147
-
148
- /**
149
- * Clear all tables in an external IndexedDB database using the raw API.
150
- */
151
- function clearExternalDB(dbName) {
152
- return new Promise((resolve) => {
153
- const request = indexedDB.open(dbName);
154
- request.onerror = () => resolve();
155
- request.onsuccess = (event) => {
156
- const db = event.target.result;
157
- const storeNames = Array.from(db.objectStoreNames);
158
- if (storeNames.length === 0) {
159
- db.close();
160
- resolve();
161
- return;
162
- }
163
- const tx = db.transaction(storeNames, "readwrite");
164
- storeNames.forEach((name) => tx.objectStore(name).clear());
165
- tx.oncomplete = () => { db.close(); resolve(); };
166
- tx.onerror = () => { db.close(); resolve(); };
167
- };
168
- });
169
- }
170
-
171
39
  const initStore = async () => {
172
40
  store.currentState.put({
173
41
  id: 1,
@@ -200,16 +68,12 @@ initStore();
200
68
 
201
69
  async function hyperbookExport() {
202
70
  const hyperbook = await store.export({ prettyJson: true });
203
- const sqlIde = await exportExternalDB('SQL-IDE');
204
- const learnJ = await exportExternalDB('LearnJ');
205
71
 
206
72
  const data = {
207
73
  version: 1,
208
74
  origin: window.location.origin,
209
75
  data: {
210
76
  hyperbook: JSON.parse(await hyperbook.text()),
211
- sqlIde: sqlIde || {},
212
- learnJ: learnJ || {},
213
77
  },
214
78
  };
215
79
 
@@ -236,8 +100,15 @@ async function hyperbookReset() {
236
100
  }
237
101
 
238
102
  clearTable(store);
239
- await clearExternalDB('LearnJ');
240
- await clearExternalDB('SQL-IDE');
103
+
104
+ // Send empty snapshot to cloud
105
+ if (window.hyperbook && window.hyperbook.cloud) {
106
+ try {
107
+ await window.hyperbook.cloud.sendSnapshot();
108
+ } catch (e) {
109
+ console.error("Failed to sync reset to cloud:", e);
110
+ }
111
+ }
241
112
 
242
113
  alert(i18n.get("store-reset-sucessful"));
243
114
  window.location.reload();
@@ -269,18 +140,21 @@ async function hyperbookImport() {
269
140
  return;
270
141
  }
271
142
 
272
- const { hyperbook, sqlIde, learnJ } = data.data;
143
+ const { hyperbook } = data.data;
273
144
 
274
145
  const hyperbookBlob = new Blob([JSON.stringify(hyperbook)], {
275
146
  type: "application/json",
276
147
  });
277
148
 
278
149
  await store.import(hyperbookBlob, { clearTablesBeforeImport: true });
279
- if (sqlIde) {
280
- await importExternalDB('SQL-IDE', sqlIde);
281
- }
282
- if (learnJ) {
283
- await importExternalDB('LearnJ', learnJ);
150
+
151
+ // Send full snapshot to cloud after import
152
+ if (window.hyperbook && window.hyperbook.cloud) {
153
+ try {
154
+ await window.hyperbook.cloud.sendSnapshot();
155
+ } catch (e) {
156
+ console.error("Failed to sync import to cloud:", e);
157
+ }
284
158
  }
285
159
 
286
160
  alert(i18n.get("store-import-sucessful"));