@diaryx/wasm 1.4.0-dev.a57c306 → 1.4.0-dev.dd1af96

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.
package/diaryx_wasm.d.ts CHANGED
@@ -182,11 +182,6 @@ export class DiaryxBackend {
182
182
  * This avoids JSON serialization overhead for better performance.
183
183
  */
184
184
  executeJs(command: any): Promise<any>;
185
- /**
186
- * Get the current configuration from root index frontmatter.
187
- * Config keys are stored as `diaryx_*` properties.
188
- */
189
- getConfig(): Promise<any>;
190
185
  /**
191
186
  * Check if this backend has native sync support.
192
187
  * Always false — sync is handled by the Extism sync plugin loaded at runtime.
@@ -238,11 +233,6 @@ export class DiaryxBackend {
238
233
  * Returns data as Uint8Array for efficient handling without base64 encoding.
239
234
  */
240
235
  readBinary(path: string): Promise<any>;
241
- /**
242
- * Save configuration to root index frontmatter.
243
- * Config keys are stored as `diaryx_*` properties.
244
- */
245
- saveConfig(config_js: any): Promise<any>;
246
236
  /**
247
237
  * No-op — CrdtFs is not used; sync handled by Extism plugin.
248
238
  */
@@ -388,12 +378,10 @@ export interface InitOutput {
388
378
  readonly diaryxbackend_eventSubscriberCount: (a: number) => number;
389
379
  readonly diaryxbackend_execute: (a: number, b: number, c: number) => any;
390
380
  readonly diaryxbackend_executeJs: (a: number, b: any) => any;
391
- readonly diaryxbackend_getConfig: (a: number) => any;
392
381
  readonly diaryxbackend_hasNativeSync: (a: number) => number;
393
382
  readonly diaryxbackend_offFileSystemEvent: (a: number, b: bigint) => number;
394
383
  readonly diaryxbackend_onFileSystemEvent: (a: number, b: any) => bigint;
395
384
  readonly diaryxbackend_readBinary: (a: number, b: number, c: number) => any;
396
- readonly diaryxbackend_saveConfig: (a: number, b: any) => any;
397
385
  readonly diaryxbackend_setCrdtEnabled: (a: number, b: number) => void;
398
386
  readonly diaryxbackend_writeBinary: (a: number, b: number, c: number, d: any) => any;
399
387
  readonly fsafilesystem_fromHandle: (a: any) => number;
@@ -406,17 +394,17 @@ export interface InitOutput {
406
394
  readonly today_formatted: (a: number, b: number) => [number, number];
407
395
  readonly init: () => void;
408
396
  readonly diaryxbackend_isCrdtEnabled: (a: number) => number;
409
- readonly __wbg_opfsfilesystem_free: (a: number, b: number) => void;
410
397
  readonly jsasyncfilesystem_new: (a: any) => number;
411
- readonly wasm_bindgen__closure__destroy__h4500db2d539387f0: (a: number, b: number) => void;
412
- readonly wasm_bindgen__closure__destroy__h383b907cd99501f0: (a: number, b: number) => void;
413
- readonly wasm_bindgen__closure__destroy__ha8e48983308a695a: (a: number, b: number) => void;
414
- readonly wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4: (a: number, b: number, c: any) => [number, number];
415
- readonly wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4_2: (a: number, b: number, c: any) => [number, number];
416
- readonly wasm_bindgen__convert__closures_____invoke__h8d091265fab4d12f: (a: number, b: number, c: any) => [number, number];
417
- readonly wasm_bindgen__convert__closures_____invoke__h8f90f75f1e0b9206: (a: number, b: number, c: any, d: any) => void;
418
- readonly wasm_bindgen__convert__closures_____invoke__hd3a0aee7c2a9d7e9: (a: number, b: number, c: any) => void;
419
- readonly wasm_bindgen__convert__closures_____invoke__h8c538aa099029b45: (a: number, b: number, c: any) => void;
398
+ readonly __wbg_opfsfilesystem_free: (a: number, b: number) => void;
399
+ readonly wasm_bindgen__closure__destroy__h356717fcf0bef3b6: (a: number, b: number) => void;
400
+ readonly wasm_bindgen__closure__destroy__h172a1002de1090db: (a: number, b: number) => void;
401
+ readonly wasm_bindgen__closure__destroy__h03c7db74cf95f03a: (a: number, b: number) => void;
402
+ readonly wasm_bindgen__convert__closures_____invoke__h800a0c6256652562: (a: number, b: number, c: any) => [number, number];
403
+ readonly wasm_bindgen__convert__closures_____invoke__h800a0c6256652562_2: (a: number, b: number, c: any) => [number, number];
404
+ readonly wasm_bindgen__convert__closures_____invoke__h82addf46b81c4b92: (a: number, b: number, c: any) => [number, number];
405
+ readonly wasm_bindgen__convert__closures_____invoke__h229fb34ceaba2930: (a: number, b: number, c: any, d: any) => void;
406
+ readonly wasm_bindgen__convert__closures_____invoke__h733716c67342e7af: (a: number, b: number, c: any) => void;
407
+ readonly wasm_bindgen__convert__closures_____invoke__hee1eb008cbb50be6: (a: number, b: number, c: any) => void;
420
408
  readonly __wbindgen_malloc: (a: number, b: number) => number;
421
409
  readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
422
410
  readonly __wbindgen_exn_store: (a: number) => void;
package/diaryx_wasm.js CHANGED
@@ -171,15 +171,6 @@ export class DiaryxBackend {
171
171
  const ret = wasm.diaryxbackend_executeJs(this.__wbg_ptr, command);
172
172
  return ret;
173
173
  }
174
- /**
175
- * Get the current configuration from root index frontmatter.
176
- * Config keys are stored as `diaryx_*` properties.
177
- * @returns {Promise<any>}
178
- */
179
- getConfig() {
180
- const ret = wasm.diaryxbackend_getConfig(this.__wbg_ptr);
181
- return ret;
182
- }
183
174
  /**
184
175
  * Check if this backend has native sync support.
185
176
  * Always false — sync is handled by the Extism sync plugin loaded at runtime.
@@ -256,16 +247,6 @@ export class DiaryxBackend {
256
247
  const ret = wasm.diaryxbackend_readBinary(this.__wbg_ptr, ptr0, len0);
257
248
  return ret;
258
249
  }
259
- /**
260
- * Save configuration to root index frontmatter.
261
- * Config keys are stored as `diaryx_*` properties.
262
- * @param {any} config_js
263
- * @returns {Promise<any>}
264
- */
265
- saveConfig(config_js) {
266
- const ret = wasm.diaryxbackend_saveConfig(this.__wbg_ptr, config_js);
267
- return ret;
268
- }
269
250
  /**
270
251
  * No-op — CrdtFs is not used; sync handled by Extism plugin.
271
252
  * @param {boolean} _enabled
@@ -1005,7 +986,7 @@ function __wbg_get_imports() {
1005
986
  const a = state0.a;
1006
987
  state0.a = 0;
1007
988
  try {
1008
- return wasm_bindgen__convert__closures_____invoke__h8f90f75f1e0b9206(a, state0.b, arg0, arg1);
989
+ return wasm_bindgen__convert__closures_____invoke__h229fb34ceaba2930(a, state0.b, arg0, arg1);
1009
990
  } finally {
1010
991
  state0.a = a;
1011
992
  }
@@ -1064,10 +1045,6 @@ function __wbg_get_imports() {
1064
1045
  const ret = OpfsFileSystem.__wrap(arg0);
1065
1046
  return ret;
1066
1047
  },
1067
- __wbg_parse_e9eddd2a82c706eb: function() { return handleError(function (arg0, arg1) {
1068
- const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
1069
- return ret;
1070
- }, arguments); },
1071
1048
  __wbg_preventDefault_25a229bfe5c510f8: function(arg0) {
1072
1049
  arg0.preventDefault();
1073
1050
  },
@@ -1159,10 +1136,6 @@ function __wbg_get_imports() {
1159
1136
  const ret = typeof window === 'undefined' ? null : window;
1160
1137
  return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
1161
1138
  },
1162
- __wbg_stringify_5ae93966a84901ac: function() { return handleError(function (arg0) {
1163
- const ret = JSON.stringify(arg0);
1164
- return ret;
1165
- }, arguments); },
1166
1139
  __wbg_target_7bc90f314634b37b: function(arg0) {
1167
1140
  const ret = arg0.target;
1168
1141
  return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
@@ -1200,27 +1173,27 @@ function __wbg_get_imports() {
1200
1173
  }, arguments); },
1201
1174
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
1202
1175
  // Cast intrinsic for `Closure(Closure { dtor_idx: 2, function: Function { arguments: [NamedExternref("Event")], shim_idx: 4, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1203
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h4500db2d539387f0, wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4);
1176
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h356717fcf0bef3b6, wasm_bindgen__convert__closures_____invoke__h800a0c6256652562);
1204
1177
  return ret;
1205
1178
  },
1206
1179
  __wbindgen_cast_0000000000000002: function(arg0, arg1) {
1207
1180
  // Cast intrinsic for `Closure(Closure { dtor_idx: 2, function: Function { arguments: [NamedExternref("IDBVersionChangeEvent")], shim_idx: 3, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1208
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h4500db2d539387f0, wasm_bindgen__convert__closures_____invoke__hd3a0aee7c2a9d7e9);
1181
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h356717fcf0bef3b6, wasm_bindgen__convert__closures_____invoke__h733716c67342e7af);
1209
1182
  return ret;
1210
1183
  },
1211
1184
  __wbindgen_cast_0000000000000003: function(arg0, arg1) {
1212
1185
  // Cast intrinsic for `Closure(Closure { dtor_idx: 2, function: Function { arguments: [NamedExternref("IteratorResult<any>")], shim_idx: 4, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1213
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h4500db2d539387f0, wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4_2);
1186
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h356717fcf0bef3b6, wasm_bindgen__convert__closures_____invoke__h800a0c6256652562_2);
1214
1187
  return ret;
1215
1188
  },
1216
1189
  __wbindgen_cast_0000000000000004: function(arg0, arg1) {
1217
- // Cast intrinsic for `Closure(Closure { dtor_idx: 570, function: Function { arguments: [NamedExternref("Event")], shim_idx: 571, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1218
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h383b907cd99501f0, wasm_bindgen__convert__closures_____invoke__h8c538aa099029b45);
1190
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 559, function: Function { arguments: [NamedExternref("Event")], shim_idx: 560, ret: Unit, inner_ret: Some(Unit) }, mutable: true }) -> Externref`.
1191
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h172a1002de1090db, wasm_bindgen__convert__closures_____invoke__hee1eb008cbb50be6);
1219
1192
  return ret;
1220
1193
  },
1221
1194
  __wbindgen_cast_0000000000000005: function(arg0, arg1) {
1222
- // Cast intrinsic for `Closure(Closure { dtor_idx: 587, function: Function { arguments: [Externref], shim_idx: 588, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1223
- const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__ha8e48983308a695a, wasm_bindgen__convert__closures_____invoke__h8d091265fab4d12f);
1195
+ // Cast intrinsic for `Closure(Closure { dtor_idx: 576, function: Function { arguments: [Externref], shim_idx: 577, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
1196
+ const ret = makeMutClosure(arg0, arg1, wasm.wasm_bindgen__closure__destroy__h03c7db74cf95f03a, wasm_bindgen__convert__closures_____invoke__h82addf46b81c4b92);
1224
1197
  return ret;
1225
1198
  },
1226
1199
  __wbindgen_cast_0000000000000006: function(arg0) {
@@ -1259,37 +1232,37 @@ function __wbg_get_imports() {
1259
1232
  };
1260
1233
  }
1261
1234
 
1262
- function wasm_bindgen__convert__closures_____invoke__hd3a0aee7c2a9d7e9(arg0, arg1, arg2) {
1263
- wasm.wasm_bindgen__convert__closures_____invoke__hd3a0aee7c2a9d7e9(arg0, arg1, arg2);
1235
+ function wasm_bindgen__convert__closures_____invoke__h733716c67342e7af(arg0, arg1, arg2) {
1236
+ wasm.wasm_bindgen__convert__closures_____invoke__h733716c67342e7af(arg0, arg1, arg2);
1264
1237
  }
1265
1238
 
1266
- function wasm_bindgen__convert__closures_____invoke__h8c538aa099029b45(arg0, arg1, arg2) {
1267
- wasm.wasm_bindgen__convert__closures_____invoke__h8c538aa099029b45(arg0, arg1, arg2);
1239
+ function wasm_bindgen__convert__closures_____invoke__hee1eb008cbb50be6(arg0, arg1, arg2) {
1240
+ wasm.wasm_bindgen__convert__closures_____invoke__hee1eb008cbb50be6(arg0, arg1, arg2);
1268
1241
  }
1269
1242
 
1270
- function wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4(arg0, arg1, arg2) {
1271
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4(arg0, arg1, arg2);
1243
+ function wasm_bindgen__convert__closures_____invoke__h800a0c6256652562(arg0, arg1, arg2) {
1244
+ const ret = wasm.wasm_bindgen__convert__closures_____invoke__h800a0c6256652562(arg0, arg1, arg2);
1272
1245
  if (ret[1]) {
1273
1246
  throw takeFromExternrefTable0(ret[0]);
1274
1247
  }
1275
1248
  }
1276
1249
 
1277
- function wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4_2(arg0, arg1, arg2) {
1278
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4_2(arg0, arg1, arg2);
1250
+ function wasm_bindgen__convert__closures_____invoke__h800a0c6256652562_2(arg0, arg1, arg2) {
1251
+ const ret = wasm.wasm_bindgen__convert__closures_____invoke__h800a0c6256652562_2(arg0, arg1, arg2);
1279
1252
  if (ret[1]) {
1280
1253
  throw takeFromExternrefTable0(ret[0]);
1281
1254
  }
1282
1255
  }
1283
1256
 
1284
- function wasm_bindgen__convert__closures_____invoke__h8d091265fab4d12f(arg0, arg1, arg2) {
1285
- const ret = wasm.wasm_bindgen__convert__closures_____invoke__h8d091265fab4d12f(arg0, arg1, arg2);
1257
+ function wasm_bindgen__convert__closures_____invoke__h82addf46b81c4b92(arg0, arg1, arg2) {
1258
+ const ret = wasm.wasm_bindgen__convert__closures_____invoke__h82addf46b81c4b92(arg0, arg1, arg2);
1286
1259
  if (ret[1]) {
1287
1260
  throw takeFromExternrefTable0(ret[0]);
1288
1261
  }
1289
1262
  }
1290
1263
 
1291
- function wasm_bindgen__convert__closures_____invoke__h8f90f75f1e0b9206(arg0, arg1, arg2, arg3) {
1292
- wasm.wasm_bindgen__convert__closures_____invoke__h8f90f75f1e0b9206(arg0, arg1, arg2, arg3);
1264
+ function wasm_bindgen__convert__closures_____invoke__h229fb34ceaba2930(arg0, arg1, arg2, arg3) {
1265
+ wasm.wasm_bindgen__convert__closures_____invoke__h229fb34ceaba2930(arg0, arg1, arg2, arg3);
1293
1266
  }
1294
1267
 
1295
1268
 
@@ -15,12 +15,10 @@ export const diaryxbackend_emitFileSystemEvent: (a: number, b: number, c: number
15
15
  export const diaryxbackend_eventSubscriberCount: (a: number) => number;
16
16
  export const diaryxbackend_execute: (a: number, b: number, c: number) => any;
17
17
  export const diaryxbackend_executeJs: (a: number, b: any) => any;
18
- export const diaryxbackend_getConfig: (a: number) => any;
19
18
  export const diaryxbackend_hasNativeSync: (a: number) => number;
20
19
  export const diaryxbackend_offFileSystemEvent: (a: number, b: bigint) => number;
21
20
  export const diaryxbackend_onFileSystemEvent: (a: number, b: any) => bigint;
22
21
  export const diaryxbackend_readBinary: (a: number, b: number, c: number) => any;
23
- export const diaryxbackend_saveConfig: (a: number, b: any) => any;
24
22
  export const diaryxbackend_setCrdtEnabled: (a: number, b: number) => void;
25
23
  export const diaryxbackend_writeBinary: (a: number, b: number, c: number, d: any) => any;
26
24
  export const fsafilesystem_fromHandle: (a: any) => number;
@@ -33,17 +31,17 @@ export const opfsfilesystem_createWithName: (a: number, b: number) => any;
33
31
  export const today_formatted: (a: number, b: number) => [number, number];
34
32
  export const init: () => void;
35
33
  export const diaryxbackend_isCrdtEnabled: (a: number) => number;
36
- export const __wbg_opfsfilesystem_free: (a: number, b: number) => void;
37
34
  export const jsasyncfilesystem_new: (a: any) => number;
38
- export const wasm_bindgen__closure__destroy__h4500db2d539387f0: (a: number, b: number) => void;
39
- export const wasm_bindgen__closure__destroy__h383b907cd99501f0: (a: number, b: number) => void;
40
- export const wasm_bindgen__closure__destroy__ha8e48983308a695a: (a: number, b: number) => void;
41
- export const wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4: (a: number, b: number, c: any) => [number, number];
42
- export const wasm_bindgen__convert__closures_____invoke__h815d350aae7569a4_2: (a: number, b: number, c: any) => [number, number];
43
- export const wasm_bindgen__convert__closures_____invoke__h8d091265fab4d12f: (a: number, b: number, c: any) => [number, number];
44
- export const wasm_bindgen__convert__closures_____invoke__h8f90f75f1e0b9206: (a: number, b: number, c: any, d: any) => void;
45
- export const wasm_bindgen__convert__closures_____invoke__hd3a0aee7c2a9d7e9: (a: number, b: number, c: any) => void;
46
- export const wasm_bindgen__convert__closures_____invoke__h8c538aa099029b45: (a: number, b: number, c: any) => void;
35
+ export const __wbg_opfsfilesystem_free: (a: number, b: number) => void;
36
+ export const wasm_bindgen__closure__destroy__h356717fcf0bef3b6: (a: number, b: number) => void;
37
+ export const wasm_bindgen__closure__destroy__h172a1002de1090db: (a: number, b: number) => void;
38
+ export const wasm_bindgen__closure__destroy__h03c7db74cf95f03a: (a: number, b: number) => void;
39
+ export const wasm_bindgen__convert__closures_____invoke__h800a0c6256652562: (a: number, b: number, c: any) => [number, number];
40
+ export const wasm_bindgen__convert__closures_____invoke__h800a0c6256652562_2: (a: number, b: number, c: any) => [number, number];
41
+ export const wasm_bindgen__convert__closures_____invoke__h82addf46b81c4b92: (a: number, b: number, c: any) => [number, number];
42
+ export const wasm_bindgen__convert__closures_____invoke__h229fb34ceaba2930: (a: number, b: number, c: any, d: any) => void;
43
+ export const wasm_bindgen__convert__closures_____invoke__h733716c67342e7af: (a: number, b: number, c: any) => void;
44
+ export const wasm_bindgen__convert__closures_____invoke__hee1eb008cbb50be6: (a: number, b: number, c: any) => void;
47
45
  export const __wbindgen_malloc: (a: number, b: number) => number;
48
46
  export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
49
47
  export const __wbindgen_exn_store: (a: number) => void;
package/package.json CHANGED
@@ -1,22 +1,17 @@
1
1
  {
2
2
  "name": "@diaryx/wasm",
3
3
  "type": "module",
4
- "description": "WebAssembly bindings for Diaryx core functionality",
5
- "version": "1.4.0-dev.a57c306",
6
- "license": "SEE LICENSE IN ../../LICENSE.md",
7
- "repository": {
8
- "type": "git",
9
- "url": "https://github.com/diaryx-org/diaryx"
10
- },
4
+ "version": "1.4.0-dev.dd1af96",
5
+ "main": "diaryx_wasm.js",
6
+ "types": "diaryx_wasm.d.ts",
11
7
  "files": [
12
8
  "diaryx_wasm.js",
13
9
  "diaryx_wasm_bg.js",
14
10
  "diaryx_wasm.d.ts",
15
11
  "diaryx_wasm_bg.wasm.d.ts"
16
12
  ],
17
- "main": "diaryx_wasm.js",
18
- "types": "diaryx_wasm.d.ts",
19
- "sideEffects": [
20
- "./snippets/*"
21
- ]
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/diaryx-org/diaryx"
16
+ }
22
17
  }
package/README.md DELETED
@@ -1,425 +0,0 @@
1
- ---
2
- title: diaryx_wasm
3
- description: WASM bindings for diaryx_core
4
- part_of: '[README](/crates/README.md)'
5
- audience:
6
- - developers
7
- contents:
8
- - '[README](/crates/diaryx_wasm/src/README.md)'
9
- attachments:
10
- - '[Cargo.toml](/crates/diaryx_wasm/Cargo.toml)'
11
- - '[build.rs](/crates/diaryx_wasm/build.rs)'
12
- exclude:
13
- - '*.lock'
14
- - '*.db'
15
- - pkg/**
16
- ---
17
- # diaryx_wasm
18
-
19
- WebAssembly bindings for `diaryx_core`, used by the web frontend in `apps/web`.
20
-
21
- ## Building
22
-
23
- To build the WebAssembly module:
24
-
25
- ```bash
26
- wasm-pack build --target web --out-dir ../../apps/web/src/lib/wasm
27
- ```
28
-
29
- ## Testing
30
-
31
- Run browser filesystem integration tests (wasm + browser):
32
-
33
- ```bash
34
- nix develop -c wasm-pack test --headless --chrome crates/diaryx_wasm
35
- ```
36
-
37
- Current filesystem test suites live in:
38
-
39
- - `crates/diaryx_wasm/tests/opfs_fs.rs`
40
- - `crates/diaryx_wasm/tests/fs_trait_parity.rs`
41
-
42
- `fs_trait_parity.rs` runs the same contract checks across:
43
-
44
- - `OpfsFileSystem`
45
- - `IndexedDbFileSystem`
46
- - `FsaFileSystem`
47
-
48
- ## Architecture
49
-
50
- `diaryx_wasm` depends only on `diaryx_core`. The main entry point is `DiaryxBackend`,
51
- which provides a unified command API (`execute()`/`executeJs()`) backed by native
52
- browser storage (OPFS, IndexedDB, File System Access API).
53
-
54
- Sync and publish functionality are provided by Extism guest plugins
55
- (`diaryx_sync.wasm`, `diaryx_publish.wasm`) loaded at runtime by the browser
56
- plugin manager. CRDT commands are routed to the sync plugin via the frontend
57
- command router before reaching the WASM backend.
58
-
59
- ### Storage Backends
60
-
61
- Unlike the CLI and Tauri backends which use `RealFileSystem` (native filesystem),
62
- the WASM backend supports several browser storage backends:
63
-
64
- - **OPFS** — Origin Private File System (default)
65
- - **IndexedDB** — IndexedDB-based filesystem
66
- - **File System Access** — User-selected directory on the real filesystem
67
- - **In-Memory** — Used for guest mode in share sessions
68
- - **JavaScript** — Bridged to external JS filesystem (Node.js, Obsidian, Electron)
69
-
70
- ## API Reference
71
-
72
- ### DiaryxValidation
73
-
74
- Validates workspace link integrity and fixes issues.
75
-
76
- ```javascript
77
- import init, { DiaryxValidation } from "./wasm/diaryx_wasm.js";
78
-
79
- await init();
80
- const validation = new DiaryxValidation();
81
-
82
- // Validate entire workspace
83
- const result = validation.validate("workspace");
84
- console.log(`Checked ${result.files_checked} files`);
85
- console.log(`Errors: ${result.errors.length}`);
86
- console.log(`Warnings: ${result.warnings.length}`);
87
-
88
- // Validate single file
89
- const fileResult = validation.validate_file("workspace/notes/my-note.md");
90
-
91
- // Fix all issues
92
- const fixSummary = validation.fix_all(result);
93
- console.log(
94
- `Fixed: ${fixSummary.total_fixed}, Failed: ${fixSummary.total_failed}`,
95
- );
96
-
97
- // Fix individual issues
98
- validation.fix_broken_part_of("workspace/broken.md");
99
- validation.fix_broken_contents_ref("workspace/index.md", "missing.md");
100
- validation.fix_unlisted_file("workspace/index.md", "workspace/unlisted.md");
101
- validation.fix_missing_part_of("workspace/orphan.md", "workspace/index.md");
102
- ```
103
-
104
- #### Validation Errors
105
-
106
- - `BrokenPartOf` - `part_of` points to non-existent file
107
- - `BrokenContentsRef` - `contents` references non-existent file
108
- - `BrokenAttachment` - `attachments` references non-existent file
109
-
110
- #### Validation Warnings
111
-
112
- - `OrphanFile` - Markdown file not in any index's `contents`
113
- - `UnlinkedEntry` - File/directory not in contents hierarchy
114
- - `CircularReference` - Circular reference in hierarchy
115
- - `NonPortablePath` - Path contains absolute or `.`/`..` components
116
- - `MultipleIndexes` - Multiple index files in same directory
117
- - `OrphanBinaryFile` - Binary file not in any index's `attachments`
118
- - `MissingPartOf` - Non-index file has no `part_of`
119
-
120
- #### Exclude Patterns
121
-
122
- Use `exclude` in frontmatter to suppress warnings. Patterns inherit up the `part_of` chain:
123
-
124
- ```yaml
125
- exclude:
126
- - "LICENSE.md"
127
- - "*.lock"
128
- ```
129
-
130
- ### Legacy API
131
-
132
- For backwards compatibility, standalone functions are also exported:
133
-
134
- ```javascript
135
- import {
136
- validate_workspace,
137
- validate_file,
138
- fix_all_validation_issues,
139
- } from "./wasm/diaryx_wasm.js";
140
-
141
- const result = validate_workspace("workspace");
142
- const fixSummary = fix_all_validation_issues(result);
143
- ```
144
-
145
- ### DiaryxAsyncFilesystem
146
-
147
- Async filesystem operations that return JavaScript Promises. This is useful for consistent async/await patterns in JavaScript and future integration with truly async storage (e.g., IndexedDB).
148
-
149
- ```javascript
150
- import init, { DiaryxAsyncFilesystem } from "./wasm/diaryx_wasm.js";
151
-
152
- await init();
153
- const asyncFs = new DiaryxAsyncFilesystem();
154
-
155
- // All methods return Promises
156
- const content = await asyncFs.read_file("workspace/README.md");
157
- await asyncFs.write_file("workspace/new.md", "# New File");
158
- const exists = await asyncFs.file_exists("workspace/new.md");
159
-
160
- // Directory operations
161
- await asyncFs.create_dir_all("workspace/notes/2024");
162
- const isDir = await asyncFs.is_dir("workspace/notes");
163
-
164
- // List files
165
- const mdFiles = await asyncFs.list_md_files("workspace");
166
- console.log(`Found ${mdFiles.count} markdown files:`, mdFiles.files);
167
-
168
- // Recursive listing
169
- const allMd = await asyncFs.list_md_files_recursive("workspace");
170
- const allFiles = await asyncFs.list_all_files_recursive("workspace");
171
-
172
- // Binary file operations
173
- const data = await asyncFs.read_binary("workspace/image.png");
174
- await asyncFs.write_binary("workspace/copy.png", data);
175
-
176
- // Bulk operations for IndexedDB sync
177
- const backupData = await asyncFs.get_backup_data();
178
- // ... persist to IndexedDB ...
179
- await asyncFs.restore_from_backup(backupData);
180
-
181
- // Load/export files
182
- await asyncFs.load_files([
183
- ["workspace/README.md", "# Hello"],
184
- ["workspace/notes.md", "# Notes"],
185
- ]);
186
- const entries = await asyncFs.export_files();
187
-
188
- // Clear filesystem
189
- await asyncFs.clear();
190
- ```
191
-
192
- #### Async vs Sync Filesystem
193
-
194
- - `DiaryxFilesystem` - Synchronous methods, returns values directly
195
- - `DiaryxAsyncFilesystem` - All methods return Promises
196
-
197
- While the underlying `InMemoryFileSystem` is synchronous, `DiaryxAsyncFilesystem` provides a Promise-based API that:
198
-
199
- 1. Enables consistent async/await patterns in JavaScript
200
- 2. Allows for future integration with truly async operations
201
- 3. Works well with JavaScript's event loop
202
-
203
- ### Diaryx (Command API with CRDT)
204
-
205
- The `Diaryx` class provides a unified command API that includes CRDT operations for real-time collaboration. Commands are executed via `execute()` (returns typed result) or `executeJs()` (returns JS-friendly object).
206
-
207
- ```javascript
208
- import init, { Diaryx } from "./wasm/diaryx_wasm.js";
209
-
210
- await init();
211
- const diaryx = new Diaryx();
212
-
213
- // All CRDT commands use the execute/executeJs pattern
214
- ```
215
-
216
- #### CRDT Workspace Operations
217
-
218
- ```javascript
219
- // Set file metadata in the CRDT workspace
220
- await diaryx.executeJs({
221
- type: "SetFileMetadata",
222
- path: "notes/my-note.md",
223
- metadata: {
224
- title: "My Note",
225
- audience: ["public"],
226
- part_of: "README.md",
227
- },
228
- });
229
-
230
- // Get file metadata
231
- const result = await diaryx.executeJs({
232
- type: "GetFileMetadata",
233
- path: "notes/my-note.md",
234
- });
235
- console.log(result.metadata); // { title: "My Note", ... }
236
-
237
- // List all files in workspace
238
- const files = await diaryx.executeJs({ type: "ListFiles" });
239
- console.log(files.files); // ["notes/my-note.md", ...]
240
-
241
- // Remove a file from workspace
242
- await diaryx.executeJs({
243
- type: "RemoveFile",
244
- path: "notes/my-note.md",
245
- });
246
- ```
247
-
248
- #### CRDT Body Document Operations
249
-
250
- ```javascript
251
- // Set document body content
252
- await diaryx.executeJs({
253
- type: "SetBody",
254
- path: "notes/my-note.md",
255
- content: "# Hello World\n\nThis is my note.",
256
- });
257
-
258
- // Get document body
259
- const body = await diaryx.executeJs({
260
- type: "GetBody",
261
- path: "notes/my-note.md",
262
- });
263
- console.log(body.content);
264
-
265
- // Insert text at position (collaborative editing)
266
- await diaryx.executeJs({
267
- type: "InsertAt",
268
- path: "notes/my-note.md",
269
- position: 0,
270
- text: "Prefix: ",
271
- });
272
-
273
- // Delete text range
274
- await diaryx.executeJs({
275
- type: "DeleteRange",
276
- path: "notes/my-note.md",
277
- start: 0,
278
- end: 8,
279
- });
280
- ```
281
-
282
- #### CRDT Sync Operations
283
-
284
- For synchronizing with Hocuspocus or other Y.js-compatible servers:
285
-
286
- ```javascript
287
- // Get sync state (state vector) for initial handshake
288
- const syncState = await diaryx.executeJs({
289
- type: "GetSyncState",
290
- doc_type: "workspace", // or "body"
291
- doc_name: null, // required for "body" type
292
- });
293
- const stateVector = syncState.state_vector; // Uint8Array
294
-
295
- // Apply remote update from server
296
- await diaryx.executeJs({
297
- type: "ApplyRemoteUpdate",
298
- doc_type: "workspace",
299
- doc_name: null,
300
- update: remoteUpdateBytes, // Uint8Array from WebSocket
301
- });
302
-
303
- // Encode full state to send to server
304
- const state = await diaryx.executeJs({
305
- type: "EncodeState",
306
- doc_type: "workspace",
307
- doc_name: null,
308
- });
309
- sendToServer(state.state); // Uint8Array
310
-
311
- // Encode incremental update since a state vector
312
- const diff = await diaryx.executeJs({
313
- type: "EncodeStateAsUpdate",
314
- doc_type: "workspace",
315
- doc_name: null,
316
- state_vector: remoteStateVector, // Uint8Array
317
- });
318
- sendToServer(diff.update); // Uint8Array
319
- ```
320
-
321
- #### Version History
322
-
323
- ```javascript
324
- // Get version history for a document
325
- const history = await diaryx.executeJs({
326
- type: "GetHistory",
327
- doc_type: "workspace", // or "body"
328
- doc_name: null, // required for "body" type
329
- });
330
-
331
- for (const entry of history.entries) {
332
- console.log(`Version ${entry.version} at ${entry.timestamp}`);
333
- console.log(` Origin: ${entry.origin}`); // "local" or "remote"
334
- console.log(` Size: ${entry.update.length} bytes`);
335
- }
336
-
337
- // Restore to a specific version (time travel)
338
- await diaryx.executeJs({
339
- type: "RestoreToVersion",
340
- doc_type: "workspace",
341
- doc_name: null,
342
- version: 5,
343
- });
344
- ```
345
-
346
- #### Document Types
347
-
348
- CRDT operations use `doc_type` to specify which document to operate on:
349
-
350
-
351
- | doc_type | doc_name | Description |
352
- | ----------- | --------- | ------------------------------------------ |
353
- | `workspace` | `null` | The workspace file hierarchy metadata |
354
- | `body` | file path | Per-file body content (e.g., `notes/a.md`) |
355
-
356
-
357
- ## Node.js / Obsidian / Electron Usage
358
-
359
- The `@diaryx/wasm-node` npm package is a build of this crate without browser-specific storage backends. It's published automatically by CI and works in any JavaScript environment that supports WebAssembly.
360
-
361
- ### Setup
362
-
363
- ```javascript
364
- import init, { DiaryxBackend } from '@diaryx/wasm-node';
365
- import fs from 'fs';
366
-
367
- // Load WASM binary and initialize
368
- const wasmPath = new URL('./diaryx_wasm_bg.wasm', import.meta.url);
369
- await init(fs.readFileSync(wasmPath));
370
-
371
- // Create backend with JavaScript filesystem callbacks
372
- const backend = DiaryxBackend.createFromJsFileSystem({
373
- readToString: (path) => fs.promises.readFile(path, 'utf8'),
374
- writeFile: (path, content) => fs.promises.writeFile(path, content),
375
- exists: (path) => fs.promises.access(path).then(() => true).catch(() => false),
376
- isDir: (path) => fs.promises.stat(path).then(s => s.isDirectory()).catch(() => false),
377
- listFiles: (dir) => fs.promises.readdir(dir),
378
- listMdFiles: (dir) => fs.promises.readdir(dir).then(f => f.filter(n => n.endsWith('.md'))),
379
- createDirAll: (path) => fs.promises.mkdir(path, { recursive: true }),
380
- moveFile: (from, to) => fs.promises.rename(from, to),
381
- deleteFile: (path) => fs.promises.unlink(path),
382
- readBinary: (path) => fs.promises.readFile(path),
383
- writeBinary: (path, data) => fs.promises.writeFile(path, data),
384
- });
385
- ```
386
-
387
- ### Obsidian Plugin Integration
388
-
389
- For Obsidian plugins, bridge the Vault adapter API:
390
-
391
- ```javascript
392
- const backend = DiaryxBackend.createFromJsFileSystem({
393
- readToString: (path) => app.vault.adapter.read(path),
394
- writeFile: (path, content) => app.vault.adapter.write(path, content),
395
- exists: (path) => app.vault.adapter.exists(path),
396
- isDir: (path) => app.vault.adapter.stat(path).then(s => s?.type === 'folder'),
397
- listFiles: (dir) => app.vault.adapter.list(dir).then(r => [...r.files, ...r.folders]),
398
- listMdFiles: (dir) => app.vault.adapter.list(dir).then(r => r.files.filter(f => f.endsWith('.md'))),
399
- createDirAll: (path) => app.vault.adapter.mkdir(path),
400
- moveFile: (from, to) => app.vault.adapter.rename(from, to),
401
- deleteFile: (path) => app.vault.adapter.remove(path),
402
- readBinary: (path) => app.vault.adapter.readBinary(path),
403
- writeBinary: (path, data) => app.vault.adapter.writeBinary(path, data),
404
- });
405
- ```
406
-
407
- ### Reacting to External File Moves
408
-
409
- When an external tool (Obsidian, VS Code, etc.) has already moved a file, use `SyncMoveMetadata` to update the workspace hierarchy metadata without re-doing the filesystem move:
410
-
411
- ```javascript
412
- // Obsidian fires this after a file is moved/renamed
413
- app.vault.on('rename', async (file, oldPath) => {
414
- await backend.executeJs({
415
- type: 'SyncMoveMetadata',
416
- params: { old_path: oldPath, new_path: file.path }
417
- });
418
- });
419
- ```
420
-
421
- This updates `contents` in the old and new parent indexes and `part_of` in the moved file.
422
-
423
- ## Error Handling
424
-
425
- All methods return `Result<T, JsValue>` for JavaScript interop. Errors are converted to JavaScript exceptions with descriptive messages.