wao 0.6.1 → 0.6.2

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/cjs/aoconnect.js CHANGED
@@ -11,7 +11,6 @@ var _base64url = _interopRequireDefault(require("base64url"));
11
11
  var _utils = require("./utils.js");
12
12
  var _armem = _interopRequireDefault(require("./armem.js"));
13
13
  var _weavedrive = _interopRequireDefault(require("./weavedrive.js"));
14
- var _kv = _interopRequireDefault(require("./kv.js"));
15
14
  var _aoLoader = _interopRequireDefault(require("@permaweb/ao-loader"));
16
15
  var _fs = require("fs");
17
16
  var _path = require("path");
@@ -39,9 +38,12 @@ function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" !=
39
38
  function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
40
39
  var pkg = (_WarpArBundles$defaul = WarpArBundles["default"]) !== null && _WarpArBundles$defaul !== void 0 ? _WarpArBundles$defaul : WarpArBundles;
41
40
  var DataItem = pkg.DataItem;
42
- var connect = exports.connect = function connect(mem) {
41
+ var connect = exports.connect = function connect(mem, _ref) {
43
42
  var _mem;
44
- var log = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
43
+ var _ref$log = _ref.log,
44
+ log = _ref$log === void 0 ? false : _ref$log,
45
+ _ref$extensions = _ref.extensions,
46
+ extensions = _ref$extensions === void 0 ? {} : _ref$extensions;
45
47
  var isMem = ((_mem = mem) === null || _mem === void 0 ? void 0 : _mem.__type__) === "mem";
46
48
  if (!isMem) {
47
49
  var _mem2;
@@ -56,18 +58,18 @@ var connect = exports.connect = function connect(mem) {
56
58
  mem: mem,
57
59
  log: log
58
60
  });
59
- var WeaveDrive = new _weavedrive["default"](ar).drive;
60
- var KV = new _kv["default"](ar).kv;
61
+ for (var k in extensions) extensions[k] = new extensions[k](ar).ext;
62
+ extensions.WeaveDrive = new _weavedrive["default"](ar).ext;
61
63
  var transform = function transform(input) {
62
64
  var _input$Tags;
63
65
  var output = {
64
66
  Tags: []
65
67
  };
66
68
  if (input.Data) output.Data = input.Data;
67
- Object.entries(input).forEach(function (_ref) {
68
- var _ref2 = _slicedToArray(_ref, 2),
69
- key = _ref2[0],
70
- value = _ref2[1];
69
+ Object.entries(input).forEach(function (_ref2) {
70
+ var _ref3 = _slicedToArray(_ref2, 2),
71
+ key = _ref3[0],
72
+ value = _ref3[1];
71
73
  if (key !== "Data" && key !== "Tags" && typeof value === "string") {
72
74
  output.Tags.push({
73
75
  name: key,
@@ -103,14 +105,14 @@ var connect = exports.connect = function connect(mem) {
103
105
  Tags: Tags !== null && Tags !== void 0 && Tags.length ? Tags : []
104
106
  };
105
107
  };
106
- var genEnv = function genEnv(_ref3) {
107
- var pid = _ref3.pid,
108
- _ref3$owner = _ref3.owner,
109
- owner = _ref3$owner === void 0 ? "" : _ref3$owner,
110
- _ref3$module = _ref3.module,
111
- module = _ref3$module === void 0 ? "" : _ref3$module,
112
- _ref3$auth = _ref3.auth,
113
- auth = _ref3$auth === void 0 ? "" : _ref3$auth;
108
+ var genEnv = function genEnv(_ref4) {
109
+ var pid = _ref4.pid,
110
+ _ref4$owner = _ref4.owner,
111
+ owner = _ref4$owner === void 0 ? "" : _ref4$owner,
112
+ _ref4$module = _ref4.module,
113
+ module = _ref4$module === void 0 ? "" : _ref4$module,
114
+ _ref4$auth = _ref4.auth,
115
+ auth = _ref4$auth === void 0 ? "" : _ref4$auth;
114
116
  return {
115
117
  Process: {
116
118
  Id: pid,
@@ -145,7 +147,7 @@ var connect = exports.connect = function connect(mem) {
145
147
  };
146
148
  };
147
149
  var spawn = /*#__PURE__*/function () {
148
- var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
150
+ var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
149
151
  var _opt$module, _mem$wasms$mod, _format, _opt$tags, _opt$tags2;
150
152
  var opt,
151
153
  mod,
@@ -165,7 +167,6 @@ var connect = exports.connect = function connect(mem) {
165
167
  __tags,
166
168
  now,
167
169
  t,
168
- wd,
169
170
  handle,
170
171
  _tags,
171
172
  res,
@@ -184,7 +185,7 @@ var connect = exports.connect = function connect(mem) {
184
185
  unit,
185
186
  _int,
186
187
  cronTags,
187
- k,
188
+ _k,
188
189
  _args = arguments;
189
190
  return _regeneratorRuntime().wrap(function _callee$(_context) {
190
191
  while (1) switch (_context.prev = _context.next) {
@@ -274,16 +275,15 @@ var connect = exports.connect = function connect(mem) {
274
275
  case 33:
275
276
  now = Date.now;
276
277
  t = (0, _utils.tags)(opt.tags);
277
- wd = t.Extension === "KV" ? KV : WeaveDrive;
278
- _context.next = 38;
278
+ _context.next = 37;
279
279
  return (0, _aoLoader["default"])(wasm, {
280
280
  format: format,
281
- WeaveDrive: wd,
281
+ WeaveDrive: extensions[t.Extension],
282
282
  spawn: item,
283
283
  module: mem.txs[mod],
284
284
  blockHeight: "100"
285
285
  });
286
- case 38:
286
+ case 37:
287
287
  handle = _context.sent;
288
288
  _module = {
289
289
  handle: handle,
@@ -308,7 +308,7 @@ var connect = exports.connect = function connect(mem) {
308
308
  opt: opt
309
309
  };
310
310
  if (!(_tags["On-Boot"] || true)) {
311
- _context.next = 59;
311
+ _context.next = 58;
312
312
  break;
313
313
  }
314
314
  data = "";
@@ -321,72 +321,72 @@ var connect = exports.connect = function connect(mem) {
321
321
  auth: _test.mu.addr
322
322
  });
323
323
  _t = (0, _utils.tags)(msg.Tags);
324
- _context.next = 53;
324
+ _context.next = 52;
325
325
  return _module.handle(null, msg, _env);
326
- case 53:
326
+ case 52:
327
327
  res = _context.sent;
328
328
  p.memory = res.Memory;
329
329
  delete res.Memory;
330
330
  p.res[id] = res;
331
- _context.next = 60;
331
+ _context.next = 59;
332
332
  break;
333
- case 59:
333
+ case 58:
334
334
  p.height += 1;
335
- case 60:
335
+ case 59:
336
336
  mem.msgs[id] = opt;
337
337
  mem.env[id] = p;
338
338
  if (!_tags["Cron-Interval"]) {
339
- _context.next = 86;
339
+ _context.next = 85;
340
340
  break;
341
341
  }
342
342
  _tags$CronInterval$s = _tags["Cron-Interval"].split("-"), _tags$CronInterval$s2 = _slicedToArray(_tags$CronInterval$s, 2), num = _tags$CronInterval$s2[0], unit = _tags$CronInterval$s2[1];
343
343
  _int = 0;
344
344
  _context.t0 = unit.replace(/s$/, "");
345
- _context.next = _context.t0 === "millisecond" ? 68 : _context.t0 === "second" ? 70 : _context.t0 === "minute" ? 72 : _context.t0 === "hour" ? 74 : _context.t0 === "day" ? 76 : _context.t0 === "month" ? 78 : _context.t0 === "year" ? 80 : 82;
345
+ _context.next = _context.t0 === "millisecond" ? 67 : _context.t0 === "second" ? 69 : _context.t0 === "minute" ? 71 : _context.t0 === "hour" ? 73 : _context.t0 === "day" ? 75 : _context.t0 === "month" ? 77 : _context.t0 === "year" ? 79 : 81;
346
346
  break;
347
- case 68:
347
+ case 67:
348
348
  _int = num;
349
- return _context.abrupt("break", 82);
350
- case 70:
349
+ return _context.abrupt("break", 81);
350
+ case 69:
351
351
  _int = num * 1000;
352
- return _context.abrupt("break", 82);
353
- case 72:
352
+ return _context.abrupt("break", 81);
353
+ case 71:
354
354
  _int = num * 1000 * 60;
355
- return _context.abrupt("break", 82);
356
- case 74:
355
+ return _context.abrupt("break", 81);
356
+ case 73:
357
357
  _int = num * 1000 * 60 * 60;
358
- return _context.abrupt("break", 82);
359
- case 76:
358
+ return _context.abrupt("break", 81);
359
+ case 75:
360
360
  _int = num * 1000 * 60 * 60 * 24;
361
- return _context.abrupt("break", 82);
362
- case 78:
361
+ return _context.abrupt("break", 81);
362
+ case 77:
363
363
  _int = num * 1000 * 60 * 60 * 24 * 30;
364
- return _context.abrupt("break", 82);
365
- case 80:
364
+ return _context.abrupt("break", 81);
365
+ case 79:
366
366
  _int = num * 1000 * 60 * 60 * 24 * 365;
367
- return _context.abrupt("break", 82);
368
- case 82:
367
+ return _context.abrupt("break", 81);
368
+ case 81:
369
369
  cronTags = [];
370
- for (k in _tags) {
371
- if (/^Cron-Tag-/.test(k)) {
370
+ for (_k in _tags) {
371
+ if (/^Cron-Tag-/.test(_k)) {
372
372
  cronTags.push({
373
- name: k.replace(/Cron-Tag-/, ""),
374
- value: _tags[k]
373
+ name: _k.replace(/Cron-Tag-/, ""),
374
+ value: _tags[_k]
375
375
  });
376
376
  }
377
377
  }
378
378
  mem.env[id].cronTags = cronTags;
379
379
  mem.env[id].span = _int;
380
- case 86:
380
+ case 85:
381
381
  return _context.abrupt("return", id);
382
- case 87:
382
+ case 86:
383
383
  case "end":
384
384
  return _context.stop();
385
385
  }
386
386
  }, _callee);
387
387
  }));
388
388
  return function spawn() {
389
- return _ref4.apply(this, arguments);
389
+ return _ref5.apply(this, arguments);
390
390
  };
391
391
  }();
392
392
  function genHashChain(previousHash) {
@@ -399,9 +399,9 @@ var connect = exports.connect = function connect(mem) {
399
399
  return (0, _base64url["default"])(hasher.digest());
400
400
  }
401
401
  var _assign = /*#__PURE__*/function () {
402
- var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(opt) {
402
+ var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2(opt) {
403
403
  var _opt$tags3;
404
- var p, _opt, hash, _yield$ar$dataitem2, id, owner, item, _opt$data2, _ref6, _opt$from, _res$Messages, _res$Spawns, _res$Assignments, data, _tags, from, raw_owner, hashBuffer, msg, _env, res, _iterator2, _step2, v, _iterator3, _step3, _v, __tags, _iterator4, _step4, _v2, _iterator5, _step5, v2;
404
+ var p, _opt, hash, _yield$ar$dataitem2, id, owner, item, _opt$data2, _ref7, _opt$from, _res$Messages, _res$Spawns, _res$Assignments, data, _tags, from, raw_owner, hashBuffer, msg, _env, res, _iterator2, _step2, v, _iterator3, _step3, _v, __tags, _iterator4, _step4, _v2, _iterator5, _step5, v2;
405
405
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
406
406
  while (1) switch (_context2.prev = _context2.next) {
407
407
  case 0:
@@ -457,7 +457,7 @@ var connect = exports.connect = function connect(mem) {
457
457
  _context2.prev = 21;
458
458
  data = (_opt$data2 = _opt.data) !== null && _opt$data2 !== void 0 ? _opt$data2 : "";
459
459
  _tags = _opt.tags;
460
- from = (_ref6 = (_opt$from = _opt.from) !== null && _opt$from !== void 0 ? _opt$from : opt.from) !== null && _ref6 !== void 0 ? _ref6 : owner;
460
+ from = (_ref7 = (_opt$from = _opt.from) !== null && _opt$from !== void 0 ? _opt$from : opt.from) !== null && _ref7 !== void 0 ? _ref7 : owner;
461
461
  if (!_opt.item) {
462
462
  _context2.next = 42;
463
463
  break;
@@ -643,11 +643,11 @@ var connect = exports.connect = function connect(mem) {
643
643
  }, _callee2, null, [[21, 124], [26, 39], [54, 65, 68, 71], [72, 83, 86, 89], [90, 115, 118, 121], [95, 105, 108, 111]]);
644
644
  }));
645
645
  return function assign(_x) {
646
- return _ref5.apply(this, arguments);
646
+ return _ref6.apply(this, arguments);
647
647
  };
648
648
  }();
649
649
  var message = /*#__PURE__*/function () {
650
- var _ref7 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(opt) {
650
+ var _ref8 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3(opt) {
651
651
  var _opt$item$id, _opt$item, _opt$owner;
652
652
  var p, ex, id, owner, item, _opt$tags4, _iterator6, _step6, v, _yield$ar$dataitem3;
653
653
  return _regeneratorRuntime().wrap(function _callee3$(_context3) {
@@ -716,7 +716,7 @@ var connect = exports.connect = function connect(mem) {
716
716
  }, _callee3);
717
717
  }));
718
718
  return function message(_x2) {
719
- return _ref7.apply(this, arguments);
719
+ return _ref8.apply(this, arguments);
720
720
  };
721
721
  }();
722
722
  return {
@@ -0,0 +1,43 @@
1
+ local json = require("json")
2
+ function rollup (id)
3
+ local file = io.open("/rollup/" .. id)
4
+ local data = nil
5
+ if file then data = file:read(file:seek('end')) end
6
+ file:close()
7
+ return data
8
+ end
9
+
10
+ function get (col, doc)
11
+ local file = io.open("/data/" .. col .. "/" .. doc)
12
+ local data = nil
13
+ if file then data = file:read(file:seek('end')) end
14
+ file:close()
15
+ return data
16
+ end
17
+
18
+ Handlers.add(
19
+ "Rollup",
20
+ "Rollup",
21
+ function (msg)
22
+ msg.reply({ Data = "committed!" })
23
+ end
24
+ )
25
+
26
+ Handlers.add(
27
+ "Finalize",
28
+ "Finalize",
29
+ function (msg)
30
+ local data = json.decode(rollup(msg.TXID))
31
+ msg.reply({ Data = "finalized!" })
32
+ end
33
+ )
34
+
35
+
36
+ Handlers.add(
37
+ "Get",
38
+ "Get",
39
+ function (msg)
40
+ msg.reply({ Data = get(msg.col, msg.doc) })
41
+ end
42
+ )
43
+
package/cjs/server.js CHANGED
@@ -44,7 +44,9 @@ var Server = /*#__PURE__*/function () {
44
44
  _ref$log = _ref.log,
45
45
  log = _ref$log === void 0 ? false : _ref$log;
46
46
  _classCallCheck(this, Server);
47
- var _connect = (0, _aoconnect.connect)(aoconnect, log),
47
+ var _connect = (0, _aoconnect.connect)(aoconnect, {
48
+ log: log
49
+ }),
48
50
  _ar = _connect.ar,
49
51
  message = _connect.message,
50
52
  spawn = _connect.spawn,
package/cjs/tao.js CHANGED
@@ -72,7 +72,9 @@ var AO = /*#__PURE__*/function (_MAO) {
72
72
  in_memory: true
73
73
  })]);
74
74
  _this.in_memory = true;
75
- var _connect = (0, _aoconnect2.connect)(opt.mem),
75
+ var _connect = (0, _aoconnect2.connect)(opt.mem, {
76
+ extensions: opt.extensions
77
+ }),
76
78
  modules = _connect.modules,
77
79
  results = _connect.results,
78
80
  assign = _connect.assign,
@@ -5,10 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports["default"] = void 0;
8
- var _arweave = _interopRequireDefault(require("arweave"));
9
- var _utils = require("./utils.js");
10
- var _ramda = require("ramda");
11
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
8
+ var _path = require("path");
9
+ var _fs = require("fs");
12
10
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
13
11
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
14
12
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
@@ -26,14 +24,28 @@ var CACHE_SZ = 32 * KB;
26
24
  var CHUNK_SZ = 128 * MB;
27
25
  var NOTIFY_SZ = 512 * MB;
28
26
  var log = console.log;
29
- var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
30
- _classCallCheck(this, KV);
31
- this.kv = function WeaveDrive(mod, FS) {
27
+ var rand = Math.floor(Math.random() * 1000000).toString();
28
+ var WeaveDB = exports["default"] = /*#__PURE__*/_createClass(function WeaveDB(ar, dir) {
29
+ var _dir;
30
+ _classCallCheck(this, WeaveDB);
31
+ (_dir = dir) !== null && _dir !== void 0 ? _dir : dir = (0, _path.resolve)(import.meta.dirname, ".db");
32
+ var kv_dir = (0, _path.resolve)(dir, rand);
33
+ var data_dir = (0, _path.resolve)(kv_dir, "data");
34
+ var rollup_dir = (0, _path.resolve)(kv_dir, "rollup");
35
+ for (var _i = 0, _arr = [dir, kv_dir, rollup_dir, data_dir]; _i < _arr.length; _i++) {
36
+ var v = _arr[_i];
37
+ if (!(0, _fs.existsSync)(v)) (0, _fs.mkdirSync)(v);
38
+ }
39
+ this.ext = function (mod, FS) {
40
+ var cache = {
41
+ data: {},
42
+ rollup: {}
43
+ };
32
44
  return {
33
45
  create: function create(id) {
34
46
  return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
35
- var _yield$ar$data$length, _yield$ar$data;
36
- var properties, node, bytesLength, stream;
47
+ var _data$length;
48
+ var properties, node, data, bytesLength, stream;
37
49
  return _regeneratorRuntime().wrap(function _callee$(_context) {
38
50
  while (1) switch (_context.prev = _context.next) {
39
51
  case 0:
@@ -41,48 +53,13 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
41
53
  isDevice: false,
42
54
  contents: null
43
55
  };
44
- if (!FS.analyzePath("/data/").exists) FS.mkdir("/data/");
45
- node = FS.createFile("/", "data/" + id, properties, true, false); // Set initial parameters
56
+ if (!FS.analyzePath("/rollup/").exists) FS.mkdir("/rollup/");
57
+ node = FS.createFile("/", "rollup/" + id, properties, true, false); // Set initial parame
46
58
  _context.next = 5;
47
59
  return ar.data(id);
48
60
  case 5:
49
- _context.t2 = _yield$ar$data = _context.sent;
50
- _context.t1 = _context.t2 === null;
51
- if (_context.t1) {
52
- _context.next = 9;
53
- break;
54
- }
55
- _context.t1 = _yield$ar$data === void 0;
56
- case 9:
57
- if (!_context.t1) {
58
- _context.next = 13;
59
- break;
60
- }
61
- _context.t3 = void 0;
62
- _context.next = 14;
63
- break;
64
- case 13:
65
- _context.t3 = _yield$ar$data.length;
66
- case 14:
67
- _context.t4 = _yield$ar$data$length = _context.t3;
68
- _context.t0 = _context.t4 !== null;
69
- if (!_context.t0) {
70
- _context.next = 18;
71
- break;
72
- }
73
- _context.t0 = _yield$ar$data$length !== void 0;
74
- case 18:
75
- if (!_context.t0) {
76
- _context.next = 22;
77
- break;
78
- }
79
- _context.t5 = _yield$ar$data$length;
80
- _context.next = 23;
81
- break;
82
- case 22:
83
- _context.t5 = 0;
84
- case 23:
85
- bytesLength = _context.t5;
61
+ data = _context.sent;
62
+ bytesLength = (_data$length = data === null || data === void 0 ? void 0 : data.length) !== null && _data$length !== void 0 ? _data$length : 0;
86
63
  node.total_size = Number(bytesLength);
87
64
  node.cache = new Uint8Array(0);
88
65
  node.position = 0;
@@ -97,66 +74,141 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
97
74
  });
98
75
 
99
76
  // Now we have created the file in the emscripten FS, we can open it as a stream
100
- stream = FS.open("/data/" + id, "r"); //console.log("JS: Created file: ", id, " fd: ", stream.fd);
77
+ stream = FS.open("/rollup/" + id, "r"); //console.log("JS: Created file: ", id, " fd: ", stream.fd);
101
78
  return _context.abrupt("return", stream);
102
- case 30:
79
+ case 13:
103
80
  case "end":
104
81
  return _context.stop();
105
82
  }
106
83
  }, _callee);
107
84
  }))();
108
85
  },
109
- open: function open(filename) {
110
- var _this = this;
86
+ createData: function createData(col, doc, val) {
111
87
  return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
112
- var pathCategory, id, stream, _stream;
88
+ var _data$length2, _data2;
89
+ var properties, node, data, _readFileSync, col_dir, _data, bytesLength, stream;
113
90
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
114
91
  while (1) switch (_context2.prev = _context2.next) {
92
+ case 0:
93
+ properties = {
94
+ isDevice: false,
95
+ contents: null
96
+ };
97
+ if (!FS.analyzePath("/data/").exists) FS.mkdir("/data/");
98
+ if (!FS.analyzePath("/data/".concat(col)).exists) FS.mkdir("/data/".concat(col));
99
+ node = FS.createFile("/", "data/".concat(col, "/").concat(doc), properties, true, false); // Set initial parame
100
+ data = val;
101
+ if (!val) {
102
+ col_dir = (0, _path.resolve)(data_dir, col);
103
+ _data = (_readFileSync = (0, _fs.readFileSync)((0, _path.resolve)(col_dir, "".concat(doc, ".json")), "utf8")) !== null && _readFileSync !== void 0 ? _readFileSync : "";
104
+ data = Buffer.from(_data, "utf8");
105
+ }
106
+ bytesLength = (_data$length2 = (_data2 = data) === null || _data2 === void 0 ? void 0 : _data2.length) !== null && _data$length2 !== void 0 ? _data$length2 : 0;
107
+ node.total_size = Number(bytesLength);
108
+ node.cache = new Uint8Array(0);
109
+ node.position = 0;
110
+
111
+ // Add a function that defers querying the file size until it is asked the first time.
112
+ Object.defineProperties(node, {
113
+ usedBytes: {
114
+ get: function get() {
115
+ return bytesLength;
116
+ }
117
+ }
118
+ });
119
+
120
+ // Now we have created the file in the emscripten FS, we can open it as a stream
121
+ stream = FS.open("/data/" + "".concat(col, "/").concat(doc), "r"); //console.log("JS: Created file: ", id, " fd: ", stream.fd);
122
+ return _context2.abrupt("return", stream);
123
+ case 13:
124
+ case "end":
125
+ return _context2.stop();
126
+ }
127
+ }, _callee2);
128
+ }))();
129
+ },
130
+ open: function open(filename, val) {
131
+ var _this = this;
132
+ return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
133
+ var pathCategory, id, stream, _stream, col, doc, _stream2, _stream3;
134
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
135
+ while (1) switch (_context3.prev = _context3.next) {
115
136
  case 0:
116
137
  pathCategory = filename.split("/")[1];
117
- id = filename.split("/")[2]; //log("JS: Opening ID: ", id)
118
- if (!(pathCategory === "data")) {
119
- _context2.next = 17;
138
+ if (!(pathCategory === "rollup")) {
139
+ _context3.next = 17;
120
140
  break;
121
141
  }
142
+ //log("JS: Opening ID: ", id)
143
+ id = filename.split("/")[2];
122
144
  if (!FS.analyzePath(filename).exists) {
123
- _context2.next = 11;
145
+ _context3.next = 11;
124
146
  break;
125
147
  }
126
148
  stream = FS.open(filename, "r");
127
149
  if (!stream.fd) {
128
- _context2.next = 7;
150
+ _context3.next = 7;
129
151
  break;
130
152
  }
131
- return _context2.abrupt("return", stream.fd);
153
+ return _context3.abrupt("return", stream.fd);
132
154
  case 7:
133
155
  console.log("JS: File not found: ", filename);
134
- return _context2.abrupt("return", 0);
156
+ return _context3.abrupt("return", 0);
135
157
  case 11:
136
- _context2.next = 13;
158
+ _context3.next = 13;
137
159
  return _this.create(id);
138
160
  case 13:
139
- _stream = _context2.sent;
140
- return _context2.abrupt("return", _stream.fd);
161
+ _stream = _context3.sent;
162
+ return _context3.abrupt("return", _stream.fd);
141
163
  case 15:
142
- _context2.next = 19;
164
+ _context3.next = 36;
143
165
  break;
144
166
  case 17:
167
+ if (!(pathCategory === "data")) {
168
+ _context3.next = 34;
169
+ break;
170
+ }
171
+ //log("JS: Opening ID: ", id)
172
+ col = filename.split("/")[2];
173
+ doc = filename.split("/")[3];
174
+ if (!FS.analyzePath(filename).exists) {
175
+ _context3.next = 28;
176
+ break;
177
+ }
178
+ _stream2 = FS.open(filename, "r");
179
+ if (!_stream2.fd) {
180
+ _context3.next = 24;
181
+ break;
182
+ }
183
+ return _context3.abrupt("return", _stream2.fd);
184
+ case 24:
185
+ console.log("JS: File not found: ", filename);
186
+ return _context3.abrupt("return", 0);
187
+ case 28:
188
+ _context3.next = 30;
189
+ return _this.createData(col, doc, val);
190
+ case 30:
191
+ _stream3 = _context3.sent;
192
+ return _context3.abrupt("return", _stream3.fd);
193
+ case 32:
194
+ _context3.next = 36;
195
+ break;
196
+ case 34:
145
197
  console.log("JS: Invalid path category: ", pathCategory);
146
- return _context2.abrupt("return", 0);
147
- case 19:
198
+ return _context3.abrupt("return", 0);
199
+ case 36:
148
200
  case "end":
149
- return _context2.stop();
201
+ return _context3.stop();
150
202
  }
151
- }, _callee2);
203
+ }, _callee3);
152
204
  }))();
153
205
  },
154
- read: function read(fd, raw_dst_ptr, raw_length) {
206
+ read: function read(fd, raw_dst_ptr, raw_length, val) {
155
207
  var _this2 = this;
156
- return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
157
- var to_read, dst_ptr, stream, i, bytes_read, chunk_download_sz, to, data, start, end, chunk, response, reader, bytes_until_cache, bytes_until_notify, downloaded_bytes, cache_chunks, _yield$reader$read, done, chunk_bytes, write_length, chunk_to_cache;
158
- return _regeneratorRuntime().wrap(function _callee3$(_context3) {
159
- while (1) switch (_context3.prev = _context3.next) {
208
+ return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() {
209
+ var to_read, dst_ptr, stream, i, bytes_read, chunk_download_sz, to, data, sp, _readFileSync2, col_dir, _data, json, _iterator, _step, _v, _val, _fd, _col_dir, start, end, chunk, response, reader, bytes_until_cache, bytes_until_notify, downloaded_bytes, cache_chunks, _yield$reader$read, done, chunk_bytes, write_length, chunk_to_cache;
210
+ return _regeneratorRuntime().wrap(function _callee4$(_context4) {
211
+ while (1) switch (_context4.prev = _context4.next) {
160
212
  case 0:
161
213
  to_read = Number(raw_length);
162
214
  dst_ptr = Number(raw_dst_ptr);
@@ -164,7 +216,6 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
164
216
  for (i = 0; i < FS.streams.length; i++) {
165
217
  if (FS.streams[i].fd === fd) stream = FS.streams[i];
166
218
  }
167
-
168
219
  // Satisfy what we can with the cache first
169
220
  bytes_read = _this2.readFromCache(stream, dst_ptr, to_read);
170
221
  stream.position += bytes_read;
@@ -173,19 +224,80 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
173
224
  to_read -= bytes_read;
174
225
 
175
226
  // Return if we have satisfied the request
227
+
228
+ //console.log("KV: Satisfied request with cache. Returning...")
176
229
  if (!(to_read === 0)) {
177
- _context3.next = 11;
230
+ _context4.next = 11;
178
231
  break;
179
232
  }
180
- return _context3.abrupt("return", bytes_read);
233
+ return _context4.abrupt("return", bytes_read);
181
234
  case 11:
182
- //console.log("WeaveDrive: Read from cache: ", bytes_read, " Remaining to read: ", to_read)
235
+ //console.log("KV: Read from cache: ", bytes_read, " Remaining to read: ", to_read)
183
236
  chunk_download_sz = Math.max(to_read, CACHE_SZ);
184
237
  to = Math.min(stream.node.total_size, stream.position + chunk_download_sz);
185
- _context3.next = 15;
238
+ data = val;
239
+ if (data) {
240
+ _context4.next = 56;
241
+ break;
242
+ }
243
+ sp = stream.path.split("/");
244
+ if (!(sp[1] === "data")) {
245
+ _context4.next = 22;
246
+ break;
247
+ }
248
+ col_dir = (0, _path.resolve)(data_dir, sp[2]);
249
+ _data = (_readFileSync2 = (0, _fs.readFileSync)((0, _path.resolve)(col_dir, "".concat(sp[3], ".json")), "utf8")) !== null && _readFileSync2 !== void 0 ? _readFileSync2 : "";
250
+ data = Buffer.from(_data, "utf8");
251
+ _context4.next = 56;
252
+ break;
253
+ case 22:
254
+ _context4.next = 24;
186
255
  return ar.data(stream.node.name);
187
- case 15:
188
- data = _context3.sent;
256
+ case 24:
257
+ data = _context4.sent;
258
+ _context4.prev = 25;
259
+ json = JSON.parse(Buffer.from(data).toString());
260
+ _iterator = _createForOfIteratorHelper(json.diffs);
261
+ _context4.prev = 28;
262
+ _iterator.s();
263
+ case 30:
264
+ if ((_step = _iterator.n()).done) {
265
+ _context4.next = 43;
266
+ break;
267
+ }
268
+ _v = _step.value;
269
+ _val = Buffer.from(JSON.stringify(_v.data));
270
+ _context4.next = 35;
271
+ return _this2.open("/data/".concat(_v.collection, "/").concat(_v.doc), _val);
272
+ case 35:
273
+ _fd = _context4.sent;
274
+ _col_dir = (0, _path.resolve)(data_dir, _v.collection);
275
+ if (!(0, _fs.existsSync)(_col_dir)) (0, _fs.mkdirSync)(_col_dir);
276
+ (0, _fs.writeFileSync)((0, _path.resolve)(_col_dir, "".concat(_v.doc, ".json")), JSON.stringify(_v.data));
277
+ _context4.next = 41;
278
+ return _this2.read(_fd, _fd, _val.length, _val);
279
+ case 41:
280
+ _context4.next = 30;
281
+ break;
282
+ case 43:
283
+ _context4.next = 48;
284
+ break;
285
+ case 45:
286
+ _context4.prev = 45;
287
+ _context4.t0 = _context4["catch"](28);
288
+ _iterator.e(_context4.t0);
289
+ case 48:
290
+ _context4.prev = 48;
291
+ _iterator.f();
292
+ return _context4.finish(48);
293
+ case 51:
294
+ _context4.next = 56;
295
+ break;
296
+ case 53:
297
+ _context4.prev = 53;
298
+ _context4.t1 = _context4["catch"](25);
299
+ log(_context4.t1);
300
+ case 56:
189
301
  // Extract the Range header to determine the start and end of the requested chunk
190
302
  start = 0;
191
303
  end = data.length; // Create a ReadableStream for the requested chunk
@@ -205,24 +317,24 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
205
317
  bytes_until_notify = NOTIFY_SZ;
206
318
  downloaded_bytes = 0;
207
319
  cache_chunks = [];
208
- _context3.prev = 25;
209
- case 26:
320
+ _context4.prev = 65;
321
+ case 66:
210
322
  if (!true) {
211
- _context3.next = 44;
323
+ _context4.next = 84;
212
324
  break;
213
325
  }
214
- _context3.next = 29;
326
+ _context4.next = 69;
215
327
  return reader.read();
216
- case 29:
217
- _yield$reader$read = _context3.sent;
328
+ case 69:
329
+ _yield$reader$read = _context4.sent;
218
330
  done = _yield$reader$read.done;
219
331
  chunk_bytes = _yield$reader$read.value;
220
332
  if (!done) {
221
- _context3.next = 34;
333
+ _context4.next = 74;
222
334
  break;
223
335
  }
224
- return _context3.abrupt("break", 44);
225
- case 34:
336
+ return _context4.abrupt("break", 84);
337
+ case 74:
226
338
  // Update the number of downloaded bytes to be _all_, not just the write length
227
339
  downloaded_bytes += chunk_bytes.length;
228
340
  bytes_until_cache -= chunk_bytes.length;
@@ -231,7 +343,7 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
231
343
  // Write bytes from the chunk and update the pointer if necessary
232
344
  write_length = Math.min(chunk_bytes.length, to_read);
233
345
  if (write_length > 0) {
234
- //console.log("WeaveDrive: Writing: ", write_length, " bytes to: ", dst_ptr)
346
+ //console.log("KV: Writing: ", write_length, " bytes to: ", dst_ptr)
235
347
  mod.HEAP8.set(chunk_bytes.subarray(0, write_length), dst_ptr);
236
348
  dst_ptr += write_length;
237
349
  bytes_read += write_length;
@@ -240,45 +352,45 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
240
352
  }
241
353
  if (to_read == 0) {
242
354
  // Add excess bytes to our cache
243
- chunk_to_cache = chunk_bytes.subarray(write_length); //console.log("WeaveDrive: Cacheing excess: ", chunk_to_cache.length)
355
+ chunk_to_cache = chunk_bytes.subarray(write_length); //console.log("KV: Cacheing excess: ", chunk_to_cache.length)
244
356
  cache_chunks.push(chunk_to_cache);
245
357
  }
246
358
  if (bytes_until_cache <= 0) {
247
- console.log("WeaveDrive: Chunk size reached. Compressing cache...");
359
+ console.log("KV: Chunk size reached. Compressing cache...");
248
360
  stream.node.cache = _this2.addChunksToCache(stream.node.cache, cache_chunks);
249
361
  cache_chunks = [];
250
362
  bytes_until_cache = CHUNK_SZ;
251
363
  }
252
364
  if (bytes_until_notify <= 0) {
253
- console.log("WeaveDrive: Downloaded: ", downloaded_bytes / stream.node.total_size * 100, "%");
365
+ console.log("KV: Downloaded: ", downloaded_bytes / stream.node.total_size * 100, "%");
254
366
  bytes_until_notify = NOTIFY_SZ;
255
367
  }
256
- _context3.next = 26;
368
+ _context4.next = 66;
257
369
  break;
258
- case 44:
259
- _context3.next = 49;
370
+ case 84:
371
+ _context4.next = 89;
260
372
  break;
261
- case 46:
262
- _context3.prev = 46;
263
- _context3.t0 = _context3["catch"](25);
264
- console.error("WeaveDrive: Error reading the stream: ", _context3.t0);
265
- case 49:
266
- _context3.prev = 49;
373
+ case 86:
374
+ _context4.prev = 86;
375
+ _context4.t2 = _context4["catch"](65);
376
+ console.error("KV: Error reading the stream: ", _context4.t2);
377
+ case 89:
378
+ _context4.prev = 89;
267
379
  reader.releaseLock();
268
- return _context3.finish(49);
269
- case 52:
380
+ return _context4.finish(89);
381
+ case 92:
270
382
  // If we have no cache, or we have not satisfied the full request, we need to download the rest
271
383
  // Rebuild the cache from the new cache chunks
272
384
  stream.node.cache = _this2.addChunksToCache(stream.node.cache, cache_chunks);
273
385
 
274
386
  // Update the last read position
275
387
  stream.lastReadPosition = stream.position;
276
- return _context3.abrupt("return", bytes_read);
277
- case 55:
388
+ return _context4.abrupt("return", bytes_read);
389
+ case 95:
278
390
  case "end":
279
- return _context3.stop();
391
+ return _context4.stop();
280
392
  }
281
- }, _callee3, null, [[25, 46, 49, 52]]);
393
+ }, _callee4, null, [[25, 53], [28, 45, 48, 51], [65, 86, 89, 92]]);
282
394
  }))();
283
395
  },
284
396
  close: function close(fd) {
@@ -291,7 +403,7 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
291
403
  readFromCache: function readFromCache(stream, dst_ptr, length) {
292
404
  // Check if the cache has been invalidated by a seek
293
405
  if (stream.lastReadPosition !== stream.position) {
294
- //console.log("WeaveDrive: Invalidating cache for fd: ", stream.fd, " Current pos: ", stream.position, " Last read pos: ", stream.lastReadPosition)
406
+ //console.log("KV: Invalidating cache for fd: ", stream.fd, " Current pos: ", stream.position, " Last read pos: ", stream.lastReadPosition)
295
407
  stream.node.cache = new Uint8Array(0);
296
408
  return 0;
297
409
  }
@@ -313,20 +425,20 @@ var KV = exports["default"] = /*#__PURE__*/_createClass(function KV(ar) {
313
425
  new_cache.set(old_cache, 0);
314
426
  // Load the cache chunks into the new cache
315
427
  var current_offset = old_cache.length;
316
- var _iterator = _createForOfIteratorHelper(chunks),
317
- _step;
428
+ var _iterator2 = _createForOfIteratorHelper(chunks),
429
+ _step2;
318
430
  try {
319
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
320
- var chunk = _step.value;
431
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
432
+ var chunk = _step2.value;
321
433
  if (current_offset < new_cache_length) {
322
434
  new_cache.set(chunk.subarray(0, new_cache_length - current_offset), current_offset);
323
435
  current_offset += chunk.length;
324
436
  }
325
437
  }
326
438
  } catch (err) {
327
- _iterator.e(err);
439
+ _iterator2.e(err);
328
440
  } finally {
329
- _iterator.f();
441
+ _iterator2.f();
330
442
  }
331
443
  return new_cache;
332
444
  }
package/cjs/weavedrive.js CHANGED
@@ -31,7 +31,7 @@ var NOTIFY_SZ = 512 * MB;
31
31
  var log = console.log;
32
32
  var WeaveDrive = exports["default"] = /*#__PURE__*/_createClass(function WeaveDrive(ar) {
33
33
  _classCallCheck(this, WeaveDrive);
34
- this.drive = function WeaveDrive(mod, FS) {
34
+ this.ext = function (mod, FS) {
35
35
  return {
36
36
  reset: function reset(fd) {
37
37
  //console.log("WeaveDrive: Resetting fd: ", fd)
@@ -49,7 +49,7 @@ var WeaveDrive = exports["default"] = /*#__PURE__*/_createClass(function WeaveDr
49
49
  properties = {
50
50
  isDevice: false,
51
51
  contents: null
52
- };
52
+ }; //console.log("WeaveDrive: Arweave ID is not admissable! ", id)
53
53
  _context.next = 3;
54
54
  return _this.checkAdmissible(id);
55
55
  case 3:
@@ -98,7 +98,7 @@ var WeaveDrive = exports["default"] = /*#__PURE__*/_createClass(function WeaveDr
98
98
  },
99
99
  createBlockHeader: function createBlockHeader(id) {
100
100
  return _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
101
- var result, block, bytesLength, node, stream;
101
+ var result, block, node, stream;
102
102
  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
103
103
  while (1) switch (_context2.prev = _context2.next) {
104
104
  case 0:
@@ -117,11 +117,10 @@ var WeaveDrive = exports["default"] = /*#__PURE__*/_createClass(function WeaveDr
117
117
  });
118
118
  }
119
119
  } catch (e) {}
120
- bytesLength = result.length;
121
120
  node = FS.createDataFile("/", "block/" + id, Buffer.from(result, "utf-8"), true, false);
122
121
  stream = FS.open("/block/" + id, "r");
123
122
  return _context2.abrupt("return", stream);
124
- case 6:
123
+ case 5:
125
124
  case "end":
126
125
  return _context2.stop();
127
126
  }
@@ -345,6 +344,8 @@ var WeaveDrive = exports["default"] = /*#__PURE__*/_createClass(function WeaveDr
345
344
  to_read -= bytes_read;
346
345
 
347
346
  // Return if we have satisfied the request
347
+
348
+ //console.log("WeaveDrive: Satisfied request with cache. Returning...")
348
349
  if (!(to_read === 0)) {
349
350
  _context6.next = 17;
350
351
  break;
package/esm/aoconnect.js CHANGED
@@ -16,7 +16,6 @@ import {
16
16
  } from "./utils.js"
17
17
  import ArMem from "./armem.js"
18
18
  import weavedrive from "./weavedrive.js"
19
- import kv from "./kv.js"
20
19
  import AoLoader from "@permaweb/ao-loader"
21
20
  import { readFileSync } from "fs"
22
21
  import { resolve } from "path"
@@ -24,7 +23,7 @@ import { scheduler, mu, su, cu, acc } from "./test.js"
24
23
  import { is, clone, fromPairs, map, mergeLeft, isNil } from "ramda"
25
24
  import AR from "./tar.js"
26
25
 
27
- export const connect = (mem, log = false) => {
26
+ export const connect = (mem, { log = false, extensions = {} }) => {
28
27
  const isMem = mem?.__type__ === "mem"
29
28
  if (!isMem) {
30
29
  let args = {}
@@ -35,8 +34,8 @@ export const connect = (mem, log = false) => {
35
34
  mem = new ArMem(args)
36
35
  }
37
36
  const ar = new AR({ mem, log })
38
- const WeaveDrive = new weavedrive(ar).drive
39
- const KV = new kv(ar).kv
37
+ for (const k in extensions) extensions[k] = new extensions[k](ar).ext
38
+ extensions.WeaveDrive = new weavedrive(ar).ext
40
39
 
41
40
  const transform = input => {
42
41
  const output = { Tags: [] }
@@ -152,10 +151,9 @@ export const connect = (mem, log = false) => {
152
151
  await ar.postItems(item, su.jwk)
153
152
  const now = Date.now
154
153
  const t = tags(opt.tags)
155
- const wd = t.Extension === "KV" ? KV : WeaveDrive
156
154
  const handle = await AoLoader(wasm, {
157
155
  format,
158
- WeaveDrive: wd,
156
+ WeaveDrive: extensions[t.Extension],
159
157
  spawn: item,
160
158
  module: mem.txs[mod],
161
159
  blockHeight: "100",
@@ -0,0 +1,43 @@
1
+ local json = require("json")
2
+ function rollup (id)
3
+ local file = io.open("/rollup/" .. id)
4
+ local data = nil
5
+ if file then data = file:read(file:seek('end')) end
6
+ file:close()
7
+ return data
8
+ end
9
+
10
+ function get (col, doc)
11
+ local file = io.open("/data/" .. col .. "/" .. doc)
12
+ local data = nil
13
+ if file then data = file:read(file:seek('end')) end
14
+ file:close()
15
+ return data
16
+ end
17
+
18
+ Handlers.add(
19
+ "Rollup",
20
+ "Rollup",
21
+ function (msg)
22
+ msg.reply({ Data = "committed!" })
23
+ end
24
+ )
25
+
26
+ Handlers.add(
27
+ "Finalize",
28
+ "Finalize",
29
+ function (msg)
30
+ local data = json.decode(rollup(msg.TXID))
31
+ msg.reply({ Data = "finalized!" })
32
+ end
33
+ )
34
+
35
+
36
+ Handlers.add(
37
+ "Get",
38
+ "Get",
39
+ function (msg)
40
+ msg.reply({ Data = get(msg.col, msg.doc) })
41
+ end
42
+ )
43
+
package/esm/server.js CHANGED
@@ -27,7 +27,7 @@ class Server {
27
27
  mem,
28
28
  monitor,
29
29
  unmonitor,
30
- } = connect(aoconnect, log)
30
+ } = connect(aoconnect, { log })
31
31
  this.monitor = monitor
32
32
  this.unmonitor = unmonitor
33
33
  this.spawn = spawn
package/esm/tao.js CHANGED
@@ -64,7 +64,7 @@ class AO extends MAO {
64
64
  monitor,
65
65
  unmonitor,
66
66
  mem,
67
- } = connect(opt.mem)
67
+ } = connect(opt.mem, { extensions: opt.extensions })
68
68
  this.module = mem.modules.aos2_0_1
69
69
  this.assign = assign
70
70
  this.result = async (...opt) => {
@@ -1,46 +1,89 @@
1
- import Arweave from "arweave"
2
- import { toGraphObj } from "./utils.js"
3
- import { map } from "ramda"
4
-
1
+ import { resolve } from "path"
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs"
5
3
  const KB = 1024
6
4
  const MB = KB * 1024
7
5
  const CACHE_SZ = 32 * KB
8
6
  const CHUNK_SZ = 128 * MB
9
7
  const NOTIFY_SZ = 512 * MB
10
8
  const log = console.log
9
+ const rand = Math.floor(Math.random() * 1000000).toString()
11
10
 
12
- export default class KV {
13
- constructor(ar) {
14
- this.kv = function WeaveDrive(mod, FS) {
11
+ export default class WeaveDB {
12
+ constructor(ar, dir) {
13
+ dir ??= resolve(import.meta.dirname, ".db")
14
+ const kv_dir = resolve(dir, rand)
15
+ const data_dir = resolve(kv_dir, "data")
16
+ const rollup_dir = resolve(kv_dir, "rollup")
17
+ for (const v of [dir, kv_dir, rollup_dir, data_dir]) {
18
+ if (!existsSync(v)) mkdirSync(v)
19
+ }
20
+ this.ext = (mod, FS) => {
21
+ let cache = { data: {}, rollup: {} }
15
22
  return {
16
23
  async create(id) {
24
+ let properties = { isDevice: false, contents: null }
25
+ if (!FS.analyzePath("/rollup/").exists) FS.mkdir("/rollup/")
26
+ let node = FS.createFile("/", "rollup/" + id, properties, true, false)
27
+
28
+ // Set initial parame
29
+ let data = await ar.data(id)
30
+ const bytesLength = data?.length ?? 0
31
+ node.total_size = Number(bytesLength)
32
+ node.cache = new Uint8Array(0)
33
+ node.position = 0
34
+
35
+ // Add a function that defers querying the file size until it is asked the first time.
36
+ Object.defineProperties(node, {
37
+ usedBytes: { get: () => bytesLength },
38
+ })
39
+
40
+ // Now we have created the file in the emscripten FS, we can open it as a stream
41
+ let stream = FS.open("/rollup/" + id, "r")
42
+
43
+ //console.log("JS: Created file: ", id, " fd: ", stream.fd);
44
+ return stream
45
+ },
46
+ async createData(col, doc, val) {
17
47
  let properties = { isDevice: false, contents: null }
18
48
  if (!FS.analyzePath("/data/").exists) FS.mkdir("/data/")
19
- let node = FS.createFile("/", "data/" + id, properties, true, false)
20
- // Set initial parameters
21
- const bytesLength = (await ar.data(id))?.length ?? 0
49
+ if (!FS.analyzePath(`/data/${col}`).exists) FS.mkdir(`/data/${col}`)
50
+ let node = FS.createFile(
51
+ "/",
52
+ `data/${col}/${doc}`,
53
+ properties,
54
+ true,
55
+ false,
56
+ )
57
+
58
+ // Set initial parame
59
+ let data = val
60
+ if (!val) {
61
+ const col_dir = resolve(data_dir, col)
62
+ const _data =
63
+ readFileSync(resolve(col_dir, `${doc}.json`), "utf8") ?? ""
64
+ data = Buffer.from(_data, "utf8")
65
+ }
66
+ const bytesLength = data?.length ?? 0
22
67
  node.total_size = Number(bytesLength)
23
68
  node.cache = new Uint8Array(0)
24
69
  node.position = 0
25
70
 
26
71
  // Add a function that defers querying the file size until it is asked the first time.
27
72
  Object.defineProperties(node, {
28
- usedBytes: {
29
- get: () => bytesLength,
30
- },
73
+ usedBytes: { get: () => bytesLength },
31
74
  })
32
75
 
33
76
  // Now we have created the file in the emscripten FS, we can open it as a stream
34
- let stream = FS.open("/data/" + id, "r")
77
+ let stream = FS.open("/data/" + `${col}/${doc}`, "r")
35
78
 
36
79
  //console.log("JS: Created file: ", id, " fd: ", stream.fd);
37
80
  return stream
38
81
  },
39
- async open(filename) {
82
+ async open(filename, val) {
40
83
  const pathCategory = filename.split("/")[1]
41
- const id = filename.split("/")[2]
42
- //log("JS: Opening ID: ", id)
43
- if (pathCategory === "data") {
84
+ if (pathCategory === "rollup") {
85
+ //log("JS: Opening ID: ", id)
86
+ const id = filename.split("/")[2]
44
87
  if (FS.analyzePath(filename).exists) {
45
88
  let stream = FS.open(filename, "r")
46
89
  if (stream.fd) return stream.fd
@@ -52,19 +95,33 @@ export default class KV {
52
95
  //console.log("JS: Open => Created file: ", id, " fd: ", stream.fd);
53
96
  return stream.fd
54
97
  }
98
+ } else if (pathCategory === "data") {
99
+ //log("JS: Opening ID: ", id)
100
+ const col = filename.split("/")[2]
101
+ const doc = filename.split("/")[3]
102
+ if (FS.analyzePath(filename).exists) {
103
+ let stream = FS.open(filename, "r")
104
+ if (stream.fd) return stream.fd
105
+ console.log("JS: File not found: ", filename)
106
+ return 0
107
+ } else {
108
+ //console.log("JS: Open => Creating file: ", id);
109
+ const stream = await this.createData(col, doc, val)
110
+ //console.log("JS: Open => Created file: ", id, " fd: ", stream.fd);
111
+ return stream.fd
112
+ }
55
113
  } else {
56
114
  console.log("JS: Invalid path category: ", pathCategory)
57
115
  return 0
58
116
  }
59
117
  },
60
- async read(fd, raw_dst_ptr, raw_length) {
118
+ async read(fd, raw_dst_ptr, raw_length, val) {
61
119
  let to_read = Number(raw_length)
62
120
  let dst_ptr = Number(raw_dst_ptr)
63
121
  let stream = 0
64
122
  for (let i = 0; i < FS.streams.length; i++) {
65
123
  if (FS.streams[i].fd === fd) stream = FS.streams[i]
66
124
  }
67
-
68
125
  // Satisfy what we can with the cache first
69
126
  let bytes_read = this.readFromCache(stream, dst_ptr, to_read)
70
127
  stream.position += bytes_read
@@ -73,22 +130,51 @@ export default class KV {
73
130
  to_read -= bytes_read
74
131
 
75
132
  // Return if we have satisfied the request
76
- if (to_read === 0) {
77
- //console.log("WeaveDrive: Satisfied request with cache. Returning...")
78
- return bytes_read
79
- }
80
- //console.log("WeaveDrive: Read from cache: ", bytes_read, " Remaining to read: ", to_read)
133
+
134
+ //console.log("KV: Satisfied request with cache. Returning...")
135
+ if (to_read === 0) return bytes_read
136
+
137
+ //console.log("KV: Read from cache: ", bytes_read, " Remaining to read: ", to_read)
81
138
 
82
139
  const chunk_download_sz = Math.max(to_read, CACHE_SZ)
83
140
  const to = Math.min(
84
141
  stream.node.total_size,
85
142
  stream.position + chunk_download_sz,
86
143
  )
87
- const data = await ar.data(stream.node.name)
144
+ let data = val
145
+ if (!data) {
146
+ const sp = stream.path.split("/")
147
+ if (sp[1] === "data") {
148
+ const col_dir = resolve(data_dir, sp[2])
149
+ const _data =
150
+ readFileSync(resolve(col_dir, `${sp[3]}.json`), "utf8") ?? ""
151
+ data = Buffer.from(_data, "utf8")
152
+ } else {
153
+ data = await ar.data(stream.node.name)
154
+ try {
155
+ const json = JSON.parse(Buffer.from(data).toString())
156
+ for (const v of json.diffs) {
157
+ const val = Buffer.from(JSON.stringify(v.data))
158
+ const _fd = await this.open(
159
+ `/data/${v.collection}/${v.doc}`,
160
+ val,
161
+ )
162
+ const col_dir = resolve(data_dir, v.collection)
163
+ if (!existsSync(col_dir)) mkdirSync(col_dir)
164
+ writeFileSync(
165
+ resolve(col_dir, `${v.doc}.json`),
166
+ JSON.stringify(v.data),
167
+ )
168
+ await this.read(_fd, _fd, val.length, val)
169
+ }
170
+ } catch (e) {
171
+ log(e)
172
+ }
173
+ }
174
+ }
88
175
  // Extract the Range header to determine the start and end of the requested chunk
89
176
  const start = 0
90
177
  const end = data.length
91
-
92
178
  // Create a ReadableStream for the requested chunk
93
179
  const chunk = data.subarray(start, end)
94
180
  const response = new Response(
@@ -120,7 +206,7 @@ export default class KV {
120
206
  // Write bytes from the chunk and update the pointer if necessary
121
207
  const write_length = Math.min(chunk_bytes.length, to_read)
122
208
  if (write_length > 0) {
123
- //console.log("WeaveDrive: Writing: ", write_length, " bytes to: ", dst_ptr)
209
+ //console.log("KV: Writing: ", write_length, " bytes to: ", dst_ptr)
124
210
  mod.HEAP8.set(chunk_bytes.subarray(0, write_length), dst_ptr)
125
211
  dst_ptr += write_length
126
212
  bytes_read += write_length
@@ -131,14 +217,11 @@ export default class KV {
131
217
  if (to_read == 0) {
132
218
  // Add excess bytes to our cache
133
219
  const chunk_to_cache = chunk_bytes.subarray(write_length)
134
- //console.log("WeaveDrive: Cacheing excess: ", chunk_to_cache.length)
220
+ //console.log("KV: Cacheing excess: ", chunk_to_cache.length)
135
221
  cache_chunks.push(chunk_to_cache)
136
222
  }
137
-
138
223
  if (bytes_until_cache <= 0) {
139
- console.log(
140
- "WeaveDrive: Chunk size reached. Compressing cache...",
141
- )
224
+ console.log("KV: Chunk size reached. Compressing cache...")
142
225
  stream.node.cache = this.addChunksToCache(
143
226
  stream.node.cache,
144
227
  cache_chunks,
@@ -149,7 +232,7 @@ export default class KV {
149
232
 
150
233
  if (bytes_until_notify <= 0) {
151
234
  console.log(
152
- "WeaveDrive: Downloaded: ",
235
+ "KV: Downloaded: ",
153
236
  (downloaded_bytes / stream.node.total_size) * 100,
154
237
  "%",
155
238
  )
@@ -157,7 +240,7 @@ export default class KV {
157
240
  }
158
241
  }
159
242
  } catch (error) {
160
- console.error("WeaveDrive: Error reading the stream: ", error)
243
+ console.error("KV: Error reading the stream: ", error)
161
244
  } finally {
162
245
  reader.releaseLock()
163
246
  }
@@ -183,7 +266,7 @@ export default class KV {
183
266
  readFromCache(stream, dst_ptr, length) {
184
267
  // Check if the cache has been invalidated by a seek
185
268
  if (stream.lastReadPosition !== stream.position) {
186
- //console.log("WeaveDrive: Invalidating cache for fd: ", stream.fd, " Current pos: ", stream.position, " Last read pos: ", stream.lastReadPosition)
269
+ //console.log("KV: Invalidating cache for fd: ", stream.fd, " Current pos: ", stream.position, " Last read pos: ", stream.lastReadPosition)
187
270
  stream.node.cache = new Uint8Array(0)
188
271
  return 0
189
272
  }
package/esm/weavedrive.js CHANGED
@@ -7,7 +7,7 @@ const log = console.log
7
7
 
8
8
  export default class WeaveDrive {
9
9
  constructor(ar) {
10
- this.drive = function WeaveDrive(mod, FS) {
10
+ this.ext = (mod, FS) => {
11
11
  return {
12
12
  reset(fd) {
13
13
  //console.log("WeaveDrive: Resetting fd: ", fd)
@@ -18,10 +18,8 @@ export default class WeaveDrive {
18
18
  async create(id) {
19
19
  var properties = { isDevice: false, contents: null }
20
20
 
21
- if (!(await this.checkAdmissible(id))) {
22
- //console.log("WeaveDrive: Arweave ID is not admissable! ", id)
23
- return 0
24
- }
21
+ //console.log("WeaveDrive: Arweave ID is not admissable! ", id)
22
+ if (!(await this.checkAdmissible(id))) return 0
25
23
 
26
24
  // Create the file in the emscripten FS
27
25
 
@@ -42,11 +40,7 @@ export default class WeaveDrive {
42
40
 
43
41
  // Add a function that defers querying the file size until it is asked the first time.
44
42
  Object.defineProperties(node, {
45
- usedBytes: {
46
- get: function () {
47
- return bytesLength
48
- },
49
- },
43
+ usedBytes: { get: () => bytesLength },
50
44
  })
51
45
 
52
46
  // Now we have created the file in the emscripten FS, we can open it as a stream
@@ -72,8 +66,6 @@ export default class WeaveDrive {
72
66
  }
73
67
  } catch (e) {}
74
68
 
75
- var bytesLength = result.length
76
-
77
69
  var node = FS.createDataFile(
78
70
  "/",
79
71
  "block/" + id,
@@ -220,10 +212,10 @@ export default class WeaveDrive {
220
212
  to_read -= bytes_read
221
213
 
222
214
  // Return if we have satisfied the request
223
- if (to_read === 0) {
224
- //console.log("WeaveDrive: Satisfied request with cache. Returning...")
225
- return bytes_read
226
- }
215
+
216
+ //console.log("WeaveDrive: Satisfied request with cache. Returning...")
217
+ if (to_read === 0) return bytes_read
218
+
227
219
  //console.log("WeaveDrive: Read from cache: ", bytes_read, " Remaining to read: ", to_read)
228
220
 
229
221
  const chunk_download_sz = Math.max(to_read, CACHE_SZ)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wao",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "",
5
5
  "main": "cjs/index.js",
6
6
  "module": "esm/index.js",