@tiddlywiki/mws 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.env-cmdrc +5 -0
  2. package/README.md +3 -1
  3. package/dist/server.d.ts +923 -0
  4. package/dist/server.js +1763 -1415
  5. package/dist/server.js.map +1 -1
  6. package/editions/mws-docs/tiddlers/$__StoryList.tid +3 -3
  7. package/editions/mws-docs/tiddlers/MWS and SQLite.md +11 -0
  8. package/editions/mws-docs/tiddlers/Request Server.md +20 -0
  9. package/editions/mws-docs/tiddlers/Request Server.md.meta +5 -0
  10. package/package.json +17 -10
  11. package/prisma/schema.prisma +1 -0
  12. package/react-user-mgmt/package-lock.json +76 -321
  13. package/react-user-mgmt/package.json +2 -5
  14. package/react-user-mgmt/public/chunk-YALWN5OT.js +2 -0
  15. package/react-user-mgmt/public/chunk-YALWN5OT.js.map +7 -0
  16. package/react-user-mgmt/public/esm-QKDFEP3B.js +3 -0
  17. package/react-user-mgmt/public/esm-QKDFEP3B.js.map +7 -0
  18. package/react-user-mgmt/public/index.html +1 -26
  19. package/react-user-mgmt/public/main.js +68 -109
  20. package/react-user-mgmt/public/main.js.map +4 -4
  21. package/react-user-mgmt/public/stats.css +597 -0
  22. package/react-user-mgmt/public/stats.html +59 -0
  23. package/react-user-mgmt/public/stats.js +2013 -0
  24. package/react-user-mgmt/public/stats.json +1 -0
  25. package/react-user-mgmt/public/stats.svg +4 -0
  26. package/react-user-mgmt/tsconfig.json +3 -0
  27. package/dist/server.cjs +0 -16677
  28. package/dist/server.cjs.map +0 -1
  29. package/src/StateObject.ts +0 -316
  30. package/src/commander.ts +0 -417
  31. package/src/commands/divider.ts +0 -20
  32. package/src/commands/index.ts +0 -24
  33. package/src/commands/mws-init-store.ts +0 -77
  34. package/src/commands/mws-listen.ts +0 -136
  35. package/src/commands/mws-load-archive.ts +0 -281
  36. package/src/commands/mws-load-plugin-bags.ts +0 -151
  37. package/src/commands/mws-load-tiddlers.ts +0 -37
  38. package/src/commands/mws-load-wiki-folder.ts +0 -124
  39. package/src/commands/mws-render-tiddlywiki5.ts +0 -55
  40. package/src/commands/mws-save-archive.ts +0 -111
  41. package/src/commands/mws-save-tiddler-text.ts +0 -33
  42. package/src/commands/tests-complete.ts +0 -21
  43. package/src/global.ts +0 -247
  44. package/src/routes/TiddlerStore.ts +0 -722
  45. package/src/routes/bag-file-server.ts +0 -340
  46. package/src/routes/cache.ts +0 -25
  47. package/src/routes/index.ts +0 -138
  48. package/src/routes/managers/index.ts +0 -17
  49. package/src/routes/managers/manager-recipes.ts +0 -438
  50. package/src/routes/managers/manager-users.ts +0 -201
  51. package/src/routes/managers/router-tiddlers.ts +0 -313
  52. package/src/routes/router.ts +0 -429
  53. package/src/routes/services/PasswordService.ts +0 -178
  54. package/src/routes/services/attachments.ts +0 -259
  55. package/src/routes/services/sessions.ts +0 -166
  56. package/src/routes/tw-test.ts +0 -65
  57. package/src/server.ts +0 -151
  58. package/src/setupDevServer.ts +0 -71
  59. package/src/streamer.ts +0 -430
  60. package/src/tiddlywiki.ts +0 -94
  61. package/src/utils/data-checks.ts +0 -172
  62. package/src/utils/index.ts +0 -4
  63. package/src/utils/rootRoute.ts +0 -237
  64. package/src/utils/utils.ts +0 -403
  65. package/src/utils/zodAssert.ts +0 -269
  66. /package/prisma/{migrations/notes.md → notes.md} +0 -0
package/dist/server.js CHANGED
@@ -50,6 +50,13 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
50
50
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
51
51
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
52
52
 
53
+ // node_modules/tsup/assets/esm_shims.js
54
+ var init_esm_shims = __esm({
55
+ "node_modules/tsup/assets/esm_shims.js"() {
56
+ "use strict";
57
+ }
58
+ });
59
+
53
60
  // src/global.ts
54
61
  import * as path from "path";
55
62
  import * as fs from "fs";
@@ -57,6 +64,7 @@ var __Result, _Result;
57
64
  var init_global = __esm({
58
65
  "src/global.ts"() {
59
66
  "use strict";
67
+ init_esm_shims();
60
68
  global.hop = function(object2, property) {
61
69
  return object2 ? Object.prototype.hasOwnProperty.call(object2, property) : false;
62
70
  };
@@ -144,8 +152,8 @@ var init_global = __esm({
144
152
  });
145
153
  };
146
154
  __Result = class __Result {
147
- constructor(ok7, error, value) {
148
- this.ok = ok7;
155
+ constructor(ok8, error, value) {
156
+ this.ok = ok8;
149
157
  this.error = error;
150
158
  this.value = value;
151
159
  }
@@ -186,6 +194,7 @@ var init_global = __esm({
186
194
  var require_depd = __commonJS({
187
195
  "node_modules/depd/index.js"(exports, module2) {
188
196
  "use strict";
197
+ init_esm_shims();
189
198
  var relative = __require("path").relative;
190
199
  module2.exports = depd;
191
200
  var basePath = process.cwd();
@@ -513,6 +522,7 @@ var require_depd = __commonJS({
513
522
  var require_setprototypeof = __commonJS({
514
523
  "node_modules/setprototypeof/index.js"(exports, module2) {
515
524
  "use strict";
525
+ init_esm_shims();
516
526
  module2.exports = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array ? setProtoOf : mixinProperties);
517
527
  function setProtoOf(obj, proto) {
518
528
  obj.__proto__ = proto;
@@ -606,6 +616,7 @@ var require_codes = __commonJS({
606
616
  var require_statuses = __commonJS({
607
617
  "node_modules/statuses/index.js"(exports, module2) {
608
618
  "use strict";
619
+ init_esm_shims();
609
620
  var codes = require_codes();
610
621
  module2.exports = status;
611
622
  status.message = codes;
@@ -682,6 +693,7 @@ var require_statuses = __commonJS({
682
693
  var require_inherits_browser = __commonJS({
683
694
  "node_modules/inherits/inherits_browser.js"(exports, module2) {
684
695
  "use strict";
696
+ init_esm_shims();
685
697
  if (typeof Object.create === "function") {
686
698
  module2.exports = /* @__PURE__ */ __name(function inherits(ctor, superCtor) {
687
699
  if (superCtor) {
@@ -715,6 +727,7 @@ var require_inherits_browser = __commonJS({
715
727
  var require_inherits = __commonJS({
716
728
  "node_modules/inherits/inherits.js"(exports, module2) {
717
729
  "use strict";
730
+ init_esm_shims();
718
731
  try {
719
732
  util = __require("util");
720
733
  if (typeof util.inherits !== "function") throw "";
@@ -730,6 +743,7 @@ var require_inherits = __commonJS({
730
743
  var require_toidentifier = __commonJS({
731
744
  "node_modules/toidentifier/index.js"(exports, module2) {
732
745
  "use strict";
746
+ init_esm_shims();
733
747
  module2.exports = toIdentifier;
734
748
  function toIdentifier(str) {
735
749
  return str.split(" ").map(function(token) {
@@ -744,6 +758,7 @@ var require_toidentifier = __commonJS({
744
758
  var require_http_errors = __commonJS({
745
759
  "node_modules/http-errors/index.js"(exports, module2) {
746
760
  "use strict";
761
+ init_esm_shims();
747
762
  var deprecate = require_depd()("http-errors");
748
763
  var setPrototypeOf = require_setprototypeof();
749
764
  var statuses = require_statuses();
@@ -920,6 +935,7 @@ var require_http_errors = __commonJS({
920
935
  var require_ms = __commonJS({
921
936
  "node_modules/ms/index.js"(exports, module2) {
922
937
  "use strict";
938
+ init_esm_shims();
923
939
  var s = 1e3;
924
940
  var m = s * 60;
925
941
  var h = m * 60;
@@ -1041,6 +1057,7 @@ var require_ms = __commonJS({
1041
1057
  var require_common = __commonJS({
1042
1058
  "node_modules/debug/src/common.js"(exports, module2) {
1043
1059
  "use strict";
1060
+ init_esm_shims();
1044
1061
  function setup(env) {
1045
1062
  createDebug.debug = createDebug;
1046
1063
  createDebug.default = createDebug;
@@ -1230,6 +1247,7 @@ var require_common = __commonJS({
1230
1247
  var require_browser = __commonJS({
1231
1248
  "node_modules/debug/src/browser.js"(exports, module2) {
1232
1249
  "use strict";
1250
+ init_esm_shims();
1233
1251
  exports.formatArgs = formatArgs;
1234
1252
  exports.save = save;
1235
1253
  exports.load = load;
@@ -1406,6 +1424,7 @@ var require_browser = __commonJS({
1406
1424
  var require_node = __commonJS({
1407
1425
  "node_modules/debug/src/node.js"(exports, module2) {
1408
1426
  "use strict";
1427
+ init_esm_shims();
1409
1428
  var tty = __require("tty");
1410
1429
  var util = __require("util");
1411
1430
  exports.init = init;
@@ -1588,6 +1607,7 @@ var require_node = __commonJS({
1588
1607
  var require_src = __commonJS({
1589
1608
  "node_modules/debug/src/index.js"(exports, module2) {
1590
1609
  "use strict";
1610
+ init_esm_shims();
1591
1611
  if (typeof process === "undefined" || process.type === "renderer" || process.browser === true || process.__nwjs) {
1592
1612
  module2.exports = require_browser();
1593
1613
  } else {
@@ -1600,6 +1620,7 @@ var require_src = __commonJS({
1600
1620
  var require_destroy = __commonJS({
1601
1621
  "node_modules/destroy/index.js"(exports, module2) {
1602
1622
  "use strict";
1623
+ init_esm_shims();
1603
1624
  var EventEmitter = __require("events").EventEmitter;
1604
1625
  var ReadStream = __require("fs").ReadStream;
1605
1626
  var Stream = __require("stream");
@@ -1698,6 +1719,7 @@ var require_destroy = __commonJS({
1698
1719
  var require_encodeurl = __commonJS({
1699
1720
  "node_modules/encodeurl/index.js"(exports, module2) {
1700
1721
  "use strict";
1722
+ init_esm_shims();
1701
1723
  module2.exports = encodeUrl;
1702
1724
  var ENCODE_CHARS_REGEXP = /(?:[^\x21\x23-\x3B\x3D\x3F-\x5F\x61-\x7A\x7C\x7E]|%(?:[^0-9A-Fa-f]|[0-9A-Fa-f][^0-9A-Fa-f]|$))+/g;
1703
1725
  var UNMATCHED_SURROGATE_PAIR_REGEXP = /(^|[^\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF]([^\uDC00-\uDFFF]|$)/g;
@@ -1713,6 +1735,7 @@ var require_encodeurl = __commonJS({
1713
1735
  var require_escape_html = __commonJS({
1714
1736
  "node_modules/escape-html/index.js"(exports, module2) {
1715
1737
  "use strict";
1738
+ init_esm_shims();
1716
1739
  var matchHtmlRegExp = /["'&<>]/;
1717
1740
  module2.exports = escapeHtml;
1718
1741
  function escapeHtml(string4) {
@@ -1761,6 +1784,7 @@ var require_escape_html = __commonJS({
1761
1784
  var require_etag = __commonJS({
1762
1785
  "node_modules/etag/index.js"(exports, module2) {
1763
1786
  "use strict";
1787
+ init_esm_shims();
1764
1788
  module2.exports = etag;
1765
1789
  var crypto = __require("crypto");
1766
1790
  var Stats = __require("fs").Stats;
@@ -1807,6 +1831,7 @@ var require_etag = __commonJS({
1807
1831
  var require_fresh = __commonJS({
1808
1832
  "node_modules/fresh/index.js"(exports, module2) {
1809
1833
  "use strict";
1834
+ init_esm_shims();
1810
1835
  var CACHE_CONTROL_NO_CACHE_REGEXP = /(?:^|,)\s*?no-cache\s*?(?:,|$)/;
1811
1836
  module2.exports = fresh;
1812
1837
  function fresh(reqHeaders, resHeaders) {
@@ -10408,6 +10433,7 @@ var require_db = __commonJS({
10408
10433
  var require_mime_db = __commonJS({
10409
10434
  "node_modules/mime-db/index.js"(exports, module2) {
10410
10435
  "use strict";
10436
+ init_esm_shims();
10411
10437
  module2.exports = require_db();
10412
10438
  }
10413
10439
  });
@@ -10416,6 +10442,7 @@ var require_mime_db = __commonJS({
10416
10442
  var require_mime_types = __commonJS({
10417
10443
  "node_modules/mime-types/index.js"(exports) {
10418
10444
  "use strict";
10445
+ init_esm_shims();
10419
10446
  var db = require_mime_db();
10420
10447
  var extname = __require("path").extname;
10421
10448
  var EXTRACT_TYPE_REGEXP = /^\s*([^;\s]*)(?:;|\s|$)/;
@@ -10511,6 +10538,7 @@ var require_mime_types = __commonJS({
10511
10538
  var require_ee_first = __commonJS({
10512
10539
  "node_modules/ee-first/index.js"(exports, module2) {
10513
10540
  "use strict";
10541
+ init_esm_shims();
10514
10542
  module2.exports = first;
10515
10543
  function first(stuff, done) {
10516
10544
  if (!Array.isArray(stuff))
@@ -10572,6 +10600,7 @@ var require_ee_first = __commonJS({
10572
10600
  var require_on_finished = __commonJS({
10573
10601
  "node_modules/on-finished/index.js"(exports, module2) {
10574
10602
  "use strict";
10603
+ init_esm_shims();
10575
10604
  module2.exports = onFinished;
10576
10605
  module2.exports.isFinished = isFinished;
10577
10606
  var asyncHooks = tryRequireAsyncHooks();
@@ -10687,6 +10716,7 @@ var require_on_finished = __commonJS({
10687
10716
  var require_range_parser = __commonJS({
10688
10717
  "node_modules/range-parser/index.js"(exports, module2) {
10689
10718
  "use strict";
10719
+ init_esm_shims();
10690
10720
  module2.exports = rangeParser;
10691
10721
  function rangeParser(size, str, options) {
10692
10722
  if (typeof str !== "string") {
@@ -10774,6 +10804,7 @@ var require_range_parser = __commonJS({
10774
10804
  var require_send = __commonJS({
10775
10805
  "node_modules/send/index.js"(exports, module2) {
10776
10806
  "use strict";
10807
+ init_esm_shims();
10777
10808
  var createError = require_http_errors();
10778
10809
  var debug = require_src()("send");
10779
10810
  var destroy = require_destroy();
@@ -10791,7 +10822,7 @@ var require_send = __commonJS({
10791
10822
  var Stream = __require("stream");
10792
10823
  var util = __require("util");
10793
10824
  var extname = path5.extname;
10794
- var join2 = path5.join;
10825
+ var join3 = path5.join;
10795
10826
  var normalize = path5.normalize;
10796
10827
  var resolve13 = path5.resolve;
10797
10828
  var sep2 = path5.sep;
@@ -10965,7 +10996,7 @@ var require_send = __commonJS({
10965
10996
  return res;
10966
10997
  }
10967
10998
  parts = path6.split(sep2);
10968
- path6 = normalize(join2(root, path6));
10999
+ path6 = normalize(join3(root, path6));
10969
11000
  } else {
10970
11001
  if (UP_PATH_REGEXP.test(path6)) {
10971
11002
  debug('malicious path "%s"', path6);
@@ -11099,7 +11130,7 @@ var require_send = __commonJS({
11099
11130
  if (err) return self.onStatError(err);
11100
11131
  return self.error(404);
11101
11132
  }
11102
- var p = join2(path6, self._index[i]);
11133
+ var p = join3(path6, self._index[i]);
11103
11134
  debug('stat "%s"', p);
11104
11135
  fs3.stat(p, function(err2, stat) {
11105
11136
  if (err2) return next(err2);
@@ -11458,6 +11489,7 @@ var _TypedGenerator, TypedGenerator, _UserError, UserError;
11458
11489
  var init_utils = __esm({
11459
11490
  "src/utils/utils.ts"() {
11460
11491
  "use strict";
11492
+ init_esm_shims();
11461
11493
  __name(readMultipartData, "readMultipartData");
11462
11494
  __name(sendResponse, "sendResponse");
11463
11495
  __name(is, "is");
@@ -11522,6 +11554,7 @@ var test1;
11522
11554
  var init_rootRoute = __esm({
11523
11555
  "src/utils/rootRoute.ts"() {
11524
11556
  "use strict";
11557
+ init_esm_shims();
11525
11558
  __name(test, "test");
11526
11559
  test1 = test({ schema: z.object({ test: z.string() }) });
11527
11560
  }
@@ -11533,6 +11566,7 @@ var _DataChecks, DataChecks;
11533
11566
  var init_data_checks = __esm({
11534
11567
  "src/utils/data-checks.ts"() {
11535
11568
  "use strict";
11569
+ init_esm_shims();
11536
11570
  init_utils();
11537
11571
  _DataChecks = class _DataChecks {
11538
11572
  constructor(options) {
@@ -11688,6 +11722,7 @@ var ZodAssert, _zodAssertAny, _zodAssert, Z2;
11688
11722
  var init_zodAssert = __esm({
11689
11723
  "src/utils/zodAssert.ts"() {
11690
11724
  "use strict";
11725
+ init_esm_shims();
11691
11726
  init_streamer();
11692
11727
  ((ZodAssert2) => {
11693
11728
  function data(state, schema, onError) {
@@ -11756,6 +11791,7 @@ var init_zodAssert = __esm({
11756
11791
  var init_utils2 = __esm({
11757
11792
  "src/utils/index.ts"() {
11758
11793
  "use strict";
11794
+ init_esm_shims();
11759
11795
  init_utils();
11760
11796
  init_rootRoute();
11761
11797
  init_data_checks();
@@ -11764,12 +11800,12 @@ var init_utils2 = __esm({
11764
11800
  });
11765
11801
 
11766
11802
  // src/streamer.ts
11767
- import * as http2 from "node:http2";
11768
11803
  import { createReadStream } from "node:fs";
11769
11804
  var import_send, SYMBOL_IGNORE_ERROR, STREAM_ENDED, _Streamer, Streamer, _StreamerState, StreamerState;
11770
11805
  var init_streamer = __esm({
11771
11806
  "src/streamer.ts"() {
11772
11807
  "use strict";
11808
+ init_esm_shims();
11773
11809
  init_global();
11774
11810
  import_send = __toESM(require_send(), 1);
11775
11811
  init_utils2();
@@ -11796,54 +11832,67 @@ var init_streamer = __esm({
11796
11832
  }), "readBody");
11797
11833
  this.headers = req.headers;
11798
11834
  this.url = req.url;
11799
- if (is(req, req.httpVersionMajor > 1)) {
11800
- this.req.headers.host = req.headers[":authority"];
11835
+ if (!this.url.startsWith("/")) throw new Error("This should never happen");
11836
+ if (router.pathPrefix) {
11837
+ if (this.url === router.pathPrefix) {
11838
+ res.writeHead(302, { "location": req.url + "/" }).end();
11839
+ throw STREAM_ENDED;
11840
+ } else if (this.url.startsWith(router.pathPrefix)) {
11841
+ this.url = this.url.slice(router.pathPrefix.length);
11842
+ } else {
11843
+ res.writeHead(500, {}).end("The server is setup with a path prefix " + router.pathPrefix + ", but this request is outside of that prefix.", "utf8");
11844
+ throw STREAM_ENDED;
11845
+ }
11801
11846
  }
11847
+ if (is(req, req.httpVersionMajor > 1))
11848
+ req.headers.host = req.headers[":authority"];
11802
11849
  if (!req.headers.host) throw new Error("This should never happen");
11803
- if (!req.method) throw new Error("This should never happen");
11804
- if (!req.url?.startsWith("/")) throw new Error("This should never happen");
11805
- if (!is(req.method, AllowedMethods.includes(req.method)))
11806
- throw this.sendString(501, {}, "Method not supported", "utf8");
11807
11850
  this.host = req.headers.host;
11851
+ if (!req.method) throw new Error("This should never happen");
11852
+ if (!is(req.method, AllowedMethods.includes(req.method))) {
11853
+ res.writeHead(501, {}).end("Method not supported", "utf8");
11854
+ throw STREAM_ENDED;
11855
+ }
11808
11856
  this.method = req.method;
11809
11857
  this.isSecure = !!req.socket.encrypted;
11810
- this.urlInfo = new URL(`https://${req.headers.host}${req.url}`);
11858
+ this.urlInfo = new URL(`https://${this.headers.host}${this.url}`);
11811
11859
  this.cookies = this.parseCookieString(req.headers.cookie || "");
11860
+ if (this.cookies.getAll("session").length > 1) {
11861
+ console.warn("Multiple session cookies found. This is very likely to cause problems. This may happen after changing the path prefix.");
11862
+ }
11812
11863
  }
11813
11864
  // RIP Push Stream. it was a great idea.
11814
- async pushStream(path5) {
11815
- return new Promise((resolve13, reject) => {
11816
- const req2 = this.req;
11817
- if (!req2.stream || !req2.stream.pushAllowed) return reject();
11818
- req2.stream.write;
11819
- const newRawHeaders = this.req.rawHeaders.slice();
11820
- for (let i = 0; i < newRawHeaders.length; i += 2) {
11821
- if (newRawHeaders[i] === ":method") newRawHeaders[i + 1] = "GET";
11822
- if (newRawHeaders[i] === ":path") newRawHeaders[i + 1] = path5;
11823
- }
11824
- req2.stream.pushStream({ ":method": "GET", ":path": path5 }, (err, pushStream, headers) => {
11825
- if (err) return reject(err);
11826
- const preq = new http2.Http2ServerRequest(pushStream, req2.headers, {}, newRawHeaders);
11827
- const pres = new http2.Http2ServerResponse(pushStream);
11828
- const pushStreamer = new _Streamer(preq, pres, this.router);
11829
- resolve13(pushStreamer);
11830
- });
11831
- }).then(async (streamer) => {
11832
- await this.router.handle(streamer);
11833
- return streamer;
11834
- }, (err) => {
11835
- if (err) throw err;
11836
- });
11837
- }
11865
+ // async pushStream(path: string) {
11866
+ // return new Promise<Streamer>((resolve, reject) => {
11867
+ // const req2: http2.Http2ServerRequest = this.req as any;
11868
+ // if (!req2.stream || !req2.stream.pushAllowed) return reject();
11869
+ // req2.stream.write
11870
+ // const newRawHeaders = this.req.rawHeaders.slice();
11871
+ // for (let i = 0; i < newRawHeaders.length; i += 2) {
11872
+ // if (newRawHeaders[i] === ":method") newRawHeaders[i + 1] = "GET";
11873
+ // if (newRawHeaders[i] === ":path") newRawHeaders[i + 1] = path;
11874
+ // }
11875
+ // req2.stream.pushStream({ ":method": "GET", ":path": path }, (err, pushStream, headers) => {
11876
+ // if (err) return reject(err);
11877
+ // const preq = new http2.Http2ServerRequest(pushStream, req2.headers, {}, newRawHeaders);
11878
+ // const pres = new http2.Http2ServerResponse(pushStream);
11879
+ // const pushStreamer = new Streamer(preq, pres, this.router);
11880
+ // resolve(pushStreamer);
11881
+ // });
11882
+ // }).then(async streamer => {
11883
+ // await this.router.handle(streamer);
11884
+ // return streamer;
11885
+ // }, (err) => { if (err) throw err; });
11886
+ // }
11838
11887
  parseCookieString(cookieString) {
11839
- const cookies = {};
11888
+ const cookies = new URLSearchParams();
11840
11889
  if (typeof cookieString !== "string") throw new Error("cookieString must be a string");
11841
11890
  cookieString.split(";").forEach((cookie) => {
11842
11891
  const parts = cookie.split("=");
11843
11892
  if (parts.length >= 2) {
11844
11893
  const key = parts[0].trim();
11845
11894
  const value = parts.slice(1).join("=").trim();
11846
- cookies[key] = decodeURIComponent(value);
11895
+ cookies.append(key, decodeURIComponent(value));
11847
11896
  }
11848
11897
  });
11849
11898
  return cookies;
@@ -12100,6 +12149,7 @@ var _StateObject, StateObject, zodURIComponent;
12100
12149
  var init_StateObject = __esm({
12101
12150
  "src/StateObject.ts"() {
12102
12151
  "use strict";
12152
+ init_esm_shims();
12103
12153
  init_utils2();
12104
12154
  init_streamer();
12105
12155
  init_utils2();
@@ -12308,6 +12358,7 @@ var RecipeKeyMap, _RecipeManager, RecipeManager;
12308
12358
  var init_manager_recipes = __esm({
12309
12359
  "src/routes/managers/manager-recipes.ts"() {
12310
12360
  "use strict";
12361
+ init_esm_shims();
12311
12362
  init_router();
12312
12363
  init_utils2();
12313
12364
  RecipeKeyMap = {
@@ -12655,6 +12706,8 @@ var UserKeyMap, _UserManager, UserManager;
12655
12706
  var init_manager_users = __esm({
12656
12707
  "src/routes/managers/manager-users.ts"() {
12657
12708
  "use strict";
12709
+ init_esm_shims();
12710
+ init_server();
12658
12711
  init_router();
12659
12712
  UserKeyMap = {
12660
12713
  user_edit_data: true,
@@ -12717,12 +12770,12 @@ var init_manager_users = __esm({
12717
12770
  this.user_create = zodManage((z5) => z5.object({
12718
12771
  username: z5.string(),
12719
12772
  email: z5.string(),
12720
- role_id: z5.prismaField("Roles", "role_id", "number", false)
12773
+ role_ids: z5.prismaField("Roles", "role_id", "number", false).array()
12721
12774
  }), async (state, prisma) => {
12722
- const { username, email, role_id } = state.data;
12775
+ const { username, email, role_ids } = state.data;
12723
12776
  state.okAdmin();
12724
12777
  const user = await prisma.users.create({
12725
- data: { username, email, password: "", roles: { connect: { role_id } } },
12778
+ data: { username, email, password: "", roles: { connect: role_ids.map((role_id) => ({ role_id })) } },
12726
12779
  select: { user_id: true, created_at: true }
12727
12780
  });
12728
12781
  return user;
@@ -12731,14 +12784,14 @@ var init_manager_users = __esm({
12731
12784
  user_id: z5.number(),
12732
12785
  username: z5.string(),
12733
12786
  email: z5.string(),
12734
- role_id: z5.prismaField("Roles", "role_id", "number").optional()
12787
+ role_ids: z5.prismaField("Roles", "role_id", "number").array()
12735
12788
  }), async (state, prisma) => {
12736
- const { user_id, username, email, role_id } = state.data;
12789
+ const { user_id, username, email, role_ids } = state.data;
12737
12790
  state.okAdmin();
12738
12791
  if (state.user.user_id === user_id) throw "Admin cannot update themselves";
12739
12792
  await prisma.users.update({
12740
12793
  where: { user_id },
12741
- data: { username, email, roles: { set: [{ role_id }] } }
12794
+ data: { username, email, roles: { set: role_ids.map((role_id) => ({ role_id })) } }
12742
12795
  });
12743
12796
  return null;
12744
12797
  });
@@ -12756,12 +12809,29 @@ var init_manager_users = __esm({
12756
12809
  this.user_update_password = zodManage((z5) => z5.object({
12757
12810
  user_id: z5.prismaField("Users", "user_id", "number"),
12758
12811
  registrationRequest: z5.string().optional(),
12759
- registrationRecord: z5.string().optional()
12812
+ registrationRecord: z5.string().optional(),
12813
+ session_id: z5.string().optional(),
12814
+ signature: z5.string().optional()
12760
12815
  }), async (state, prisma) => {
12761
12816
  const { user_id, registrationRecord, registrationRequest } = state.data;
12762
12817
  state.okUser();
12763
- if (state.user.user_id !== user_id && !state.user.isAdmin)
12764
- throw "You must be an admin to update another user's password";
12818
+ if (!state.user.isAdmin) {
12819
+ if (!state.data) throw "Session id and signature are required";
12820
+ const session = await prisma.sessions.findUnique({
12821
+ where: { session_id: state.data.session_id }
12822
+ });
12823
+ if (!session?.session_key)
12824
+ throw "Session not found";
12825
+ const { session_key } = session;
12826
+ const { session_id, signature } = state.data;
12827
+ if (!session_id || !signature)
12828
+ throw "Session id and signature are required";
12829
+ assertSignature({ session_id, session_key, signature });
12830
+ if (session.user_id !== user_id)
12831
+ throw "You must be an admin to update another user's password";
12832
+ if (state.user.user_id !== user_id)
12833
+ throw "You must be logged in as this user to update the password, but normally this isn't supposed to happen (this is a bug, please report it)";
12834
+ }
12765
12835
  const userExists = await prisma.users.count({ where: { user_id } });
12766
12836
  if (!userExists) throw "User does not exist";
12767
12837
  if (registrationRequest) {
@@ -12823,6 +12893,7 @@ var ManagerRoutes;
12823
12893
  var init_managers = __esm({
12824
12894
  "src/routes/managers/index.ts"() {
12825
12895
  "use strict";
12896
+ init_esm_shims();
12826
12897
  init_manager_recipes();
12827
12898
  init_manager_users();
12828
12899
  init_manager_users();
@@ -12840,6 +12911,7 @@ var _TiddlerStore, TiddlerStore;
12840
12911
  var init_TiddlerStore = __esm({
12841
12912
  "src/routes/TiddlerStore.ts"() {
12842
12913
  "use strict";
12914
+ init_esm_shims();
12843
12915
  init_utils2();
12844
12916
  _TiddlerStore = class _TiddlerStore {
12845
12917
  constructor(commander, prisma) {
@@ -13244,6 +13316,7 @@ var init_TiddlerStore = __esm({
13244
13316
  var require_sjcl = __commonJS({
13245
13317
  "node_modules/sjcl/sjcl.js"(exports, module2) {
13246
13318
  "use strict";
13319
+ init_esm_shims();
13247
13320
  var sjcl3 = { cipher: {}, hash: {}, keyexchange: {}, mode: {}, misc: {}, codec: {}, exception: { corrupt: /* @__PURE__ */ __name(function(a) {
13248
13321
  this.toString = function() {
13249
13322
  return "CORRUPT: " + this.message;
@@ -14015,6 +14088,7 @@ var import_sjcl, _TiddlerServer, TiddlerServer;
14015
14088
  var init_bag_file_server = __esm({
14016
14089
  "src/routes/bag-file-server.ts"() {
14017
14090
  "use strict";
14091
+ init_esm_shims();
14018
14092
  init_TiddlerStore();
14019
14093
  import_sjcl = __toESM(require_sjcl(), 1);
14020
14094
  _TiddlerServer = class _TiddlerServer extends TiddlerStore {
@@ -14022,7 +14096,7 @@ var init_bag_file_server = __esm({
14022
14096
  super(state.commander, prisma);
14023
14097
  this.state = state;
14024
14098
  }
14025
- toTiddlyWebJson(info10) {
14099
+ toTiddlyWebJson(info11) {
14026
14100
  const output = { fields: {} };
14027
14101
  const knownFields = [
14028
14102
  "bag",
@@ -14039,16 +14113,16 @@ var init_bag_file_server = __esm({
14039
14113
  "type",
14040
14114
  "uri"
14041
14115
  ];
14042
- each(info10.tiddler, (field, name) => {
14116
+ each(info11.tiddler, (field, name) => {
14043
14117
  if (knownFields.indexOf(name) !== -1) {
14044
14118
  output[name] = field;
14045
14119
  } else {
14046
14120
  output.fields[name] = field;
14047
14121
  }
14048
14122
  });
14049
- output.type = info10.tiddler.type || "text/vnd.tiddlywiki";
14050
- output.revision = `${info10.tiddler_id}`;
14051
- output.bag = info10.bag_name;
14123
+ output.type = info11.tiddler.type || "text/vnd.tiddlywiki";
14124
+ output.revision = `${info11.tiddler_id}`;
14125
+ output.bag = info11.bag_name;
14052
14126
  return output;
14053
14127
  }
14054
14128
  /** If neither bag_name nor bag_id are specified, the fallback will be sent. */
@@ -14265,6 +14339,10 @@ var init_bag_file_server = __esm({
14265
14339
  title: "$:/state/multiwikiclient/recipe/last_tiddler_id",
14266
14340
  text: (lastTiddlerId._max.tiddler_id ?? 0).toString()
14267
14341
  });
14342
+ writeTiddler({
14343
+ title: "$:/config/multiwikiclient/host",
14344
+ text: "$protocol$//$host$" + this.state.config.pathPrefix + "/"
14345
+ });
14268
14346
  state.write(template.substring(markerPos + marker.length));
14269
14347
  return state.end();
14270
14348
  }
@@ -14284,6 +14362,7 @@ var TiddlerKeyMap, _TiddlerRouter, TiddlerRouter;
14284
14362
  var init_router_tiddlers = __esm({
14285
14363
  "src/routes/managers/router-tiddlers.ts"() {
14286
14364
  "use strict";
14365
+ init_esm_shims();
14287
14366
  init_streamer();
14288
14367
  init_utils2();
14289
14368
  init_router();
@@ -14532,551 +14611,187 @@ var init_router_tiddlers = __esm({
14532
14611
  }
14533
14612
  });
14534
14613
 
14535
- // src/routes/services/PasswordService.ts
14536
- var PasswordService_exports = {};
14537
- __export(PasswordService_exports, {
14538
- createPasswordService: () => createPasswordService
14539
- });
14540
- import * as opaque from "@serenity-kit/opaque";
14541
- import { randomBytes } from "node:crypto";
14542
- async function createPasswordService(serverSetup) {
14543
- await opaque.ready;
14544
- const serverState = /* @__PURE__ */ new Map();
14545
- const LoginGenerator = TypedGenerator.wrapper()(async function* ({
14546
- user_id,
14547
- startLoginRequest,
14548
- registrationRecord
14549
- }) {
14550
- const { asV, asY } = TypedGenerator.checker();
14551
- const { serverLoginState, loginResponse } = opaque.server.startLogin({
14552
- serverSetup,
14553
- userIdentifier: user_id.toString(),
14554
- registrationRecord,
14555
- startLoginRequest
14556
- });
14557
- const timestamp = Date.now();
14558
- const finishLoginRequest = asV(1, yield asY(0, loginResponse));
14559
- if (timestamp + 1e3 * 60 * 5 < Date.now()) return;
14560
- return asY(1, {
14561
- session: opaque.server.finishLogin({
14562
- finishLoginRequest,
14563
- serverLoginState
14564
- }),
14565
- user_id
14566
- });
14567
- });
14568
- async function PasswordCreation(userID, password) {
14569
- const { clientRegistrationState, registrationRequest } = opaque.client.startRegistration({ password });
14570
- const userIdentifier = userID;
14571
- const { registrationResponse } = opaque.server.createRegistrationResponse({
14572
- serverSetup,
14573
- userIdentifier,
14574
- registrationRequest
14575
- });
14576
- const { registrationRecord } = opaque.client.finishRegistration({
14577
- clientRegistrationState,
14578
- registrationResponse,
14579
- password
14614
+ // import("./**/*/**/*") in src/routes/index.ts
14615
+ var globImport;
14616
+ var init_ = __esm({
14617
+ 'import("./**/*/**/*") in src/routes/index.ts'() {
14618
+ globImport = __glob({
14619
+ "./managers/index.ts": () => Promise.resolve().then(() => (init_managers(), managers_exports)),
14620
+ "./managers/manager-recipes.ts": () => Promise.resolve().then(() => (init_manager_recipes(), manager_recipes_exports)),
14621
+ "./managers/manager-users.ts": () => Promise.resolve().then(() => (init_manager_users(), manager_users_exports)),
14622
+ "./managers/router-tiddlers.ts": () => Promise.resolve().then(() => (init_router_tiddlers(), router_tiddlers_exports))
14580
14623
  });
14581
- return registrationRecord;
14582
14624
  }
14583
- __name(PasswordCreation, "PasswordCreation");
14584
- async function createRegistrationResponse({ userID, registrationRequest }) {
14585
- const { registrationResponse } = opaque.server.createRegistrationResponse({
14586
- serverSetup,
14587
- userIdentifier: userID.toString(),
14588
- registrationRequest
14625
+ });
14626
+
14627
+ // src/routes/index.ts
14628
+ import { Prisma } from "@prisma/client";
14629
+ async function RootRoute(root, config) {
14630
+ TiddlerRouter.defineRoutes(root);
14631
+ ManagerRoutes(root, config);
14632
+ if (typeof ENABLE_UNSAFE_PRISMA_ROUTE !== "undefined")
14633
+ root.defineRoute({
14634
+ method: ["POST"],
14635
+ path: /^\/prisma$/,
14636
+ bodyFormat: "json"
14637
+ }, async (state) => {
14638
+ ZodAssert.data(state, (z5) => z5.object({
14639
+ table: z5.string(),
14640
+ action: z5.string(),
14641
+ arg: z5.any()
14642
+ }));
14643
+ return await state.$transaction(async (prisma) => {
14644
+ const p = prisma;
14645
+ const table = p[state.data.table];
14646
+ if (!table) throw new Error(`No such table`);
14647
+ const fn = table[state.data.action];
14648
+ if (!fn) throw new Error(`No such table or action`);
14649
+ console.log(state.data.arg);
14650
+ return state.sendJSON(200, await fn.call(table, state.data.arg));
14651
+ });
14589
14652
  });
14590
- return registrationResponse;
14591
- }
14592
- __name(createRegistrationResponse, "createRegistrationResponse");
14593
- async function startLoginSession(stater) {
14594
- let loginSession;
14595
- do {
14596
- loginSession = randomBytes(16).toString("base64url");
14597
- } while (serverState.has(loginSession));
14598
- serverState.set(loginSession, stater);
14599
- return loginSession;
14653
+ await importEsbuild(root);
14654
+ }
14655
+ async function importEsbuild(root) {
14656
+ root.defineRoute({
14657
+ method: ["GET"],
14658
+ path: /^\/.*/,
14659
+ bodyFormat: "stream"
14660
+ }, async (state) => {
14661
+ await state.sendDevServer();
14662
+ });
14663
+ }
14664
+ function findValueInObject(val, predicate, keys = [], paths = []) {
14665
+ if (predicate(val)) {
14666
+ paths.push(keys.join("/"));
14667
+ return paths;
14600
14668
  }
14601
- __name(startLoginSession, "startLoginSession");
14602
- async function finishLoginSession(loginSession) {
14603
- const stater = serverState.get(loginSession);
14604
- if (stater) serverState.delete(loginSession);
14605
- return stater;
14669
+ if (val && typeof val === "object") {
14670
+ for (const key of Object.keys(val)) {
14671
+ if (!val.hasOwnProperty(key)) continue;
14672
+ findValueInObject(val[key], predicate, [...keys, key], paths);
14673
+ }
14606
14674
  }
14607
- __name(finishLoginSession, "finishLoginSession");
14608
- return {
14609
- serverState,
14610
- LoginGenerator,
14611
- PasswordCreation,
14612
- createRegistrationResponse,
14613
- startLoginSession,
14614
- finishLoginSession
14615
- };
14675
+ console.log(paths, keys);
14676
+ return paths;
14616
14677
  }
14617
- var init_PasswordService = __esm({
14618
- "src/routes/services/PasswordService.ts"() {
14678
+ function capitalize(table) {
14679
+ return table.slice(0, 1).toUpperCase() + table.slice(1);
14680
+ }
14681
+ var _error, _ProxyPromise, ProxyPromise, argproxy;
14682
+ var init_routes = __esm({
14683
+ "src/routes/index.ts"() {
14619
14684
  "use strict";
14685
+ init_esm_shims();
14620
14686
  init_utils2();
14621
- __name(createPasswordService, "createPasswordService");
14687
+ init_managers();
14688
+ init_router_tiddlers();
14689
+ init_();
14690
+ __name(RootRoute, "RootRoute");
14691
+ __name(importEsbuild, "importEsbuild");
14692
+ _ProxyPromise = class _ProxyPromise {
14693
+ constructor({ action, table, arg }) {
14694
+ __privateAdd(this, _error, new Error("An error occured for this request"));
14695
+ this.action = action;
14696
+ this.table = table;
14697
+ this.arg = arg;
14698
+ Object.defineProperty(this, "toJSON", {
14699
+ configurable: true,
14700
+ enumerable: true,
14701
+ value: /* @__PURE__ */ __name(() => ({
14702
+ action: this.action,
14703
+ table: this.table,
14704
+ arg: this.arg,
14705
+ dbnulls: this.arg.data && findValueInObject(this.arg.data, (e) => e === Prisma.DbNull),
14706
+ jsnulls: this.arg.data && findValueInObject(this.arg.data, (e) => e === Prisma.JsonNull)
14707
+ }), "value")
14708
+ });
14709
+ }
14710
+ static getErrorStack(t) {
14711
+ return __privateGet(t, _error).stack;
14712
+ }
14713
+ };
14714
+ _error = new WeakMap();
14715
+ __name(_ProxyPromise, "ProxyPromise");
14716
+ ProxyPromise = _ProxyPromise;
14717
+ __name(findValueInObject, "findValueInObject");
14718
+ __name(capitalize, "capitalize");
14719
+ argproxy = (() => new Proxy({}, {
14720
+ get(target, table) {
14721
+ return target[table] = target[table] || new Proxy({}, {
14722
+ get(target2, action) {
14723
+ return target2[action] = target2[action] || ((arg) => {
14724
+ return new ProxyPromise({ action, table: capitalize(table), arg });
14725
+ });
14726
+ }
14727
+ });
14728
+ }
14729
+ }))();
14622
14730
  }
14623
14731
  });
14624
14732
 
14625
- // src/routes/services/attachments.ts
14626
- var attachments_exports = {};
14627
- __export(attachments_exports, {
14628
- AttachmentService: () => AttachmentService
14629
- });
14630
- import * as path3 from "path";
14631
- import * as fs2 from "fs";
14632
- var import_sjcl2, $tw, _AttachmentService, AttachmentService;
14633
- var init_attachments = __esm({
14634
- "src/routes/services/attachments.ts"() {
14635
- "use strict";
14636
- init_utils2();
14637
- import_sjcl2 = __toESM(require_sjcl(), 1);
14638
- $tw = {};
14639
- _AttachmentService = class _AttachmentService {
14640
- constructor(config, prisma) {
14641
- this.config = config;
14642
- this.prisma = prisma;
14643
- }
14644
- makeCanonicalUri(bag_name, title) {
14645
- return `/bags/${encodeURIComponentExtended(bag_name)}/tiddlers/${encodeURIComponentExtended(title)}/blob`;
14733
+ // src/setupDevServer.ts
14734
+ import { request } from "http";
14735
+ import { join, resolve as resolve3 } from "path";
14736
+ import { createHash as createHash3 } from "crypto";
14737
+ import { readFile } from "fs/promises";
14738
+ import { writeFileSync } from "fs";
14739
+ async function setupDevServer(enableDevServer, pathPrefix) {
14740
+ const index_file = Buffer.from(`
14741
+ <!DOCTYPE html>
14742
+
14743
+ <head>
14744
+ <style>
14745
+ @media (prefers-color-scheme: dark) {
14746
+ html:not(.loaded) {
14747
+ background-color: #121212;
14646
14748
  }
14647
- /*
14648
- Given tiddler fields, tiddler_id and a bag_name, return the tiddler fields after the following process:
14649
- - Apply the tiddler_id as the revision field
14650
- - Apply the bag_name as the bag field
14651
- */
14652
- processOutgoingTiddler({ tiddler, tiddler_id, bag_name, attachment_hash }) {
14653
- if (attachment_hash !== null) {
14654
- return Object.assign(
14655
- {},
14656
- tiddler,
14657
- {
14658
- text: void 0,
14659
- _canonical_uri: this.makeCanonicalUri(bag_name, tiddler.title),
14660
- revision: tiddler_id,
14661
- bag: bag_name
14662
- }
14663
- );
14664
- } else {
14665
- return tiddler;
14666
- }
14749
+ }
14750
+
14751
+ @media (prefers-color-scheme: light) {
14752
+ html:not(.loaded) {
14753
+ background-color: #ffffff;
14667
14754
  }
14668
- /*
14669
- */
14670
- async processIncomingTiddler({
14671
- tiddlerFields,
14672
- existing_attachment_hash,
14673
- existing_canonical_uri
14674
- }) {
14675
- const { attachmentSizeLimit, attachmentsEnabled } = this.config;
14676
- const contentTypeInfo = this.config.contentTypeInfo[tiddlerFields.type || "text/vnd.tiddlywiki"];
14677
- const isBinary = !!contentTypeInfo && contentTypeInfo.encoding === "base64";
14678
- let shouldProcessAttachment = tiddlerFields.text && tiddlerFields.text.length > attachmentSizeLimit;
14679
- if (existing_attachment_hash) {
14680
- const fileSize = await this.getAttachmentFileSize(existing_attachment_hash);
14681
- if (fileSize && fileSize <= attachmentSizeLimit) {
14682
- const existingAttachmentMeta = await this.getAttachmentMetadata(existing_attachment_hash);
14683
- const hasCanonicalField = !!tiddlerFields._canonical_uri;
14684
- const skipAttachment = hasCanonicalField && tiddlerFields._canonical_uri === (existingAttachmentMeta ? existingAttachmentMeta._canonical_uri : existing_canonical_uri);
14685
- shouldProcessAttachment = !skipAttachment;
14686
- } else {
14687
- shouldProcessAttachment = false;
14688
- }
14689
- }
14690
- if (attachmentsEnabled && isBinary && shouldProcessAttachment) {
14691
- const attachment_hash = existing_attachment_hash || await this.saveAttachment({
14692
- text: tiddlerFields.text,
14693
- type: tiddlerFields.type,
14694
- reference: tiddlerFields.title,
14695
- _canonical_uri: tiddlerFields._canonical_uri
14696
- });
14697
- if (tiddlerFields && tiddlerFields._canonical_uri) {
14698
- delete tiddlerFields._canonical_uri;
14699
- }
14700
- return {
14701
- tiddlerFields: Object.assign({}, tiddlerFields, { text: void 0 }),
14702
- attachment_hash
14703
- };
14704
- } else {
14705
- return {
14706
- tiddlerFields,
14707
- attachment_hash: existing_attachment_hash
14708
- };
14709
- }
14710
- }
14711
- /*
14712
- Check if an attachment name is valid (is a 64 character hex string)
14713
- */
14714
- isValidAttachmentName(content_hash) {
14715
- const re = new RegExp("^[a-f0-9]{64}$");
14716
- return re.test(content_hash);
14717
- }
14718
- /*
14719
- Saves an attachment to a file. Options include:
14720
-
14721
- text: text content (may be binary)
14722
- type: MIME type of content
14723
- reference: reference to use for debugging
14724
- _canonical_uri: canonical uri of the content
14725
- */
14726
- async saveAttachment(options) {
14727
- const contentHash = import_sjcl2.default.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(options.text)).slice(0, 64).toString();
14728
- const contentTypeInfo = this.config.contentTypeInfo[options.type] || this.config.contentTypeInfo["application/octet-stream"];
14729
- const attachmentPath = path3.resolve(this.config.storePath, "files", contentHash);
14730
- createDirectory(attachmentPath);
14731
- const dataFilename = "data" + contentTypeInfo.extension;
14732
- fs2.writeFileSync(path3.resolve(attachmentPath, dataFilename), options.text, contentTypeInfo.encoding);
14733
- this.writeMetaFile(fs2, path3, attachmentPath, options, contentHash, dataFilename);
14734
- return contentHash;
14735
- }
14736
- writeMetaFile(fs3, path5, attachmentPath, options, contentHash, dataFilename) {
14737
- fs3.writeFileSync(path5.resolve(attachmentPath, "meta.json"), JSON.stringify({
14738
- _canonical_uri: options._canonical_uri,
14739
- created: (/* @__PURE__ */ new Date()).toISOString(),
14740
- modified: (/* @__PURE__ */ new Date()).toISOString(),
14741
- contentHash,
14742
- filename: dataFilename,
14743
- type: options.type
14744
- }, null, 4));
14745
- }
14746
- /*
14747
- Adopts an attachment file into the store (e.g. move from a temp upload directory)
14748
- */
14749
- async adoptAttachment({ incomingFilepath, type, hash, _canonical_uri }) {
14750
- const contentTypeInfo = this.config.contentTypeInfo[type] || this.config.contentTypeInfo["application/octet-stream"];
14751
- const attachmentPath = path3.resolve(this.config.storePath, "files", hash);
14752
- createDirectory(attachmentPath);
14753
- const dataFilename = "data" + contentTypeInfo.extension, dataFilepath = path3.resolve(attachmentPath, dataFilename);
14754
- fs2.renameSync(incomingFilepath, dataFilepath);
14755
- fs2.writeFileSync(path3.resolve(attachmentPath, "meta.json"), JSON.stringify({
14756
- _canonical_uri,
14757
- created: (/* @__PURE__ */ new Date()).toISOString(),
14758
- modified: (/* @__PURE__ */ new Date()).toISOString(),
14759
- contentHash: hash,
14760
- filename: dataFilename,
14761
- type
14762
- }, null, 4));
14763
- return hash;
14764
- }
14765
- /*
14766
- Get an attachment ready to stream. Returns null if there is an error or:
14767
- stream: filestream of file
14768
- type: type of file
14769
- */
14770
- async getAttachmentStream(content_hash) {
14771
- if (!this.isValidAttachmentName(content_hash)) return null;
14772
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
14773
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
14774
- if (!fs2.existsSync(metaJsonPath) || !fs2.statSync(metaJsonPath).isFile()) return null;
14775
- const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
14776
- if (!meta) return null;
14777
- const dataFilepath = path3.resolve(attachmentPath, meta.filename);
14778
- if (!fs2.existsSync(dataFilepath) || !fs2.statSync(dataFilepath).isFile()) return null;
14779
- return {
14780
- stream: fs2.createReadStream(dataFilepath),
14781
- type: meta.type
14782
- };
14783
- }
14784
- /*
14785
- Get the size of an attachment file given the contentHash.
14786
- Returns the size in bytes, or null if the file doesn't exist.
14787
- */
14788
- async getAttachmentFileSize(content_hash) {
14789
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
14790
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
14791
- if (!(fs2.existsSync(metaJsonPath) && fs2.statSync(metaJsonPath).isFile())) return null;
14792
- const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
14793
- if (!meta) return null;
14794
- const dataFilepath = path3.resolve(attachmentPath, meta.filename);
14795
- if (!(fs2.existsSync(dataFilepath) && fs2.statSync(dataFilepath).isFile())) return null;
14796
- return fs2.statSync(dataFilepath).size;
14797
- }
14798
- async getAttachmentMetadata(content_hash) {
14799
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
14800
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
14801
- if (!fs2.existsSync(metaJsonPath)) return null;
14802
- return JSON.parse(fs2.readFileSync(metaJsonPath, "utf8"));
14803
- }
14804
- };
14805
- __name(_AttachmentService, "AttachmentService");
14806
- AttachmentService = _AttachmentService;
14807
- }
14808
- });
14809
-
14810
- // src/routes/services/sessions.ts
14811
- var sessions_exports = {};
14812
- __export(sessions_exports, {
14813
- SessionKeyMap: () => SessionKeyMap,
14814
- SessionManager: () => SessionManager,
14815
- zodSession: () => zodSession
14816
- });
14817
- import { randomBytes as randomBytes2 } from "node:crypto";
14818
- function zodSession(path5, zodRequest, inner) {
14819
- return zodRoute(["POST"], path5, (z5) => ({}), "json", zodRequest, async (state) => {
14820
- return state.$transaction(async (prisma) => await inner(state, prisma));
14821
- });
14822
- }
14823
- var SessionKeyMap, _SessionManager, SessionManager;
14824
- var init_sessions = __esm({
14825
- "src/routes/services/sessions.ts"() {
14826
- "use strict";
14827
- init_router();
14828
- SessionKeyMap = {
14829
- login1: true,
14830
- login2: true,
14831
- logout: true
14832
- };
14833
- __name(zodSession, "zodSession");
14834
- _SessionManager = class _SessionManager {
14835
- constructor() {
14836
- this.login1 = zodSession("/login/1", (z5) => z5.object({
14837
- username: z5.prismaField("Users", "username", "string"),
14838
- startLoginRequest: z5.string()
14839
- }), async (state, prisma) => {
14840
- const { username, startLoginRequest } = state.data;
14841
- const user = await prisma.users.findUnique({
14842
- where: { username },
14843
- select: { user_id: true, password: true }
14844
- });
14845
- if (!user) throw "User not found.";
14846
- const { user_id, password } = user;
14847
- const stater = state.PasswordService.LoginGenerator({
14848
- user_id,
14849
- startLoginRequest,
14850
- registrationRecord: password
14851
- });
14852
- const loginResponse = await stater.next(0);
14853
- if (loginResponse.done) throw "Login failed.";
14854
- const loginSession = await state.PasswordService.startLoginSession(stater);
14855
- state.setCookie("loginsession", loginSession, { httpOnly: true, path: "/", secure: state.isSecure, sameSite: "Strict" });
14856
- return { loginResponse: loginResponse.value };
14857
- });
14858
- this.login2 = zodSession("/login/2", (z5) => z5.object({
14859
- finishLoginRequest: z5.string()
14860
- }), async (state, prisma) => {
14861
- const { finishLoginRequest } = state.data;
14862
- if (!state.cookies.loginsession) throw "Login session not found.";
14863
- const stater = state.PasswordService.serverState.get(state.cookies.loginsession);
14864
- if (!stater) throw "Login session not found.";
14865
- const { done, value } = await stater.next(1, finishLoginRequest);
14866
- if (!value?.session?.sessionKey) throw "Login failed.";
14867
- const session_id = await this.createSession(prisma, value.user_id, value.session.sessionKey);
14868
- state.setCookie("session", session_id, { httpOnly: true, path: "/", secure: state.isSecure, sameSite: "Strict" });
14869
- return null;
14870
- });
14871
- this.logout = zodSession("/logout", (z5) => z5.undefined(), async (state, prisma) => {
14872
- if (state.user.isLoggedIn) {
14873
- await prisma.sessions.delete({ where: { session_id: state.user.sessionId } });
14874
- }
14875
- var cookies = state.headers.cookie ? state.headers.cookie.split(";") : [];
14876
- for (var i = 0; i < cookies.length; i++) {
14877
- var cookie = cookies[i]?.trim().split("=")[0];
14878
- if (!cookie) continue;
14879
- state.setCookie(cookie, "", { httpOnly: true, path: "/", expires: /* @__PURE__ */ new Date(0), secure: state.isSecure, sameSite: "Strict" });
14880
- }
14881
- return null;
14882
- });
14883
- }
14884
- static async defineRoutes(root) {
14885
- registerZodRoutes(root, new _SessionManager(), Object.keys(SessionKeyMap));
14886
- }
14887
- static async parseIncomingRequest(streamer, router) {
14888
- const sessionId = streamer.cookies.session;
14889
- const session = sessionId && await router.engine.sessions.findUnique({
14890
- where: { session_id: sessionId },
14891
- select: { user: { select: { user_id: true, username: true, roles: { select: { role_id: true } } } } }
14892
- });
14893
- if (sessionId && session) return {
14894
- user_id: session.user.user_id,
14895
- username: session.user.username,
14896
- isAdmin: session.user.roles.some((e) => e.role_id === 1),
14897
- role_ids: session.user.roles.map((e) => e.role_id),
14898
- sessionId,
14899
- isLoggedIn: true
14900
- };
14901
- else return {
14902
- user_id: 0,
14903
- username: "(anon)",
14904
- isAdmin: false,
14905
- role_ids: [],
14906
- sessionId: void 0,
14907
- isLoggedIn: false
14908
- };
14909
- }
14910
- async createSession(prisma, user_id, session_key) {
14911
- const session_id = randomBytes2(16).toString("base64url");
14912
- return await prisma.sessions.create({
14913
- data: {
14914
- user_id,
14915
- session_key,
14916
- session_id,
14917
- last_accessed: /* @__PURE__ */ new Date()
14918
- }
14919
- }).then(({ session_id: session_id2 }) => session_id2);
14920
- }
14921
- };
14922
- __name(_SessionManager, "SessionManager");
14923
- SessionManager = _SessionManager;
14924
- }
14925
- });
14926
-
14927
- // import("./**/*/**/*") in src/routes/index.ts
14928
- var globImport;
14929
- var init_ = __esm({
14930
- 'import("./**/*/**/*") in src/routes/index.ts'() {
14931
- globImport = __glob({
14932
- "./managers/index.ts": () => Promise.resolve().then(() => (init_managers(), managers_exports)),
14933
- "./managers/manager-recipes.ts": () => Promise.resolve().then(() => (init_manager_recipes(), manager_recipes_exports)),
14934
- "./managers/manager-users.ts": () => Promise.resolve().then(() => (init_manager_users(), manager_users_exports)),
14935
- "./managers/router-tiddlers.ts": () => Promise.resolve().then(() => (init_router_tiddlers(), router_tiddlers_exports)),
14936
- "./services/PasswordService.ts": () => Promise.resolve().then(() => (init_PasswordService(), PasswordService_exports)),
14937
- "./services/attachments.ts": () => Promise.resolve().then(() => (init_attachments(), attachments_exports)),
14938
- "./services/sessions.ts": () => Promise.resolve().then(() => (init_sessions(), sessions_exports))
14939
- });
14940
- }
14941
- });
14942
-
14943
- // src/routes/index.ts
14944
- import { Prisma } from "@prisma/client";
14945
- async function RootRoute(root, config) {
14946
- TiddlerRouter.defineRoutes(root);
14947
- ManagerRoutes(root, config);
14948
- if (typeof ENABLE_UNSAFE_PRISMA_ROUTE !== "undefined")
14949
- root.defineRoute({
14950
- method: ["POST"],
14951
- path: /^\/prisma$/,
14952
- bodyFormat: "json"
14953
- }, async (state) => {
14954
- ZodAssert.data(state, (z5) => z5.object({
14955
- table: z5.string(),
14956
- action: z5.string(),
14957
- arg: z5.any()
14958
- }));
14959
- return await state.$transaction(async (prisma) => {
14960
- const p = prisma;
14961
- const table = p[state.data.table];
14962
- if (!table) throw new Error(`No such table`);
14963
- const fn = table[state.data.action];
14964
- if (!fn) throw new Error(`No such table or action`);
14965
- console.log(state.data.arg);
14966
- return state.sendJSON(200, await fn.call(table, state.data.arg));
14967
- });
14968
- });
14969
- await importEsbuild(root);
14970
- }
14971
- async function importEsbuild(root) {
14972
- root.defineRoute({
14973
- method: ["GET"],
14974
- path: /^\/(.*)/,
14975
- pathParams: ["reqpath"],
14976
- bodyFormat: "stream"
14977
- }, async (state) => {
14978
- await state.sendDevServer();
14979
- });
14980
- }
14981
- function findValueInObject(val, predicate, keys = [], paths = []) {
14982
- if (predicate(val)) {
14983
- paths.push(keys.join("/"));
14984
- return paths;
14985
- }
14986
- if (val && typeof val === "object") {
14987
- for (const key of Object.keys(val)) {
14988
- if (!val.hasOwnProperty(key)) continue;
14989
- findValueInObject(val[key], predicate, [...keys, key], paths);
14990
- }
14991
- }
14992
- console.log(paths, keys);
14993
- return paths;
14994
- }
14995
- function capitalize(table) {
14996
- return table.slice(0, 1).toUpperCase() + table.slice(1);
14997
- }
14998
- var _error, _ProxyPromise, ProxyPromise, argproxy;
14999
- var init_routes = __esm({
15000
- "src/routes/index.ts"() {
15001
- "use strict";
15002
- init_utils2();
15003
- init_managers();
15004
- init_router_tiddlers();
15005
- init_();
15006
- __name(RootRoute, "RootRoute");
15007
- __name(importEsbuild, "importEsbuild");
15008
- _ProxyPromise = class _ProxyPromise {
15009
- constructor({ action, table, arg }) {
15010
- __privateAdd(this, _error, new Error("An error occured for this request"));
15011
- this.action = action;
15012
- this.table = table;
15013
- this.arg = arg;
15014
- Object.defineProperty(this, "toJSON", {
15015
- configurable: true,
15016
- enumerable: true,
15017
- value: /* @__PURE__ */ __name(() => ({
15018
- action: this.action,
15019
- table: this.table,
15020
- arg: this.arg,
15021
- dbnulls: this.arg.data && findValueInObject(this.arg.data, (e) => e === Prisma.DbNull),
15022
- jsnulls: this.arg.data && findValueInObject(this.arg.data, (e) => e === Prisma.JsonNull)
15023
- }), "value")
15024
- });
15025
- }
15026
- static getErrorStack(t) {
15027
- return __privateGet(t, _error).stack;
15028
- }
15029
- };
15030
- _error = new WeakMap();
15031
- __name(_ProxyPromise, "ProxyPromise");
15032
- ProxyPromise = _ProxyPromise;
15033
- __name(findValueInObject, "findValueInObject");
15034
- __name(capitalize, "capitalize");
15035
- argproxy = (() => new Proxy({}, {
15036
- get(target, table) {
15037
- return target[table] = target[table] || new Proxy({}, {
15038
- get(target2, action) {
15039
- return target2[action] = target2[action] || ((arg) => {
15040
- return new ProxyPromise({ action, table: capitalize(table), arg });
15041
- });
15042
- }
15043
- });
15044
- }
15045
- }))();
15046
- }
15047
- });
14755
+ }
14756
+ </style>
14757
+ <base href="${pathPrefix}/">
14758
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
14759
+ <link rel="stylesheet" href="${pathPrefix}/main.css" />
14760
+ </head>
15048
14761
 
15049
- // src/setupDevServer.ts
15050
- import { request } from "http";
15051
- import { resolve as resolve4 } from "path";
15052
- async function setupDevServer(enableDevServer) {
14762
+ <body class="tc-body">
14763
+ <div id="root"></div>
14764
+ <script>window.pathPrefix = ${JSON.stringify(pathPrefix)};</script>
14765
+ <script type="module" src="${pathPrefix}/main.js"></script>
14766
+ </body>
14767
+
14768
+ </html>
14769
+ `.trim(), "utf8");
14770
+ const index_hash = createHash3("sha1").update(index_file).digest().toString("base64");
14771
+ const rootdir = dist_resolve("../react-user-mgmt");
14772
+ const index_placeholder = await readFile(join(rootdir, "public/index.html"), "utf8");
15053
14773
  if (!enableDevServer) {
15054
14774
  return /* @__PURE__ */ __name(async function sendProdServer(state) {
15055
- const rootdir = dist_resolve("../react-user-mgmt/public");
14775
+ const sendIndex = /* @__PURE__ */ __name(() => state.sendBuffer(200, {
14776
+ "content-type": "text/html",
14777
+ "content-length": index_file.length,
14778
+ "etag": index_hash
14779
+ }, index_file), "sendIndex");
14780
+ if (state.url === "/") return sendIndex();
15056
14781
  return state.sendFile(200, {}, {
15057
14782
  root: rootdir,
15058
- reqpath: state.url === "/" ? "/index.html" : state.url,
15059
- on404: /* @__PURE__ */ __name(() => state.sendFile(200, {}, { reqpath: "/index.html", root: rootdir }), "on404")
14783
+ reqpath: state.url,
14784
+ on404: /* @__PURE__ */ __name(async () => sendIndex(), "on404")
15060
14785
  });
15061
14786
  }, "sendProdServer");
15062
14787
  } else {
15063
- const esbuild = await import("esbuild");
15064
- const rootdir = resolve4(enableDevServer, "react-user-mgmt");
15065
- let ctx = await esbuild.context({
15066
- entryPoints: [resolve4(rootdir, "src/main.tsx")],
15067
- bundle: true,
15068
- target: "es2020",
15069
- platform: "browser",
15070
- jsx: "automatic",
15071
- outdir: resolve4(rootdir, "public"),
15072
- minify: true,
15073
- sourcemap: true
15074
- });
15075
- const { port } = await ctx.serve({
15076
- servedir: resolve4(rootdir, "public"),
15077
- fallback: resolve4(rootdir, "public/index.html")
15078
- });
14788
+ const { ctx, port } = await esbuildStartup();
15079
14789
  return /* @__PURE__ */ __name(async function sendDevServer(state) {
14790
+ const sendIndex = /* @__PURE__ */ __name(() => state.sendBuffer(200, {
14791
+ "content-type": "text/html",
14792
+ "content-length": index_file.length,
14793
+ "etag": index_hash
14794
+ }, index_file), "sendIndex");
15080
14795
  const proxyRes = await new Promise((resolve13, reject) => {
15081
14796
  const headers2 = { ...state.headers };
15082
14797
  delete headers2[":method"];
@@ -15085,7 +14800,7 @@ async function setupDevServer(enableDevServer) {
15085
14800
  delete headers2[":scheme"];
15086
14801
  headers2.host = "localhost";
15087
14802
  const proxyReq = request({
15088
- hostname: "localhost",
14803
+ hostname: "127.0.0.20",
15089
14804
  port,
15090
14805
  path: state.url,
15091
14806
  method: state.method,
@@ -15094,20 +14809,62 @@ async function setupDevServer(enableDevServer) {
15094
14809
  state.reader.pipe(proxyReq, { end: true });
15095
14810
  });
15096
14811
  const { statusCode, headers } = proxyRes;
14812
+ if (statusCode === 200 && headers["content-type"] === "text/html; charset=utf-8" && headers["content-length"] === "61") {
14813
+ const indexCheck = await new Promise((resolve13) => {
14814
+ const chunks = [];
14815
+ proxyRes.on("data", (chunk) => {
14816
+ chunks.push(chunk);
14817
+ });
14818
+ proxyRes.on("end", () => {
14819
+ resolve13(Buffer.concat(chunks));
14820
+ });
14821
+ });
14822
+ if (indexCheck.toString() === index_placeholder) return sendIndex();
14823
+ }
15097
14824
  if (statusCode === 404 || !statusCode) {
15098
14825
  proxyRes.resume();
15099
- return state.sendEmpty(404, { "Content-Type": "text/html" });
14826
+ return state.sendBuffer(200, {
14827
+ "content-type": "text/html",
14828
+ "content-length": index_file.length,
14829
+ "etag": index_hash
14830
+ }, index_file);
15100
14831
  } else {
15101
14832
  return state.sendStream(statusCode, headers, proxyRes);
15102
14833
  }
15103
14834
  }, "sendDevServer");
15104
14835
  }
15105
14836
  }
14837
+ async function esbuildStartup() {
14838
+ const rootdir = dist_resolve("../react-user-mgmt");
14839
+ const esbuild = await import("esbuild");
14840
+ let ctx = await esbuild.context({
14841
+ entryPoints: [resolve3(rootdir, "src/main.tsx")],
14842
+ bundle: true,
14843
+ target: "es2020",
14844
+ platform: "browser",
14845
+ jsx: "automatic",
14846
+ outdir: resolve3(rootdir, "public"),
14847
+ minify: true,
14848
+ sourcemap: true,
14849
+ metafile: true,
14850
+ splitting: true,
14851
+ format: "esm"
14852
+ });
14853
+ const { port } = await ctx.serve({
14854
+ servedir: resolve3(rootdir, "public"),
14855
+ host: "127.0.0.20"
14856
+ });
14857
+ const result = await ctx.rebuild();
14858
+ writeFileSync(resolve3(rootdir, "public/stats.json"), JSON.stringify(result.metafile));
14859
+ return { ctx, port, result, rootdir };
14860
+ }
15106
14861
  var init_setupDevServer = __esm({
15107
14862
  "src/setupDevServer.ts"() {
15108
14863
  "use strict";
14864
+ init_esm_shims();
15109
14865
  init_utils2();
15110
14866
  __name(setupDevServer, "setupDevServer");
14867
+ __name(esbuildStartup, "esbuildStartup");
15111
14868
  }
15112
14869
  });
15113
14870
 
@@ -15128,6 +14885,7 @@ async function startupCache(commander) {
15128
14885
  var init_cache = __esm({
15129
14886
  "src/routes/cache.ts"() {
15130
14887
  "use strict";
14888
+ init_esm_shims();
15131
14889
  init_utils2();
15132
14890
  __name(startupCache, "startupCache");
15133
14891
  }
@@ -15165,10 +14923,11 @@ function zodManage(zodRequest, inner) {
15165
14923
  return state.$transaction(async (prisma) => await inner(state, prisma));
15166
14924
  });
15167
14925
  }
15168
- var AllowedMethods, BodyFormats, zodTransformJSON, _Router, Router3, ROOT_ROUTE, registerZodRoutes;
14926
+ var AllowedMethods, BodyFormats, zodTransformJSON, _Router, Router2, ROOT_ROUTE, registerZodRoutes;
15169
14927
  var init_router = __esm({
15170
14928
  "src/routes/router.ts"() {
15171
14929
  "use strict";
14930
+ init_esm_shims();
15172
14931
  init_streamer();
15173
14932
  init_StateObject();
15174
14933
  init_routes();
@@ -15176,6 +14935,7 @@ var init_router = __esm({
15176
14935
  init_utils2();
15177
14936
  init_setupDevServer();
15178
14937
  init_cache();
14938
+ init_server();
15179
14939
  AllowedMethods = [...["GET", "HEAD", "OPTIONS", "POST", "PUT", "DELETE"]];
15180
14940
  BodyFormats = ["stream", "string", "json", "buffer", "www-form-urlencoded", "www-form-urlencoded-urlsearchparams", "ignore"];
15181
14941
  zodTransformJSON = /* @__PURE__ */ __name((arg, ctx) => {
@@ -15206,13 +14966,12 @@ var init_router = __esm({
15206
14966
  this.enableBrowserCache = true;
15207
14967
  this.enableGzip = false;
15208
14968
  this.csrfDisable = false;
15209
- this.servername = "";
15210
- this.variables = /* @__PURE__ */ new Map();
15211
14969
  this.engine = commander.engine;
15212
14970
  this.SessionManager = commander.SessionManager;
14971
+ this.pathPrefix = commander.siteConfig.pathPrefix;
15213
14972
  }
15214
14973
  static async makeRouter(commander, enableDevServer) {
15215
- const sendDevServer = await setupDevServer(enableDevServer);
14974
+ const sendDevServer = await setupDevServer(enableDevServer, commander.siteConfig.pathPrefix);
15216
14975
  const rootRoute2 = defineRoute(ROOT_ROUTE, {
15217
14976
  method: AllowedMethods,
15218
14977
  path: /^/,
@@ -15225,15 +14984,27 @@ var init_router = __esm({
15225
14984
  const cache = await startupCache(commander);
15226
14985
  return new _Router(rootRoute2, commander, cache);
15227
14986
  }
15228
- get(name) {
15229
- return this.variables.get(name) || "";
14987
+ handleIncomingRequest(req, res) {
14988
+ const [ok8, err, streamer] = function() {
14989
+ try {
14990
+ return [true, void 0, new Streamer(req, res, this)];
14991
+ } catch (e) {
14992
+ return [false, e, void 0];
14993
+ }
14994
+ }.call(this);
14995
+ if (!ok8) {
14996
+ if (err === STREAM_ENDED) return;
14997
+ res.writeHead(500, { "x-reason": "handle incoming request" }).end();
14998
+ throw err;
14999
+ }
15000
+ this.handle(streamer).catch(streamer.catcher);
15230
15001
  }
15231
15002
  async handle(streamer) {
15232
15003
  if (!this.csrfDisable && ["POST", "PUT", "DELETE"].includes(streamer.method) && streamer.headers["x-requested-with"] !== "TiddlyWiki")
15233
15004
  throw streamer.sendString(
15234
- 403,
15005
+ 400,
15235
15006
  { "x-reason": "x-requested-with missing" },
15236
- `'X-Requested-With' header required to login to '${this.servername}'`,
15007
+ `'X-Requested-With' header required`,
15237
15008
  "utf8"
15238
15009
  );
15239
15010
  const authUser = await this.SessionManager.parseIncomingRequest(streamer, this);
@@ -15329,13 +15100,11 @@ var init_router = __esm({
15329
15100
  findRoute(streamer) {
15330
15101
  const { method, urlInfo } = streamer;
15331
15102
  let testPath = urlInfo.pathname || "/";
15332
- if (this.pathPrefix && testPath.startsWith(this.pathPrefix))
15333
- testPath = testPath.slice(this.pathPrefix.length) || "/";
15334
15103
  return this.findRouteRecursive([this.rootRoute], testPath, method);
15335
15104
  }
15336
15105
  };
15337
15106
  __name(_Router, "Router");
15338
- Router3 = _Router;
15107
+ Router2 = _Router;
15339
15108
  ROOT_ROUTE = Symbol("ROOT_ROUTE");
15340
15109
  __name(defineRoute, "defineRoute");
15341
15110
  __name(zodRoute, "zodRoute");
@@ -15392,16 +15161,7 @@ var init_router = __esm({
15392
15161
  }
15393
15162
  });
15394
15163
 
15395
- // src/server.ts
15396
- init_router();
15397
- init_StateObject();
15398
- init_streamer();
15399
- init_global();
15400
- import * as opaque2 from "@serenity-kit/opaque";
15401
- import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
15402
-
15403
15164
  // src/tiddlywiki.ts
15404
- init_utils2();
15405
15165
  import { TiddlyWiki } from "tiddlywiki";
15406
15166
  import { ok as ok5 } from "node:assert";
15407
15167
  async function bootTiddlyWiki(wikiPath) {
@@ -15458,19 +15218,341 @@ async function bootTiddlyWiki(wikiPath) {
15458
15218
  ok5(!$tw2.boot.tasks.readBrowserTiddlers);
15459
15219
  return $tw2;
15460
15220
  }
15461
- __name(bootTiddlyWiki, "bootTiddlyWiki");
15221
+ var init_tiddlywiki = __esm({
15222
+ "src/tiddlywiki.ts"() {
15223
+ "use strict";
15224
+ init_esm_shims();
15225
+ init_utils2();
15226
+ __name(bootTiddlyWiki, "bootTiddlyWiki");
15227
+ }
15228
+ });
15462
15229
 
15463
- // src/commander.ts
15464
- init_sessions();
15465
- init_attachments();
15466
- init_utils2();
15467
- import * as path4 from "node:path";
15468
- import { PrismaClient as PrismaClient2 } from "@prisma/client";
15469
- import { createClient } from "@libsql/client";
15470
- import { PrismaLibSQL } from "@prisma/adapter-libsql";
15471
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "node:fs";
15472
- import { readdir, readFile } from "node:fs/promises";
15473
- import { createHash as createHash3, randomUUID } from "node:crypto";
15230
+ // src/services/sessions.ts
15231
+ import { createHash as createHash4, randomBytes } from "node:crypto";
15232
+ function zodSession(path5, zodRequest, inner) {
15233
+ return {
15234
+ ...zodRoute(["POST"], path5, (z5) => ({}), "json", zodRequest, async (state) => {
15235
+ return state.$transaction(async (prisma) => await inner(state, prisma));
15236
+ }),
15237
+ path: path5
15238
+ };
15239
+ }
15240
+ async function createSession(prisma, user_id, session_key) {
15241
+ const session_id = randomBytes(16).toString("base64url");
15242
+ return await prisma.sessions.create({
15243
+ data: {
15244
+ user_id,
15245
+ session_key,
15246
+ session_id,
15247
+ last_accessed: /* @__PURE__ */ new Date()
15248
+ }
15249
+ }).then(({ session_id: session_id2 }) => session_id2);
15250
+ }
15251
+ function assertSignature({ session_id, signature, session_key }) {
15252
+ const hash = createHash4("sha256").update(session_key + session_id).digest("base64");
15253
+ if (hash !== signature) throw "Invalid session signature.";
15254
+ }
15255
+ var SessionKeyMap, _SessionManager, SessionManager;
15256
+ var init_sessions = __esm({
15257
+ "src/services/sessions.ts"() {
15258
+ "use strict";
15259
+ init_esm_shims();
15260
+ init_router();
15261
+ SessionKeyMap = {
15262
+ login1: true,
15263
+ login2: true,
15264
+ logout: true
15265
+ };
15266
+ __name(zodSession, "zodSession");
15267
+ _SessionManager = class _SessionManager {
15268
+ constructor() {
15269
+ this.login1 = zodSession("/login/1", (z5) => z5.object({
15270
+ username: z5.prismaField("Users", "username", "string"),
15271
+ startLoginRequest: z5.string()
15272
+ }), async (state, prisma) => {
15273
+ const { username, startLoginRequest } = state.data;
15274
+ const user = await prisma.users.findUnique({
15275
+ where: { username },
15276
+ select: { user_id: true, password: true }
15277
+ });
15278
+ if (!user) throw "User not found.";
15279
+ const { user_id, password } = user;
15280
+ const stater = state.PasswordService.LoginGenerator({
15281
+ user_id,
15282
+ startLoginRequest,
15283
+ registrationRecord: password
15284
+ });
15285
+ const loginResponse = await stater.next(0);
15286
+ if (loginResponse.done) throw "Login failed.";
15287
+ const loginSession = await state.PasswordService.startLoginSession(stater);
15288
+ return { loginResponse: loginResponse.value, loginSession };
15289
+ });
15290
+ this.login2 = zodSession("/login/2", (z5) => z5.object({
15291
+ finishLoginRequest: z5.string(),
15292
+ loginSession: z5.string(),
15293
+ skipCookie: z5.boolean().optional().default(false)
15294
+ }), async (state, prisma) => {
15295
+ const { finishLoginRequest, skipCookie, loginSession } = state.data;
15296
+ if (!loginSession) throw "Login session not found.";
15297
+ const stater = state.PasswordService.serverState.get(loginSession);
15298
+ if (!stater) throw "Login session not found.";
15299
+ const { value } = await stater.next(1, finishLoginRequest);
15300
+ if (!value?.session?.sessionKey) throw "Login failed.";
15301
+ const session_id = await createSession(prisma, value.user_id, value.session.sessionKey);
15302
+ if (!skipCookie) {
15303
+ state.setCookie("session", session_id, {
15304
+ httpOnly: true,
15305
+ path: state.config.pathPrefix + "/",
15306
+ secure: state.isSecure,
15307
+ sameSite: "Strict"
15308
+ });
15309
+ }
15310
+ return { user_id: value.user_id, session_id };
15311
+ });
15312
+ this.logout = zodSession("/logout", (z5) => z5.object({
15313
+ session_id: z5.string(),
15314
+ signature: z5.string(),
15315
+ skipCookie: z5.boolean().refine((e) => e === true)
15316
+ }).optional(), async (state, prisma) => {
15317
+ if (state.data?.skipCookie) {
15318
+ const session = await prisma.sessions.findUnique({
15319
+ where: { session_id: state.data.session_id },
15320
+ select: { user_id: true, session_key: true }
15321
+ });
15322
+ if (!session?.session_key) throw "Session not found.";
15323
+ const { session_key } = session;
15324
+ const { session_id, signature } = state.data;
15325
+ assertSignature({ session_id, signature, session_key });
15326
+ await prisma.sessions.delete({ where: { session_id: state.data.session_id } });
15327
+ return null;
15328
+ }
15329
+ if (state.user.isLoggedIn) {
15330
+ await prisma.sessions.delete({ where: { session_id: state.user.sessionId } });
15331
+ }
15332
+ var cookies = state.headers.cookie ? state.headers.cookie.split(";") : [];
15333
+ for (var i = 0; i < cookies.length; i++) {
15334
+ var cookie = cookies[i]?.trim().split("=")[0];
15335
+ if (!cookie) continue;
15336
+ state.setCookie(cookie, "", { httpOnly: true, path: state.config.pathPrefix + "/", expires: /* @__PURE__ */ new Date(0), secure: state.isSecure, sameSite: "Strict" });
15337
+ }
15338
+ return null;
15339
+ });
15340
+ }
15341
+ static async defineRoutes(root) {
15342
+ registerZodRoutes(root, new _SessionManager(), Object.keys(SessionKeyMap));
15343
+ }
15344
+ static async parseIncomingRequest(streamer, router) {
15345
+ const sessionId = streamer.cookies.get("session");
15346
+ const session = sessionId && await router.engine.sessions.findUnique({
15347
+ where: { session_id: sessionId },
15348
+ select: { user: { select: { user_id: true, username: true, roles: { select: { role_id: true } } } } }
15349
+ });
15350
+ if (sessionId && session) return {
15351
+ user_id: session.user.user_id,
15352
+ username: session.user.username,
15353
+ isAdmin: session.user.roles.some((e) => e.role_id === 1),
15354
+ role_ids: session.user.roles.map((e) => e.role_id),
15355
+ sessionId,
15356
+ isLoggedIn: true
15357
+ };
15358
+ else return {
15359
+ user_id: 0,
15360
+ username: "(anon)",
15361
+ isAdmin: false,
15362
+ role_ids: [],
15363
+ sessionId: void 0,
15364
+ isLoggedIn: false
15365
+ };
15366
+ }
15367
+ };
15368
+ __name(_SessionManager, "SessionManager");
15369
+ SessionManager = _SessionManager;
15370
+ __name(createSession, "createSession");
15371
+ __name(assertSignature, "assertSignature");
15372
+ }
15373
+ });
15374
+
15375
+ // src/services/attachments.ts
15376
+ import * as path3 from "path";
15377
+ import * as fs2 from "fs";
15378
+ var import_sjcl2, $tw, _AttachmentService, AttachmentService;
15379
+ var init_attachments = __esm({
15380
+ "src/services/attachments.ts"() {
15381
+ "use strict";
15382
+ init_esm_shims();
15383
+ init_utils2();
15384
+ import_sjcl2 = __toESM(require_sjcl(), 1);
15385
+ $tw = {};
15386
+ _AttachmentService = class _AttachmentService {
15387
+ constructor(config, prisma) {
15388
+ this.config = config;
15389
+ this.prisma = prisma;
15390
+ }
15391
+ makeCanonicalUri(bag_name, title) {
15392
+ return `/bags/${encodeURIComponentExtended(bag_name)}/tiddlers/${encodeURIComponentExtended(title)}/blob`;
15393
+ }
15394
+ /*
15395
+ Given tiddler fields, tiddler_id and a bag_name, return the tiddler fields after the following process:
15396
+ - Apply the tiddler_id as the revision field
15397
+ - Apply the bag_name as the bag field
15398
+ */
15399
+ processOutgoingTiddler({ tiddler, tiddler_id, bag_name, attachment_hash }) {
15400
+ if (attachment_hash !== null) {
15401
+ return Object.assign(
15402
+ {},
15403
+ tiddler,
15404
+ {
15405
+ text: void 0,
15406
+ _canonical_uri: this.makeCanonicalUri(bag_name, tiddler.title),
15407
+ revision: tiddler_id,
15408
+ bag: bag_name
15409
+ }
15410
+ );
15411
+ } else {
15412
+ return tiddler;
15413
+ }
15414
+ }
15415
+ /*
15416
+ */
15417
+ async processIncomingTiddler({
15418
+ tiddlerFields,
15419
+ existing_attachment_hash,
15420
+ existing_canonical_uri
15421
+ }) {
15422
+ const { attachmentSizeLimit, attachmentsEnabled } = this.config;
15423
+ const contentTypeInfo = this.config.contentTypeInfo[tiddlerFields.type || "text/vnd.tiddlywiki"];
15424
+ const isBinary = !!contentTypeInfo && contentTypeInfo.encoding === "base64";
15425
+ let shouldProcessAttachment = tiddlerFields.text && tiddlerFields.text.length > attachmentSizeLimit;
15426
+ if (existing_attachment_hash) {
15427
+ const fileSize = await this.getAttachmentFileSize(existing_attachment_hash);
15428
+ if (fileSize && fileSize <= attachmentSizeLimit) {
15429
+ const existingAttachmentMeta = await this.getAttachmentMetadata(existing_attachment_hash);
15430
+ const hasCanonicalField = !!tiddlerFields._canonical_uri;
15431
+ const skipAttachment = hasCanonicalField && tiddlerFields._canonical_uri === (existingAttachmentMeta ? existingAttachmentMeta._canonical_uri : existing_canonical_uri);
15432
+ shouldProcessAttachment = !skipAttachment;
15433
+ } else {
15434
+ shouldProcessAttachment = false;
15435
+ }
15436
+ }
15437
+ if (attachmentsEnabled && isBinary && shouldProcessAttachment) {
15438
+ const attachment_hash = existing_attachment_hash || await this.saveAttachment({
15439
+ text: tiddlerFields.text,
15440
+ type: tiddlerFields.type,
15441
+ reference: tiddlerFields.title,
15442
+ _canonical_uri: tiddlerFields._canonical_uri
15443
+ });
15444
+ if (tiddlerFields && tiddlerFields._canonical_uri) {
15445
+ delete tiddlerFields._canonical_uri;
15446
+ }
15447
+ return {
15448
+ tiddlerFields: Object.assign({}, tiddlerFields, { text: void 0 }),
15449
+ attachment_hash
15450
+ };
15451
+ } else {
15452
+ return {
15453
+ tiddlerFields,
15454
+ attachment_hash: existing_attachment_hash
15455
+ };
15456
+ }
15457
+ }
15458
+ /*
15459
+ Check if an attachment name is valid (is a 64 character hex string)
15460
+ */
15461
+ isValidAttachmentName(content_hash) {
15462
+ const re = new RegExp("^[a-f0-9]{64}$");
15463
+ return re.test(content_hash);
15464
+ }
15465
+ /*
15466
+ Saves an attachment to a file. Options include:
15467
+
15468
+ text: text content (may be binary)
15469
+ type: MIME type of content
15470
+ reference: reference to use for debugging
15471
+ _canonical_uri: canonical uri of the content
15472
+ */
15473
+ async saveAttachment(options) {
15474
+ const contentHash = import_sjcl2.default.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(options.text)).slice(0, 64).toString();
15475
+ const contentTypeInfo = this.config.contentTypeInfo[options.type] || this.config.contentTypeInfo["application/octet-stream"];
15476
+ const attachmentPath = path3.resolve(this.config.storePath, "files", contentHash);
15477
+ createDirectory(attachmentPath);
15478
+ const dataFilename = "data" + contentTypeInfo.extension;
15479
+ fs2.writeFileSync(path3.resolve(attachmentPath, dataFilename), options.text, contentTypeInfo.encoding);
15480
+ this.writeMetaFile(fs2, path3, attachmentPath, options, contentHash, dataFilename);
15481
+ return contentHash;
15482
+ }
15483
+ writeMetaFile(fs3, path5, attachmentPath, options, contentHash, dataFilename) {
15484
+ fs3.writeFileSync(path5.resolve(attachmentPath, "meta.json"), JSON.stringify({
15485
+ _canonical_uri: options._canonical_uri,
15486
+ created: (/* @__PURE__ */ new Date()).toISOString(),
15487
+ modified: (/* @__PURE__ */ new Date()).toISOString(),
15488
+ contentHash,
15489
+ filename: dataFilename,
15490
+ type: options.type
15491
+ }, null, 4));
15492
+ }
15493
+ /*
15494
+ Adopts an attachment file into the store (e.g. move from a temp upload directory)
15495
+ */
15496
+ async adoptAttachment({ incomingFilepath, type, hash, _canonical_uri }) {
15497
+ const contentTypeInfo = this.config.contentTypeInfo[type] || this.config.contentTypeInfo["application/octet-stream"];
15498
+ const attachmentPath = path3.resolve(this.config.storePath, "files", hash);
15499
+ createDirectory(attachmentPath);
15500
+ const dataFilename = "data" + contentTypeInfo.extension, dataFilepath = path3.resolve(attachmentPath, dataFilename);
15501
+ fs2.renameSync(incomingFilepath, dataFilepath);
15502
+ fs2.writeFileSync(path3.resolve(attachmentPath, "meta.json"), JSON.stringify({
15503
+ _canonical_uri,
15504
+ created: (/* @__PURE__ */ new Date()).toISOString(),
15505
+ modified: (/* @__PURE__ */ new Date()).toISOString(),
15506
+ contentHash: hash,
15507
+ filename: dataFilename,
15508
+ type
15509
+ }, null, 4));
15510
+ return hash;
15511
+ }
15512
+ /*
15513
+ Get an attachment ready to stream. Returns null if there is an error or:
15514
+ stream: filestream of file
15515
+ type: type of file
15516
+ */
15517
+ async getAttachmentStream(content_hash) {
15518
+ if (!this.isValidAttachmentName(content_hash)) return null;
15519
+ const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15520
+ const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15521
+ if (!fs2.existsSync(metaJsonPath) || !fs2.statSync(metaJsonPath).isFile()) return null;
15522
+ const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
15523
+ if (!meta) return null;
15524
+ const dataFilepath = path3.resolve(attachmentPath, meta.filename);
15525
+ if (!fs2.existsSync(dataFilepath) || !fs2.statSync(dataFilepath).isFile()) return null;
15526
+ return {
15527
+ stream: fs2.createReadStream(dataFilepath),
15528
+ type: meta.type
15529
+ };
15530
+ }
15531
+ /*
15532
+ Get the size of an attachment file given the contentHash.
15533
+ Returns the size in bytes, or null if the file doesn't exist.
15534
+ */
15535
+ async getAttachmentFileSize(content_hash) {
15536
+ const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15537
+ const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15538
+ if (!(fs2.existsSync(metaJsonPath) && fs2.statSync(metaJsonPath).isFile())) return null;
15539
+ const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
15540
+ if (!meta) return null;
15541
+ const dataFilepath = path3.resolve(attachmentPath, meta.filename);
15542
+ if (!(fs2.existsSync(dataFilepath) && fs2.statSync(dataFilepath).isFile())) return null;
15543
+ return fs2.statSync(dataFilepath).size;
15544
+ }
15545
+ async getAttachmentMetadata(content_hash) {
15546
+ const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15547
+ const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15548
+ if (!fs2.existsSync(metaJsonPath)) return null;
15549
+ return JSON.parse(fs2.readFileSync(metaJsonPath, "utf8"));
15550
+ }
15551
+ };
15552
+ __name(_AttachmentService, "AttachmentService");
15553
+ AttachmentService = _AttachmentService;
15554
+ }
15555
+ });
15474
15556
 
15475
15557
  // src/commands/mws-load-plugin-bags.ts
15476
15558
  var mws_load_plugin_bags_exports = {};
@@ -15478,34 +15560,7 @@ __export(mws_load_plugin_bags_exports, {
15478
15560
  Command: () => Command,
15479
15561
  info: () => info
15480
15562
  });
15481
- init_TiddlerStore();
15482
- init_utils2();
15483
15563
  import { resolve as resolve5 } from "node:path";
15484
- var info = {
15485
- name: "mws-load-plugin-bags",
15486
- synchronous: true
15487
- };
15488
- var _Command = class _Command {
15489
- constructor(params, commander, callback) {
15490
- this.params = params;
15491
- this.commander = commander;
15492
- this.callback = callback;
15493
- }
15494
- get $tw() {
15495
- return this.commander.$tw;
15496
- }
15497
- async execute() {
15498
- console.time(`${info.name} complete`);
15499
- await loadPluginBags(
15500
- this.$tw,
15501
- new TiddlerStore(this.commander, this.commander.engine),
15502
- this.commander.engine
15503
- );
15504
- console.timeEnd(`${info.name} complete`);
15505
- }
15506
- };
15507
- __name(_Command, "Command");
15508
- var Command = _Command;
15509
15564
  async function loadPluginBags($tw2, store, engine) {
15510
15565
  function makePluginBagName2(type, publisher, name) {
15511
15566
  return "$:/" + type + "/" + (publisher ? publisher + "/" : "") + name;
@@ -15563,7 +15618,41 @@ async function loadPluginBags($tw2, store, engine) {
15563
15618
  });
15564
15619
  await engine.$transaction(prismaPromiseArray);
15565
15620
  }
15566
- __name(loadPluginBags, "loadPluginBags");
15621
+ var info, _Command, Command;
15622
+ var init_mws_load_plugin_bags = __esm({
15623
+ "src/commands/mws-load-plugin-bags.ts"() {
15624
+ "use strict";
15625
+ init_esm_shims();
15626
+ init_TiddlerStore();
15627
+ init_utils2();
15628
+ info = {
15629
+ name: "mws-load-plugin-bags",
15630
+ synchronous: true
15631
+ };
15632
+ _Command = class _Command {
15633
+ constructor(params, commander, callback) {
15634
+ this.params = params;
15635
+ this.commander = commander;
15636
+ this.callback = callback;
15637
+ }
15638
+ get $tw() {
15639
+ return this.commander.$tw;
15640
+ }
15641
+ async execute() {
15642
+ console.time(`${info.name} complete`);
15643
+ await loadPluginBags(
15644
+ this.$tw,
15645
+ new TiddlerStore(this.commander, this.commander.engine),
15646
+ this.commander.engine
15647
+ );
15648
+ console.timeEnd(`${info.name} complete`);
15649
+ }
15650
+ };
15651
+ __name(_Command, "Command");
15652
+ Command = _Command;
15653
+ __name(loadPluginBags, "loadPluginBags");
15654
+ }
15655
+ });
15567
15656
 
15568
15657
  // src/commands/mws-render-tiddlywiki5.ts
15569
15658
  var mws_render_tiddlywiki5_exports = {};
@@ -15572,21 +15661,26 @@ __export(mws_render_tiddlywiki5_exports, {
15572
15661
  info: () => info2
15573
15662
  });
15574
15663
  import { resolve as resolve6 } from "node:path";
15575
- var { writeFileSync: writeFileSync2 } = __require("fs");
15576
- var info2 = {
15577
- name: "mws-render-tiddlywiki5",
15578
- synchronous: true
15579
- };
15580
- var _Command2 = class _Command2 {
15581
- constructor(params, commander, callback) {
15582
- this.params = params;
15583
- this.commander = commander;
15584
- this.callback = callback;
15585
- }
15586
- async execute() {
15587
- const result = this.commander.$tw.wiki.renderTiddler("text/plain", "$:/core/templates/tiddlywiki5.html", {
15588
- variables: {
15589
- saveTiddlerFilter: `
15664
+ var writeFileSync3, info2, _Command2, Command2;
15665
+ var init_mws_render_tiddlywiki5 = __esm({
15666
+ "src/commands/mws-render-tiddlywiki5.ts"() {
15667
+ "use strict";
15668
+ init_esm_shims();
15669
+ ({ writeFileSync: writeFileSync3 } = __require("fs"));
15670
+ info2 = {
15671
+ name: "mws-render-tiddlywiki5",
15672
+ synchronous: true
15673
+ };
15674
+ _Command2 = class _Command2 {
15675
+ constructor(params, commander, callback) {
15676
+ this.params = params;
15677
+ this.commander = commander;
15678
+ this.callback = callback;
15679
+ }
15680
+ async execute() {
15681
+ const result = this.commander.$tw.wiki.renderTiddler("text/plain", "$:/core/templates/tiddlywiki5.html", {
15682
+ variables: {
15683
+ saveTiddlerFilter: `
15590
15684
  $:/boot/boot.css
15591
15685
  $:/boot/boot.js
15592
15686
  $:/boot/bootprefix.js
@@ -15597,14 +15691,16 @@ var _Command2 = class _Command2 {
15597
15691
  $:/themes/tiddlywiki/snowwhite
15598
15692
  $:/themes/tiddlywiki/vanilla
15599
15693
  `
15694
+ }
15695
+ });
15696
+ const filepath = resolve6(this.commander.wikiPath, "tiddlywiki5.html");
15697
+ writeFileSync3(filepath, result);
15600
15698
  }
15601
- });
15602
- const filepath = resolve6(this.commander.wikiPath, "tiddlywiki5.html");
15603
- writeFileSync2(filepath, result);
15699
+ };
15700
+ __name(_Command2, "Command");
15701
+ Command2 = _Command2;
15604
15702
  }
15605
- };
15606
- __name(_Command2, "Command");
15607
- var Command2 = _Command2;
15703
+ });
15608
15704
 
15609
15705
  // src/commands/mws-load-wiki-folder.ts
15610
15706
  var mws_load_wiki_folder_exports = {};
@@ -15612,41 +15708,10 @@ __export(mws_load_wiki_folder_exports, {
15612
15708
  Command: () => Command3,
15613
15709
  info: () => info3
15614
15710
  });
15615
- init_TiddlerStore();
15616
15711
  import { resolve as resolve7 } from "path";
15617
- var info3 = {
15618
- name: "mws-load-wiki-folder",
15619
- synchronous: true
15620
- };
15621
- var _Command3 = class _Command3 {
15622
- constructor(params, commander, callback) {
15623
- this.params = params;
15624
- this.commander = commander;
15625
- this.callback = callback;
15626
- }
15627
- async execute() {
15628
- if (this.params.length < 5) {
15629
- return "Missing parameters for --mws-load-wiki-folder command";
15630
- }
15631
- await this.commander.engine.$transaction(loadWikiFolder({
15632
- wikiPath: this.params[0],
15633
- bagName: this.params[1],
15634
- bagDescription: this.params[2],
15635
- recipeName: this.params[3],
15636
- recipeDescription: this.params[4],
15637
- store: new TiddlerStore(this.commander, this.commander.engine),
15638
- $tw: this.commander.$tw
15639
- }));
15640
- console.log(info3.name, "complete:", this.params[0]);
15641
- return null;
15642
- }
15643
- };
15644
- __name(_Command3, "Command");
15645
- var Command3 = _Command3;
15646
15712
  function makePluginBagName(type, publisher, name) {
15647
15713
  return "$:/" + type + "/" + (publisher ? publisher + "/" : "") + name;
15648
15714
  }
15649
- __name(makePluginBagName, "makePluginBagName");
15650
15715
  function loadWikiFolder({ $tw: $tw2, store, ...options }) {
15651
15716
  const path5 = __require("path"), fs3 = __require("fs");
15652
15717
  const wikiInfoPath = path5.resolve(options.wikiPath, $tw2.config.wikiInfo);
@@ -15697,7 +15762,45 @@ function loadWikiFolder({ $tw: $tw2, store, ...options }) {
15697
15762
  ...store.saveTiddlersFromPath_PrismaArray(tiddlersFromPath, options.bagName)
15698
15763
  ];
15699
15764
  }
15700
- __name(loadWikiFolder, "loadWikiFolder");
15765
+ var info3, _Command3, Command3;
15766
+ var init_mws_load_wiki_folder = __esm({
15767
+ "src/commands/mws-load-wiki-folder.ts"() {
15768
+ "use strict";
15769
+ init_esm_shims();
15770
+ init_TiddlerStore();
15771
+ info3 = {
15772
+ name: "mws-load-wiki-folder",
15773
+ synchronous: true
15774
+ };
15775
+ _Command3 = class _Command3 {
15776
+ constructor(params, commander, callback) {
15777
+ this.params = params;
15778
+ this.commander = commander;
15779
+ this.callback = callback;
15780
+ }
15781
+ async execute() {
15782
+ if (this.params.length < 5) {
15783
+ return "Missing parameters for --mws-load-wiki-folder command";
15784
+ }
15785
+ await this.commander.engine.$transaction(loadWikiFolder({
15786
+ wikiPath: this.params[0],
15787
+ bagName: this.params[1],
15788
+ bagDescription: this.params[2],
15789
+ recipeName: this.params[3],
15790
+ recipeDescription: this.params[4],
15791
+ store: new TiddlerStore(this.commander, this.commander.engine),
15792
+ $tw: this.commander.$tw
15793
+ }));
15794
+ console.log(info3.name, "complete:", this.params[0]);
15795
+ return null;
15796
+ }
15797
+ };
15798
+ __name(_Command3, "Command");
15799
+ Command3 = _Command3;
15800
+ __name(makePluginBagName, "makePluginBagName");
15801
+ __name(loadWikiFolder, "loadWikiFolder");
15802
+ }
15803
+ });
15701
15804
 
15702
15805
  // src/commands/mws-save-archive.ts
15703
15806
  var mws_save_archive_exports = {};
@@ -15705,98 +15808,105 @@ __export(mws_save_archive_exports, {
15705
15808
  Command: () => Command4,
15706
15809
  info: () => info4
15707
15810
  });
15708
- init_TiddlerStore();
15709
- init_utils2();
15710
15811
  import { resolve as resolve8 } from "path";
15711
15812
  import * as _fsp from "fs/promises";
15712
- var fsp = createStrictAwaitProxy(_fsp);
15713
- var info4 = {
15714
- name: "mws-save-archive",
15715
- synchronous: true
15716
- };
15717
- var _Command4 = class _Command4 {
15718
- constructor(params, commander, callback) {
15719
- this.params = params;
15720
- this.commander = commander;
15721
- this.callback = callback;
15722
- }
15723
- get $tw() {
15724
- return this.commander.$tw;
15725
- }
15726
- get archivePath() {
15727
- return this.params[0];
15728
- }
15729
- async execute() {
15730
- if (this.params.length < 1) throw "Missing pathname";
15731
- await this.commander.$transaction(async (prisma) => {
15732
- this.store = new TiddlerStore(this.commander, prisma);
15733
- await this.saveArchive();
15734
- this.store = void 0;
15735
- });
15736
- console.log(info4.name, "complete:", this.params[0]);
15737
- return null;
15738
- }
15739
- async getRecipes() {
15740
- return await this.store.prisma.recipes.findMany({
15741
- include: { recipe_bags: true, acl: true }
15742
- });
15743
- }
15744
- async getBags() {
15745
- const bags = await this.store.prisma.bags.findMany({
15746
- include: { tiddlers: { include: { fields: true } }, acl: true }
15747
- });
15748
- return bags.map((e) => ({
15749
- ...e,
15750
- tiddlers: e.tiddlers.map((t) => ({
15751
- ...t,
15752
- fields: Object.fromEntries(t.fields.map((f) => [f.field_name, f.field_value]))
15753
- }))
15754
- }));
15755
- }
15756
- async getUsers() {
15757
- return await this.store.prisma.users.findMany({ include: { roles: true, sessions: true, groups: true } });
15758
- }
15759
- async getGroups() {
15760
- return await this.store.prisma.groups.findMany({ include: { roles: true } });
15761
- }
15762
- async getRoles() {
15763
- return await this.store.prisma.roles.findMany({});
15764
- }
15765
- async saveArchive() {
15766
- if (!this.store) throw new Error("Store not initialized");
15767
- const uriC = encodeURIComponent;
15768
- await fsp.mkdir(resolve8(this.archivePath, "recipes"), { recursive: true });
15769
- const recipes = await this.getRecipes();
15770
- for (const recipeInfo of recipes) {
15771
- const recipeFile = `recipes/${uriC(recipeInfo.recipe_name)}.json`;
15772
- await fsp.writeFile(resolve8(this.archivePath, recipeFile), JSON.stringify(recipeInfo, null, " "));
15773
- }
15774
- await fsp.mkdir(resolve8(this.archivePath, "bags"), { recursive: true });
15775
- const bags = await this.getBags();
15776
- await Promise.all(bags.map(async (bagInfo) => {
15777
- const tiddlersFolder = `bags/${uriC(bagInfo.bag_name)}/tiddlers`;
15778
- await fsp.mkdir(resolve8(this.archivePath, tiddlersFolder), { recursive: true });
15779
- const bagFile = `bags/${uriC(bagInfo.bag_name)}/meta.json`;
15780
- await fsp.writeFile(resolve8(this.archivePath, bagFile), JSON.stringify({ ...bagInfo, tiddlers: void 0 }, null, " "));
15781
- for (const tiddler of bagInfo.tiddlers) {
15782
- const tiddlerFile = `bags/${uriC(bagInfo.bag_name)}/tiddlers/${tiddler.tiddler_id}.json`;
15783
- await fsp.writeFile(resolve8(this.archivePath, tiddlerFile), JSON.stringify(tiddler, null, " "));
15784
- }
15785
- }));
15786
- const users = await this.getUsers();
15787
- await fsp.writeFile(resolve8(this.archivePath, "users.json"), JSON.stringify(users, null, " "));
15788
- const groups = await this.getGroups();
15789
- await fsp.writeFile(resolve8(this.archivePath, "groups.json"), JSON.stringify(groups, null, " "));
15790
- const roles = await this.getRoles();
15791
- await fsp.writeFile(resolve8(this.archivePath, "roles.json"), JSON.stringify(roles, null, " "));
15792
- await fsp.writeFile(resolve8(this.archivePath, "index.json"), JSON.stringify({
15793
- version: 2,
15794
- comment: "The version is an internal identifier for the archive format. It is not the same as the version of TiddlyWiki or MWS."
15795
- }, null, " "));
15813
+ var fsp, info4, _Command4, Command4;
15814
+ var init_mws_save_archive = __esm({
15815
+ "src/commands/mws-save-archive.ts"() {
15816
+ "use strict";
15817
+ init_esm_shims();
15818
+ init_TiddlerStore();
15819
+ init_utils2();
15820
+ fsp = createStrictAwaitProxy(_fsp);
15821
+ info4 = {
15822
+ name: "mws-save-archive",
15823
+ synchronous: true
15824
+ };
15825
+ _Command4 = class _Command4 {
15826
+ constructor(params, commander, callback) {
15827
+ this.params = params;
15828
+ this.commander = commander;
15829
+ this.callback = callback;
15830
+ }
15831
+ get $tw() {
15832
+ return this.commander.$tw;
15833
+ }
15834
+ get archivePath() {
15835
+ return this.params[0];
15836
+ }
15837
+ async execute() {
15838
+ if (this.params.length < 1) throw "Missing pathname";
15839
+ await this.commander.$transaction(async (prisma) => {
15840
+ this.store = new TiddlerStore(this.commander, prisma);
15841
+ await this.saveArchive();
15842
+ this.store = void 0;
15843
+ });
15844
+ console.log(info4.name, "complete:", this.params[0]);
15845
+ return null;
15846
+ }
15847
+ async getRecipes() {
15848
+ return await this.store.prisma.recipes.findMany({
15849
+ include: { recipe_bags: true, acl: true }
15850
+ });
15851
+ }
15852
+ async getBags() {
15853
+ const bags = await this.store.prisma.bags.findMany({
15854
+ include: { tiddlers: { include: { fields: true } }, acl: true }
15855
+ });
15856
+ return bags.map((e) => ({
15857
+ ...e,
15858
+ tiddlers: e.tiddlers.map((t) => ({
15859
+ ...t,
15860
+ fields: Object.fromEntries(t.fields.map((f) => [f.field_name, f.field_value]))
15861
+ }))
15862
+ }));
15863
+ }
15864
+ async getUsers() {
15865
+ return await this.store.prisma.users.findMany({ include: { roles: true, sessions: true, groups: true } });
15866
+ }
15867
+ async getGroups() {
15868
+ return await this.store.prisma.groups.findMany({ include: { roles: true } });
15869
+ }
15870
+ async getRoles() {
15871
+ return await this.store.prisma.roles.findMany({});
15872
+ }
15873
+ async saveArchive() {
15874
+ if (!this.store) throw new Error("Store not initialized");
15875
+ const uriC = encodeURIComponent;
15876
+ await fsp.mkdir(resolve8(this.archivePath, "recipes"), { recursive: true });
15877
+ const recipes = await this.getRecipes();
15878
+ for (const recipeInfo of recipes) {
15879
+ const recipeFile = `recipes/${uriC(recipeInfo.recipe_name)}.json`;
15880
+ await fsp.writeFile(resolve8(this.archivePath, recipeFile), JSON.stringify(recipeInfo, null, " "));
15881
+ }
15882
+ await fsp.mkdir(resolve8(this.archivePath, "bags"), { recursive: true });
15883
+ const bags = await this.getBags();
15884
+ await Promise.all(bags.map(async (bagInfo) => {
15885
+ const tiddlersFolder = `bags/${uriC(bagInfo.bag_name)}/tiddlers`;
15886
+ await fsp.mkdir(resolve8(this.archivePath, tiddlersFolder), { recursive: true });
15887
+ const bagFile = `bags/${uriC(bagInfo.bag_name)}/meta.json`;
15888
+ await fsp.writeFile(resolve8(this.archivePath, bagFile), JSON.stringify({ ...bagInfo, tiddlers: void 0 }, null, " "));
15889
+ for (const tiddler of bagInfo.tiddlers) {
15890
+ const tiddlerFile = `bags/${uriC(bagInfo.bag_name)}/tiddlers/${tiddler.tiddler_id}.json`;
15891
+ await fsp.writeFile(resolve8(this.archivePath, tiddlerFile), JSON.stringify(tiddler, null, " "));
15892
+ }
15893
+ }));
15894
+ const users = await this.getUsers();
15895
+ await fsp.writeFile(resolve8(this.archivePath, "users.json"), JSON.stringify(users, null, " "));
15896
+ const groups = await this.getGroups();
15897
+ await fsp.writeFile(resolve8(this.archivePath, "groups.json"), JSON.stringify(groups, null, " "));
15898
+ const roles = await this.getRoles();
15899
+ await fsp.writeFile(resolve8(this.archivePath, "roles.json"), JSON.stringify(roles, null, " "));
15900
+ await fsp.writeFile(resolve8(this.archivePath, "index.json"), JSON.stringify({
15901
+ version: 2,
15902
+ comment: "The version is an internal identifier for the archive format. It is not the same as the version of TiddlyWiki or MWS."
15903
+ }, null, " "));
15904
+ }
15905
+ };
15906
+ __name(_Command4, "Command");
15907
+ Command4 = _Command4;
15796
15908
  }
15797
- };
15798
- __name(_Command4, "Command");
15799
- var Command4 = _Command4;
15909
+ });
15800
15910
 
15801
15911
  // src/commands/mws-load-archive.ts
15802
15912
  var mws_load_archive_exports = {};
@@ -15804,237 +15914,244 @@ __export(mws_load_archive_exports, {
15804
15914
  Command: () => Command5,
15805
15915
  info: () => info5
15806
15916
  });
15807
- init_utils2();
15808
- import { join, resolve as resolve9 } from "path";
15917
+ import { join as join2, resolve as resolve9 } from "path";
15809
15918
  import * as _fsp2 from "fs/promises";
15810
15919
  import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
15811
15920
  import { existsSync as existsSync3 } from "fs";
15812
- var fsp2 = createStrictAwaitProxy(_fsp2);
15813
- var info5 = {
15814
- name: "mws-load-archive",
15815
- synchronous: true
15816
- };
15817
- var _Command5 = class _Command5 {
15818
- constructor(params, commander, callback) {
15819
- this.params = params;
15820
- this.commander = commander;
15821
- this.callback = callback;
15822
- }
15823
- async execute() {
15824
- if (this.params.length < 1) throw "Missing pathname";
15825
- const archivePath = this.params[0];
15826
- const index = existsSync3(resolve9(archivePath, "index.json")) ? JSON.parse(await fsp2.readFile(resolve9(archivePath, "index.json"), "utf8")) : { version: 1 };
15827
- switch (index.version) {
15828
- case 1:
15829
- await new Archiver1(this.commander).loadArchive(archivePath);
15830
- break;
15831
- case 2:
15832
- await new Archiver2(this.commander).loadArchive(archivePath);
15833
- break;
15834
- default:
15835
- throw new Error(`Unsupported archive version ${index.version}`);
15836
- }
15837
- this.commander.setupRequired = false;
15838
- }
15839
- };
15840
- __name(_Command5, "Command");
15841
- var Command5 = _Command5;
15842
- var _Archiver = class _Archiver {
15843
- constructor(commander) {
15844
- this.commander = commander;
15845
- }
15846
- };
15847
- __name(_Archiver, "Archiver");
15848
- var Archiver = _Archiver;
15849
- var _Archiver1 = class _Archiver1 extends Archiver {
15850
- async loadArchive(archivePath) {
15851
- await this.commander.$transaction(async (prisma) => {
15852
- const roles = JSON.parse(await fsp2.readFile(resolve9(archivePath, "roles", "roles.json"), "utf8"));
15853
- await prisma.roles.createMany({ data: roles });
15854
- const userFiles = await fsp2.readdir(resolve9(archivePath, "users"));
15855
- const users = await Promise.all(userFiles.map(async (userFile) => {
15856
- return JSON.parse(await fsp2.readFile(resolve9(archivePath, "users", userFile), "utf8"));
15857
- }));
15858
- await prisma.users.createMany({ data: users });
15859
- const bagNames = await fsp2.readdir(resolve9(archivePath, "bags"));
15860
- for (const bagFilename of bagNames) {
15861
- const stat = await fsp2.stat(resolve9(archivePath, "bags", bagFilename));
15862
- if (!stat.isDirectory()) continue;
15863
- console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
15864
- await this.restoreBag(resolve9(archivePath, "bags", bagFilename), prisma);
15865
- }
15866
- const recipeNames = await fsp2.readdir(resolve9(archivePath, "recipes"));
15867
- for (const recipeFilename of recipeNames) {
15868
- if (!recipeFilename.endsWith(".json")) continue;
15869
- console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
15870
- await this.restoreRecipe(resolve9(archivePath, "recipes", recipeFilename), prisma);
15871
- }
15872
- }).catch((e) => {
15873
- if (e instanceof PrismaClientKnownRequestError) {
15874
- console.log(e.code, e.meta, e.message);
15875
- throw e.message;
15876
- } else {
15877
- throw e;
15921
+ var fsp2, info5, _Command5, Command5, _Archiver, Archiver, _Archiver1, Archiver1, _Archiver2, Archiver2;
15922
+ var init_mws_load_archive = __esm({
15923
+ "src/commands/mws-load-archive.ts"() {
15924
+ "use strict";
15925
+ init_esm_shims();
15926
+ init_utils2();
15927
+ fsp2 = createStrictAwaitProxy(_fsp2);
15928
+ info5 = {
15929
+ name: "mws-load-archive",
15930
+ synchronous: true
15931
+ };
15932
+ _Command5 = class _Command5 {
15933
+ constructor(params, commander, callback) {
15934
+ this.params = params;
15935
+ this.commander = commander;
15936
+ this.callback = callback;
15937
+ }
15938
+ async execute() {
15939
+ if (this.params.length < 1) throw "Missing pathname";
15940
+ const archivePath = this.params[0];
15941
+ const index = existsSync3(resolve9(archivePath, "index.json")) ? JSON.parse(await fsp2.readFile(resolve9(archivePath, "index.json"), "utf8")) : { version: 1 };
15942
+ switch (index.version) {
15943
+ case 1:
15944
+ await new Archiver1(this.commander).loadArchive(archivePath);
15945
+ break;
15946
+ case 2:
15947
+ await new Archiver2(this.commander).loadArchive(archivePath);
15948
+ break;
15949
+ default:
15950
+ throw new Error(`Unsupported archive version ${index.version}`);
15951
+ }
15952
+ this.commander.setupRequired = false;
15878
15953
  }
15879
- });
15880
- }
15881
- async restoreRecipe(file, prisma) {
15882
- const recipeInfo = JSON.parse(await fsp2.readFile(file, "utf8"));
15883
- await prisma.recipes.create({
15884
- data: {
15885
- recipe_id: recipeInfo.recipe_id,
15886
- recipe_name: recipeInfo.recipe_name,
15887
- description: recipeInfo.description,
15888
- owner_id: recipeInfo.owner_id,
15889
- acl: { createMany: { data: recipeInfo.acl } },
15890
- recipe_bags: {
15891
- createMany: {
15892
- data: recipeInfo.recipe_bags.map((e) => ({
15893
- bag_id: e.bag_id,
15894
- position: e.position,
15895
- with_acl: e.with_acl
15896
- }))
15954
+ };
15955
+ __name(_Command5, "Command");
15956
+ Command5 = _Command5;
15957
+ _Archiver = class _Archiver {
15958
+ constructor(commander) {
15959
+ this.commander = commander;
15960
+ }
15961
+ };
15962
+ __name(_Archiver, "Archiver");
15963
+ Archiver = _Archiver;
15964
+ _Archiver1 = class _Archiver1 extends Archiver {
15965
+ async loadArchive(archivePath) {
15966
+ await this.commander.$transaction(async (prisma) => {
15967
+ const roles = JSON.parse(await fsp2.readFile(resolve9(archivePath, "roles", "roles.json"), "utf8"));
15968
+ await prisma.roles.createMany({ data: roles });
15969
+ const userFiles = await fsp2.readdir(resolve9(archivePath, "users"));
15970
+ const users = await Promise.all(userFiles.map(async (userFile) => {
15971
+ return JSON.parse(await fsp2.readFile(resolve9(archivePath, "users", userFile), "utf8"));
15972
+ }));
15973
+ await prisma.users.createMany({ data: users });
15974
+ const bagNames = await fsp2.readdir(resolve9(archivePath, "bags"));
15975
+ for (const bagFilename of bagNames) {
15976
+ const stat = await fsp2.stat(resolve9(archivePath, "bags", bagFilename));
15977
+ if (!stat.isDirectory()) continue;
15978
+ console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
15979
+ await this.restoreBag(resolve9(archivePath, "bags", bagFilename), prisma);
15897
15980
  }
15898
- }
15981
+ const recipeNames = await fsp2.readdir(resolve9(archivePath, "recipes"));
15982
+ for (const recipeFilename of recipeNames) {
15983
+ if (!recipeFilename.endsWith(".json")) continue;
15984
+ console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
15985
+ await this.restoreRecipe(resolve9(archivePath, "recipes", recipeFilename), prisma);
15986
+ }
15987
+ }).catch((e) => {
15988
+ if (e instanceof PrismaClientKnownRequestError) {
15989
+ console.log(e.code, e.meta, e.message);
15990
+ throw e.message;
15991
+ } else {
15992
+ throw e;
15993
+ }
15994
+ });
15899
15995
  }
15900
- });
15901
- }
15902
- async restoreBag(folder, prisma) {
15903
- const bagInfo = JSON.parse(await fsp2.readFile(join(folder, "meta.json"), "utf8"));
15904
- await prisma.bags.create({
15905
- data: {
15906
- bag_id: bagInfo.bag_id,
15907
- bag_name: bagInfo.bag_name,
15908
- description: bagInfo.description,
15909
- owner_id: bagInfo.owner_id,
15910
- is_plugin: bagInfo.bag_name.startsWith("$:/"),
15911
- acl: { createMany: { data: bagInfo.acl } }
15996
+ async restoreRecipe(file, prisma) {
15997
+ const recipeInfo = JSON.parse(await fsp2.readFile(file, "utf8"));
15998
+ await prisma.recipes.create({
15999
+ data: {
16000
+ recipe_id: recipeInfo.recipe_id,
16001
+ recipe_name: recipeInfo.recipe_name,
16002
+ description: recipeInfo.description,
16003
+ owner_id: recipeInfo.owner_id,
16004
+ acl: { createMany: { data: recipeInfo.acl } },
16005
+ recipe_bags: {
16006
+ createMany: {
16007
+ data: recipeInfo.recipe_bags.map((e) => ({
16008
+ bag_id: e.bag_id,
16009
+ position: e.position,
16010
+ with_acl: e.with_acl
16011
+ }))
16012
+ }
16013
+ }
16014
+ }
16015
+ });
15912
16016
  }
15913
- });
15914
- const tiddlerFiles = await fsp2.readdir(join(folder, "tiddlers"));
15915
- const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
15916
- if (!tiddlerFilename.endsWith(".json")) return;
15917
- const value = await fsp2.readFile(join(folder, "tiddlers", tiddlerFilename), "utf8");
15918
- return JSON.parse(value);
15919
- }));
15920
- await prisma.tiddlers.createMany({
15921
- data: tiddlers.flatMap((tiddler) => ({
15922
- bag_id: bagInfo.bag_id,
15923
- title: tiddler.title,
15924
- is_deleted: tiddler.is_deleted,
15925
- attachment_hash: tiddler.attachment_hash,
15926
- tiddler_id: tiddler.tiddler_id
15927
- }))
15928
- });
15929
- await prisma.fields.createMany({
15930
- data: tiddlers.flatMap(
15931
- ({ tiddler_id, fields }) => Object.entries(fields).map(
15932
- ([field_name, field_value]) => ({ tiddler_id, field_name, field_value })
15933
- )
15934
- )
15935
- });
15936
- }
15937
- };
15938
- __name(_Archiver1, "Archiver1");
15939
- var Archiver1 = _Archiver1;
15940
- var _Archiver2 = class _Archiver2 extends Archiver {
15941
- async loadArchive(archivePath) {
15942
- await this.commander.$transaction(async (prisma) => {
15943
- const roles = JSON.parse(await fsp2.readFile(resolve9(archivePath, "roles.json"), "utf8"));
15944
- await prisma.roles.createMany({ data: roles });
15945
- const users = JSON.parse(await fsp2.readFile(resolve9(archivePath, "users.json"), "utf8"));
15946
- await Promise.all(users.map((e) => prisma.users.create({
15947
- data: {
15948
- user_id: e.user_id,
15949
- email: e.email,
15950
- password: e.password,
15951
- username: e.username,
15952
- created_at: e.created_at,
15953
- last_login: e.last_login,
15954
- roles: { connect: e.roles.map((e2) => ({ role_id: e2.role_id })) }
15955
- }
15956
- })));
15957
- const bagNames = await fsp2.readdir(resolve9(archivePath, "bags"));
15958
- for (const bagFilename of bagNames) {
15959
- const stat = await fsp2.stat(resolve9(archivePath, "bags", bagFilename));
15960
- if (!stat.isDirectory()) continue;
15961
- console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
15962
- await this.restoreBag(resolve9(archivePath, "bags", bagFilename), prisma);
15963
- }
15964
- const recipeNames = await fsp2.readdir(resolve9(archivePath, "recipes"));
15965
- for (const recipeFilename of recipeNames) {
15966
- if (!recipeFilename.endsWith(".json")) continue;
15967
- console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
15968
- await this.restoreRecipe(resolve9(archivePath, "recipes", recipeFilename), prisma);
15969
- }
15970
- }).catch((e) => {
15971
- if (e instanceof PrismaClientKnownRequestError) {
15972
- console.log(e.code, e.meta, e.message);
15973
- throw e.message;
15974
- } else {
15975
- throw e;
16017
+ async restoreBag(folder, prisma) {
16018
+ const bagInfo = JSON.parse(await fsp2.readFile(join2(folder, "meta.json"), "utf8"));
16019
+ await prisma.bags.create({
16020
+ data: {
16021
+ bag_id: bagInfo.bag_id,
16022
+ bag_name: bagInfo.bag_name,
16023
+ description: bagInfo.description,
16024
+ owner_id: bagInfo.owner_id,
16025
+ is_plugin: bagInfo.bag_name.startsWith("$:/"),
16026
+ acl: { createMany: { data: bagInfo.acl } }
16027
+ }
16028
+ });
16029
+ const tiddlerFiles = await fsp2.readdir(join2(folder, "tiddlers"));
16030
+ const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
16031
+ if (!tiddlerFilename.endsWith(".json")) return;
16032
+ const value = await fsp2.readFile(join2(folder, "tiddlers", tiddlerFilename), "utf8");
16033
+ return JSON.parse(value);
16034
+ }));
16035
+ await prisma.tiddlers.createMany({
16036
+ data: tiddlers.flatMap((tiddler) => ({
16037
+ bag_id: bagInfo.bag_id,
16038
+ title: tiddler.title,
16039
+ is_deleted: tiddler.is_deleted,
16040
+ attachment_hash: tiddler.attachment_hash,
16041
+ tiddler_id: tiddler.tiddler_id
16042
+ }))
16043
+ });
16044
+ await prisma.fields.createMany({
16045
+ data: tiddlers.flatMap(
16046
+ ({ tiddler_id, fields }) => Object.entries(fields).map(
16047
+ ([field_name, field_value]) => ({ tiddler_id, field_name, field_value })
16048
+ )
16049
+ )
16050
+ });
15976
16051
  }
15977
- });
15978
- }
15979
- async restoreRecipe(file, prisma) {
15980
- const recipeInfo = JSON.parse(await fsp2.readFile(file, "utf8"));
15981
- await prisma.recipes.create({
15982
- data: {
15983
- recipe_id: recipeInfo.recipe_id,
15984
- recipe_name: recipeInfo.recipe_name,
15985
- description: recipeInfo.description,
15986
- owner_id: recipeInfo.owner_id,
15987
- acl: { createMany: { data: recipeInfo.acl } },
15988
- recipe_bags: {
15989
- createMany: {
15990
- data: recipeInfo.recipe_bags.map((e) => ({
15991
- bag_id: e.bag_id,
15992
- position: e.position,
15993
- with_acl: e.with_acl
15994
- }))
16052
+ };
16053
+ __name(_Archiver1, "Archiver1");
16054
+ Archiver1 = _Archiver1;
16055
+ _Archiver2 = class _Archiver2 extends Archiver {
16056
+ async loadArchive(archivePath) {
16057
+ await this.commander.$transaction(async (prisma) => {
16058
+ const roles = JSON.parse(await fsp2.readFile(resolve9(archivePath, "roles.json"), "utf8"));
16059
+ await prisma.roles.createMany({ data: roles });
16060
+ const users = JSON.parse(await fsp2.readFile(resolve9(archivePath, "users.json"), "utf8"));
16061
+ await Promise.all(users.map((e) => prisma.users.create({
16062
+ data: {
16063
+ user_id: e.user_id,
16064
+ email: e.email,
16065
+ password: e.password,
16066
+ username: e.username,
16067
+ created_at: e.created_at,
16068
+ last_login: e.last_login,
16069
+ roles: { connect: e.roles.map((e2) => ({ role_id: e2.role_id })) }
16070
+ }
16071
+ })));
16072
+ const bagNames = await fsp2.readdir(resolve9(archivePath, "bags"));
16073
+ for (const bagFilename of bagNames) {
16074
+ const stat = await fsp2.stat(resolve9(archivePath, "bags", bagFilename));
16075
+ if (!stat.isDirectory()) continue;
16076
+ console.log(`Reading bag ${decodeURIComponent(bagFilename)}`);
16077
+ await this.restoreBag(resolve9(archivePath, "bags", bagFilename), prisma);
15995
16078
  }
15996
- }
16079
+ const recipeNames = await fsp2.readdir(resolve9(archivePath, "recipes"));
16080
+ for (const recipeFilename of recipeNames) {
16081
+ if (!recipeFilename.endsWith(".json")) continue;
16082
+ console.log(`Reading recipe ${decodeURIComponent(recipeFilename)}`);
16083
+ await this.restoreRecipe(resolve9(archivePath, "recipes", recipeFilename), prisma);
16084
+ }
16085
+ }).catch((e) => {
16086
+ if (e instanceof PrismaClientKnownRequestError) {
16087
+ console.log(e.code, e.meta, e.message);
16088
+ throw e.message;
16089
+ } else {
16090
+ throw e;
16091
+ }
16092
+ });
15997
16093
  }
15998
- });
15999
- }
16000
- async restoreBag(folder, prisma) {
16001
- const bagInfo = JSON.parse(await fsp2.readFile(join(folder, "meta.json"), "utf8"));
16002
- await prisma.bags.create({
16003
- data: {
16004
- bag_id: bagInfo.bag_id,
16005
- bag_name: bagInfo.bag_name,
16006
- description: bagInfo.description,
16007
- owner_id: bagInfo.owner_id,
16008
- is_plugin: bagInfo.is_plugin,
16009
- acl: { createMany: { data: bagInfo.acl } }
16094
+ async restoreRecipe(file, prisma) {
16095
+ const recipeInfo = JSON.parse(await fsp2.readFile(file, "utf8"));
16096
+ await prisma.recipes.create({
16097
+ data: {
16098
+ recipe_id: recipeInfo.recipe_id,
16099
+ recipe_name: recipeInfo.recipe_name,
16100
+ description: recipeInfo.description,
16101
+ owner_id: recipeInfo.owner_id,
16102
+ acl: { createMany: { data: recipeInfo.acl } },
16103
+ recipe_bags: {
16104
+ createMany: {
16105
+ data: recipeInfo.recipe_bags.map((e) => ({
16106
+ bag_id: e.bag_id,
16107
+ position: e.position,
16108
+ with_acl: e.with_acl
16109
+ }))
16110
+ }
16111
+ }
16112
+ }
16113
+ });
16010
16114
  }
16011
- });
16012
- const tiddlerFiles = await fsp2.readdir(join(folder, "tiddlers"));
16013
- const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
16014
- if (!tiddlerFilename.endsWith(".json")) return;
16015
- const value = await fsp2.readFile(join(folder, "tiddlers", tiddlerFilename), "utf8");
16016
- return JSON.parse(value);
16017
- }));
16018
- await prisma.tiddlers.createMany({
16019
- data: tiddlers.flatMap((tiddler) => ({
16020
- bag_id: bagInfo.bag_id,
16021
- title: tiddler.title,
16022
- is_deleted: tiddler.is_deleted,
16023
- attachment_hash: tiddler.attachment_hash,
16024
- tiddler_id: tiddler.tiddler_id
16025
- }))
16026
- });
16027
- await prisma.fields.createMany({
16028
- data: tiddlers.flatMap(
16029
- ({ tiddler_id, fields }) => Object.entries(fields).map(
16030
- ([field_name, field_value]) => ({ tiddler_id, field_name, field_value })
16031
- )
16032
- )
16033
- });
16115
+ async restoreBag(folder, prisma) {
16116
+ const bagInfo = JSON.parse(await fsp2.readFile(join2(folder, "meta.json"), "utf8"));
16117
+ await prisma.bags.create({
16118
+ data: {
16119
+ bag_id: bagInfo.bag_id,
16120
+ bag_name: bagInfo.bag_name,
16121
+ description: bagInfo.description,
16122
+ owner_id: bagInfo.owner_id,
16123
+ is_plugin: bagInfo.is_plugin,
16124
+ acl: { createMany: { data: bagInfo.acl } }
16125
+ }
16126
+ });
16127
+ const tiddlerFiles = await fsp2.readdir(join2(folder, "tiddlers"));
16128
+ const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
16129
+ if (!tiddlerFilename.endsWith(".json")) return;
16130
+ const value = await fsp2.readFile(join2(folder, "tiddlers", tiddlerFilename), "utf8");
16131
+ return JSON.parse(value);
16132
+ }));
16133
+ await prisma.tiddlers.createMany({
16134
+ data: tiddlers.flatMap((tiddler) => ({
16135
+ bag_id: bagInfo.bag_id,
16136
+ title: tiddler.title,
16137
+ is_deleted: tiddler.is_deleted,
16138
+ attachment_hash: tiddler.attachment_hash,
16139
+ tiddler_id: tiddler.tiddler_id
16140
+ }))
16141
+ });
16142
+ await prisma.fields.createMany({
16143
+ data: tiddlers.flatMap(
16144
+ ({ tiddler_id, fields }) => Object.entries(fields).map(
16145
+ ([field_name, field_value]) => ({ tiddler_id, field_name, field_value })
16146
+ )
16147
+ )
16148
+ });
16149
+ }
16150
+ };
16151
+ __name(_Archiver2, "Archiver2");
16152
+ Archiver2 = _Archiver2;
16034
16153
  }
16035
- };
16036
- __name(_Archiver2, "Archiver2");
16037
- var Archiver2 = _Archiver2;
16154
+ });
16038
16155
 
16039
16156
  // src/commands/mws-init-store.ts
16040
16157
  var mws_init_store_exports = {};
@@ -16042,77 +16159,84 @@ __export(mws_init_store_exports, {
16042
16159
  Command: () => Command6,
16043
16160
  info: () => info6
16044
16161
  });
16045
- init_utils2();
16046
16162
  import { resolve as resolve10 } from "node:path";
16047
- var info6 = {
16048
- name: "mws-init-store",
16049
- synchronous: true
16050
- };
16051
- var _Command6 = class _Command6 {
16052
- constructor(params, commander, callback) {
16053
- this.params = params;
16054
- this.commander = commander;
16055
- this.callback = callback;
16056
- }
16057
- get $tw() {
16058
- return this.commander.$tw;
16059
- }
16060
- async execute() {
16061
- if (!this.commander.setupRequired) return;
16062
- await this.commander.$transaction(async (prisma) => {
16063
- const userCount = await prisma.users.count();
16064
- if (!userCount) {
16065
- await prisma.roles.createMany({
16066
- data: [
16067
- { role_id: 1, role_name: "ADMIN", description: "System Administrator" },
16068
- { role_id: 2, role_name: "USER", description: "Basic User" }
16069
- ]
16070
- });
16071
- const user = await prisma.users.create({
16072
- data: { username: "admin", email: "", password: "", roles: { connect: { role_id: 1 } } },
16073
- select: { user_id: true }
16074
- });
16075
- const password = await this.commander.PasswordService.PasswordCreation(user.user_id.toString(), "1234");
16076
- await prisma.users.update({
16077
- where: { user_id: user.user_id },
16078
- data: { password }
16163
+ var info6, _Command6, Command6;
16164
+ var init_mws_init_store = __esm({
16165
+ "src/commands/mws-init-store.ts"() {
16166
+ "use strict";
16167
+ init_esm_shims();
16168
+ init_utils2();
16169
+ info6 = {
16170
+ name: "mws-init-store",
16171
+ synchronous: true
16172
+ };
16173
+ _Command6 = class _Command6 {
16174
+ constructor(params, commander, callback) {
16175
+ this.params = params;
16176
+ this.commander = commander;
16177
+ this.callback = callback;
16178
+ }
16179
+ get $tw() {
16180
+ return this.commander.$tw;
16181
+ }
16182
+ async execute() {
16183
+ if (!this.commander.setupRequired) return;
16184
+ await this.commander.$transaction(async (prisma) => {
16185
+ const userCount = await prisma.users.count();
16186
+ if (!userCount) {
16187
+ await prisma.roles.createMany({
16188
+ data: [
16189
+ { role_id: 1, role_name: "ADMIN", description: "System Administrator" },
16190
+ { role_id: 2, role_name: "USER", description: "Basic User" }
16191
+ ]
16192
+ });
16193
+ const user = await prisma.users.create({
16194
+ data: { username: "admin", email: "", password: "", roles: { connect: { role_id: 1 } } },
16195
+ select: { user_id: true }
16196
+ });
16197
+ const password = await this.commander.PasswordService.PasswordCreation(user.user_id.toString(), "1234");
16198
+ await prisma.users.update({
16199
+ where: { user_id: user.user_id },
16200
+ data: { password }
16201
+ });
16202
+ }
16079
16203
  });
16204
+ const tweditions = resolve10(dist_require_resolve("tiddlywiki"), "../../editions");
16205
+ this.commander.addCommandTokens([
16206
+ "--mws-load-plugin-bags",
16207
+ "--mws-load-wiki-folder",
16208
+ dist_resolve("../editions/mws-docs"),
16209
+ "mws-docs",
16210
+ "MWS Documentation from https://mws.tiddlywiki.com",
16211
+ "mws-docs",
16212
+ "MWS Documentation from https://mws.tiddlywiki.com",
16213
+ "--mws-load-wiki-folder",
16214
+ resolve10(tweditions, "tw5.com"),
16215
+ "docs",
16216
+ "TiddlyWiki Documentation from https://tiddlywiki.com",
16217
+ "docs",
16218
+ "TiddlyWiki Documentation from https://tiddlywiki.com",
16219
+ "--mws-load-wiki-folder",
16220
+ resolve10(tweditions, "dev"),
16221
+ "dev",
16222
+ "TiddlyWiki Developer Documentation from https://tiddlywiki.com/dev",
16223
+ "dev-docs",
16224
+ "TiddlyWiki Developer Documentation from https://tiddlywiki.com/dev",
16225
+ "--mws-load-wiki-folder",
16226
+ resolve10(tweditions, "tour"),
16227
+ "tour",
16228
+ "TiddlyWiki Interactive Tour from https://tiddlywiki.com",
16229
+ "tour",
16230
+ "TiddlyWiki Interactive Tour from https://tiddlywiki.com",
16231
+ "--divider"
16232
+ ]);
16233
+ this.commander.setupRequired = false;
16080
16234
  }
16081
- });
16082
- const tweditions = resolve10(dist_require_resolve("tiddlywiki"), "../../editions");
16083
- this.commander.addCommandTokens([
16084
- "--mws-load-plugin-bags",
16085
- "--mws-load-wiki-folder",
16086
- dist_resolve("../editions/mws-docs"),
16087
- "mws-docs",
16088
- "MWS Documentation from https://mws.tiddlywiki.com",
16089
- "mws-docs",
16090
- "MWS Documentation from https://mws.tiddlywiki.com",
16091
- "--mws-load-wiki-folder",
16092
- resolve10(tweditions, "tw5.com"),
16093
- "docs",
16094
- "TiddlyWiki Documentation from https://tiddlywiki.com",
16095
- "docs",
16096
- "TiddlyWiki Documentation from https://tiddlywiki.com",
16097
- "--mws-load-wiki-folder",
16098
- resolve10(tweditions, "dev"),
16099
- "dev",
16100
- "TiddlyWiki Developer Documentation from https://tiddlywiki.com/dev",
16101
- "dev-docs",
16102
- "TiddlyWiki Developer Documentation from https://tiddlywiki.com/dev",
16103
- "--mws-load-wiki-folder",
16104
- resolve10(tweditions, "tour"),
16105
- "tour",
16106
- "TiddlyWiki Interactive Tour from https://tiddlywiki.com",
16107
- "tour",
16108
- "TiddlyWiki Interactive Tour from https://tiddlywiki.com",
16109
- "--divider"
16110
- ]);
16111
- this.commander.setupRequired = false;
16235
+ };
16236
+ __name(_Command6, "Command");
16237
+ Command6 = _Command6;
16112
16238
  }
16113
- };
16114
- __name(_Command6, "Command");
16115
- var Command6 = _Command6;
16239
+ });
16116
16240
 
16117
16241
  // src/commands/mws-listen.ts
16118
16242
  var mws_listen_exports = {};
@@ -16123,113 +16247,118 @@ __export(mws_listen_exports, {
16123
16247
  ListenerHTTPS: () => ListenerHTTPS,
16124
16248
  info: () => info7
16125
16249
  });
16126
- init_router();
16127
- init_streamer();
16128
16250
  import { ok as ok6 } from "assert";
16129
16251
  import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
16130
16252
  import { createServer } from "http";
16131
- import * as http22 from "node:http2";
16132
- var _ListenerBase = class _ListenerBase {
16133
- constructor(server3, router, bindInfo) {
16134
- this.server = server3;
16135
- this.router = router;
16136
- this.bindInfo = bindInfo;
16137
- this.server.on("request", (req, res) => {
16138
- this.handleRequest(req, res);
16139
- });
16140
- this.server.on("error", (error) => {
16141
- if (error.syscall !== "listen") {
16142
- throw error;
16253
+ import * as http2 from "node:http2";
16254
+ var _ListenerBase, ListenerBase, _ListenerHTTPS, ListenerHTTPS, _ListenerHTTP, ListenerHTTP, info7, _Command7, Command7;
16255
+ var init_mws_listen = __esm({
16256
+ "src/commands/mws-listen.ts"() {
16257
+ "use strict";
16258
+ init_esm_shims();
16259
+ init_router();
16260
+ _ListenerBase = class _ListenerBase {
16261
+ constructor(server3, router, bindInfo) {
16262
+ this.server = server3;
16263
+ this.router = router;
16264
+ this.bindInfo = bindInfo;
16265
+ this.server.on("request", (req, res) => {
16266
+ this.handleRequest(req, res);
16267
+ });
16268
+ this.server.on("error", (error) => {
16269
+ if (error.syscall !== "listen") {
16270
+ throw error;
16271
+ }
16272
+ switch (error.code) {
16273
+ case "EACCES":
16274
+ console.error(bindInfo + " requires elevated privileges");
16275
+ process.exit();
16276
+ break;
16277
+ case "EADDRINUSE":
16278
+ console.error(bindInfo + " is already in use");
16279
+ process.exit();
16280
+ break;
16281
+ default:
16282
+ throw error;
16283
+ }
16284
+ });
16285
+ this.server.on("listening", () => {
16286
+ const address = this.server.address();
16287
+ console.log(`Listening on`, address);
16288
+ });
16143
16289
  }
16144
- switch (error.code) {
16145
- case "EACCES":
16146
- console.error(bindInfo + " requires elevated privileges");
16147
- process.exit();
16148
- break;
16149
- case "EADDRINUSE":
16150
- console.error(bindInfo + " is already in use");
16151
- process.exit();
16152
- break;
16153
- default:
16154
- throw error;
16290
+ handleRequest(req, res) {
16291
+ this.router.handleIncomingRequest(req, res);
16155
16292
  }
16156
- });
16157
- this.server.on("listening", () => {
16158
- const address = this.server.address();
16159
- console.log(`Listening on`, address);
16160
- });
16161
- }
16162
- handleRequest(req, res) {
16163
- const streamer = new Streamer(req, res, this.router);
16164
- this.router.handle(streamer).catch(streamer.catcher);
16165
- }
16166
- };
16167
- __name(_ListenerBase, "ListenerBase");
16168
- var ListenerBase = _ListenerBase;
16169
- var _ListenerHTTPS = class _ListenerHTTPS extends ListenerBase {
16170
- constructor(router, config) {
16171
- const { port, host } = config;
16172
- if (port && typeof port !== "number") throw new Error("If specified, port must be a number");
16173
- const bindInfo = host ? `HTTPS ${host} ${port}` : `HTTPS ${port}`;
16174
- ok6(config.key && existsSync4(config.key), "Key file not found");
16175
- ok6(config.cert && existsSync4(config.cert), "Cert file not found");
16176
- const key = readFileSync3(config.key);
16177
- const cert = readFileSync3(config.cert);
16178
- super(http22.createSecureServer({ key, cert, allowHTTP1: true }), router, bindInfo);
16179
- if (port) this.server.listen(port, host);
16180
- }
16181
- };
16182
- __name(_ListenerHTTPS, "ListenerHTTPS");
16183
- var ListenerHTTPS = _ListenerHTTPS;
16184
- var _ListenerHTTP = class _ListenerHTTP extends ListenerBase {
16185
- /** Create an http1 server */
16186
- constructor(router, config) {
16187
- const { port, host } = config;
16188
- if (port && typeof port !== "number") throw new Error("If specified, port must be a number");
16189
- const bindInfo = host ? `HTTP ${host} ${port}` : `HTTP ${port}`;
16190
- super(createServer(), router, bindInfo);
16191
- if (port) this.server.listen(port, host);
16192
- }
16193
- };
16194
- __name(_ListenerHTTP, "ListenerHTTP");
16195
- var ListenerHTTP = _ListenerHTTP;
16196
- var info7 = {
16197
- name: "mws-listen",
16198
- synchronous: true
16199
- };
16200
- var _Command7 = class _Command7 {
16201
- constructor(params, commander, listenConfig, onListenersCreated) {
16202
- this.params = params;
16203
- this.commander = commander;
16204
- if (this.params.length) throw `${info7.name}: No parameters allowed. Please put listener options in the config file.`;
16205
- this.execute = async () => {
16206
- this.commander.addCommandTokens([
16207
- "--mws-render-tiddlywiki5",
16208
- "--divider"
16209
- ]);
16210
- const router = await Router3.makeRouter(
16211
- this.commander,
16212
- this.commander.config.enableDevServer
16213
- ).catch((e) => {
16214
- console.log(e.stack);
16215
- throw "Router failed to load";
16216
- });
16217
- const listeners = listenConfig.map((e) => {
16218
- if (!e.key !== !e.cert) {
16219
- throw new Error("Both key and cert are required for HTTPS");
16220
- }
16221
- const listener = e.key && e.cert ? new ListenerHTTPS(router, e) : new ListenerHTTP(router, e);
16222
- return listener;
16223
- });
16224
- await onListenersCreated?.(listeners);
16225
16293
  };
16294
+ __name(_ListenerBase, "ListenerBase");
16295
+ ListenerBase = _ListenerBase;
16296
+ _ListenerHTTPS = class _ListenerHTTPS extends ListenerBase {
16297
+ constructor(router, config) {
16298
+ const { port, host } = config;
16299
+ if (port && typeof port !== "number") throw new Error("If specified, port must be a number");
16300
+ const bindInfo = host ? `HTTPS ${host} ${port}` : `HTTPS ${port}`;
16301
+ ok6(config.key && existsSync4(config.key), "Key file not found");
16302
+ ok6(config.cert && existsSync4(config.cert), "Cert file not found");
16303
+ const key = readFileSync3(config.key);
16304
+ const cert = readFileSync3(config.cert);
16305
+ super(http2.createSecureServer({ key, cert, allowHTTP1: true }), router, bindInfo);
16306
+ if (port) this.server.listen(port, host);
16307
+ }
16308
+ };
16309
+ __name(_ListenerHTTPS, "ListenerHTTPS");
16310
+ ListenerHTTPS = _ListenerHTTPS;
16311
+ _ListenerHTTP = class _ListenerHTTP extends ListenerBase {
16312
+ /** Create an http1 server */
16313
+ constructor(router, config) {
16314
+ const { port, host } = config;
16315
+ if (port && typeof port !== "number") throw new Error("If specified, port must be a number");
16316
+ const bindInfo = host ? `HTTP ${host} ${port}` : `HTTP ${port}`;
16317
+ super(createServer(), router, bindInfo);
16318
+ if (port) this.server.listen(port, host);
16319
+ }
16320
+ };
16321
+ __name(_ListenerHTTP, "ListenerHTTP");
16322
+ ListenerHTTP = _ListenerHTTP;
16323
+ info7 = {
16324
+ name: "mws-listen",
16325
+ synchronous: true
16326
+ };
16327
+ _Command7 = class _Command7 {
16328
+ constructor(params, commander, listenConfig, onListenersCreated) {
16329
+ this.params = params;
16330
+ this.commander = commander;
16331
+ if (this.params.length) throw `${info7.name}: No parameters allowed. Please put listener options in the config file.`;
16332
+ this.execute = async () => {
16333
+ this.commander.addCommandTokens([
16334
+ "--mws-render-tiddlywiki5",
16335
+ "--divider"
16336
+ ]);
16337
+ const router = await Router2.makeRouter(
16338
+ this.commander,
16339
+ this.commander.config.enableDevServer ?? false
16340
+ ).catch((e) => {
16341
+ console.log(e.stack);
16342
+ throw "Router failed to load";
16343
+ });
16344
+ const listeners = listenConfig.map((e) => {
16345
+ if (!e.key !== !e.cert) {
16346
+ throw new Error("Both key and cert are required for HTTPS");
16347
+ }
16348
+ const listener = e.key && e.cert ? new ListenerHTTPS(router, e) : new ListenerHTTP(router, e);
16349
+ return listener;
16350
+ });
16351
+ await onListenersCreated?.(listeners);
16352
+ };
16353
+ }
16354
+ get $tw() {
16355
+ return this.commander.$tw;
16356
+ }
16357
+ };
16358
+ __name(_Command7, "Command");
16359
+ Command7 = _Command7;
16226
16360
  }
16227
- get $tw() {
16228
- return this.commander.$tw;
16229
- }
16230
- };
16231
- __name(_Command7, "Command");
16232
- var Command7 = _Command7;
16361
+ });
16233
16362
 
16234
16363
  // src/commands/divider.ts
16235
16364
  var divider_exports = {};
@@ -16237,21 +16366,28 @@ __export(divider_exports, {
16237
16366
  Command: () => Command8,
16238
16367
  info: () => info8
16239
16368
  });
16240
- var info8 = {
16241
- name: "divider",
16242
- synchronous: true
16243
- };
16244
- var _Command8 = class _Command8 {
16245
- constructor(params, commander) {
16246
- this.params = params;
16247
- this.commander = commander;
16248
- if (this.params.length) throw `${info8.name}: No parameters allowed. This is a no-op command.`;
16249
- }
16250
- execute() {
16369
+ var info8, _Command8, Command8;
16370
+ var init_divider = __esm({
16371
+ "src/commands/divider.ts"() {
16372
+ "use strict";
16373
+ init_esm_shims();
16374
+ info8 = {
16375
+ name: "divider",
16376
+ synchronous: true
16377
+ };
16378
+ _Command8 = class _Command8 {
16379
+ constructor(params, commander) {
16380
+ this.params = params;
16381
+ this.commander = commander;
16382
+ if (this.params.length) throw `${info8.name}: No parameters allowed. This is a no-op command.`;
16383
+ }
16384
+ execute() {
16385
+ }
16386
+ };
16387
+ __name(_Command8, "Command");
16388
+ Command8 = _Command8;
16251
16389
  }
16252
- };
16253
- __name(_Command8, "Command");
16254
- var Command8 = _Command8;
16390
+ });
16255
16391
 
16256
16392
  // src/commands/tests-complete.ts
16257
16393
  var tests_complete_exports = {};
@@ -16259,264 +16395,461 @@ __export(tests_complete_exports, {
16259
16395
  Command: () => Command9,
16260
16396
  info: () => info9
16261
16397
  });
16262
- var info9 = {
16263
- name: "tests-complete",
16264
- synchronous: true
16265
- };
16266
- var _Command9 = class _Command9 {
16267
- constructor(params, commander) {
16268
- this.params = params;
16269
- this.commander = commander;
16398
+ var info9, _Command9, Command9;
16399
+ var init_tests_complete = __esm({
16400
+ "src/commands/tests-complete.ts"() {
16401
+ "use strict";
16402
+ init_esm_shims();
16403
+ info9 = {
16404
+ name: "tests-complete",
16405
+ synchronous: true
16406
+ };
16407
+ _Command9 = class _Command9 {
16408
+ constructor(params, commander) {
16409
+ this.params = params;
16410
+ this.commander = commander;
16411
+ }
16412
+ execute() {
16413
+ console.log("Tests completed successfully.");
16414
+ process.exit(0);
16415
+ }
16416
+ };
16417
+ __name(_Command9, "Command");
16418
+ Command9 = _Command9;
16270
16419
  }
16271
- execute() {
16272
- console.log("Tests completed successfully.");
16273
- process.exit(0);
16420
+ });
16421
+
16422
+ // src/commands/mws-client-build.ts
16423
+ var mws_client_build_exports = {};
16424
+ __export(mws_client_build_exports, {
16425
+ Command: () => Command10,
16426
+ info: () => info10
16427
+ });
16428
+ var info10, _Command10, Command10;
16429
+ var init_mws_client_build = __esm({
16430
+ "src/commands/mws-client-build.ts"() {
16431
+ "use strict";
16432
+ init_esm_shims();
16433
+ init_setupDevServer();
16434
+ info10 = {
16435
+ name: "mws-client-build",
16436
+ synchronous: true
16437
+ };
16438
+ _Command10 = class _Command10 {
16439
+ constructor(params, commander) {
16440
+ this.params = params;
16441
+ this.commander = commander;
16442
+ if (this.params.length) throw `${info10.name}: No parameters allowed. This is a no-op command.`;
16443
+ }
16444
+ async execute() {
16445
+ if (!this.commander.config.enableDevServer) throw "Dev server is not enabled. Please set enableDevServer to true in the config file.";
16446
+ const { ctx, port, rootdir } = await esbuildStartup();
16447
+ ctx.dispose();
16448
+ }
16449
+ };
16450
+ __name(_Command10, "Command");
16451
+ Command10 = _Command10;
16274
16452
  }
16275
- };
16276
- __name(_Command9, "Command");
16277
- var Command9 = _Command9;
16453
+ });
16278
16454
 
16279
16455
  // src/commands/index.ts
16280
- var commands = {
16281
- [info.name]: mws_load_plugin_bags_exports,
16282
- [info2.name]: mws_render_tiddlywiki5_exports,
16283
- [info3.name]: mws_load_wiki_folder_exports,
16284
- [info4.name]: mws_save_archive_exports,
16285
- [info5.name]: mws_load_archive_exports,
16286
- [info6.name]: mws_init_store_exports,
16287
- [info7.name]: mws_listen_exports,
16288
- [info8.name]: divider_exports,
16289
- [info9.name]: tests_complete_exports
16290
- };
16291
-
16292
- // src/commander.ts
16293
- var _StartupCommander = class _StartupCommander {
16294
- constructor(config, $tw2, PasswordService) {
16295
- this.config = config;
16296
- this.$tw = $tw2;
16297
- this.PasswordService = PasswordService;
16298
- /** Signals that database setup is required. May be set to false by any qualified setup command. */
16299
- this.setupRequired = true;
16300
- this.wikiPath = config.wikiPath;
16301
- this.storePath = path4.resolve(this.wikiPath, "store");
16302
- this.databasePath = path4.resolve(this.storePath, "database.sqlite");
16303
- this.outputPath = path4.resolve($tw2.boot.wikiPath, $tw2.config.wikiOutputSubDir);
16304
- this.cachePath = path4.resolve(this.wikiPath, "cache");
16305
- if (!existsSync5(this.storePath)) {
16306
- mkdirSync2(this.storePath, { recursive: true });
16307
- this.setupRequired = true;
16308
- }
16309
- this.libsql = createClient({ url: "file:" + this.databasePath });
16310
- this.engine = new PrismaClient2({
16311
- log: ["info", "warn"],
16312
- adapter: new PrismaLibSQL(this.libsql)
16313
- // datasourceUrl: "file:" + this.databasePath
16314
- });
16315
- this.siteConfig = {
16316
- wikiPath: this.wikiPath,
16317
- allowAnonReads: !!config.config?.allowAnonReads,
16318
- allowAnonWrites: !!config.config?.allowAnonWrites,
16319
- allowUnreadableBags: !!config.config?.allowUnreadableBags,
16320
- attachmentsEnabled: !!config.config?.saveLargeTextToFileSystem,
16321
- attachmentSizeLimit: config.config?.saveLargeTextToFileSystem ?? 0,
16322
- enableBrowserCache: !!config.config?.enableBrowserCache,
16323
- enableGzip: !!config.config?.enableGzip,
16324
- contentTypeInfo: $tw2.config.contentTypeInfo,
16325
- storePath: this.storePath,
16326
- saveLargeTextToFileSystem: void 0
16456
+ var commands;
16457
+ var init_commands = __esm({
16458
+ "src/commands/index.ts"() {
16459
+ "use strict";
16460
+ init_esm_shims();
16461
+ init_mws_load_plugin_bags();
16462
+ init_mws_render_tiddlywiki5();
16463
+ init_mws_load_wiki_folder();
16464
+ init_mws_save_archive();
16465
+ init_mws_load_archive();
16466
+ init_mws_init_store();
16467
+ init_mws_listen();
16468
+ init_divider();
16469
+ init_tests_complete();
16470
+ init_mws_client_build();
16471
+ commands = {
16472
+ [info.name]: mws_load_plugin_bags_exports,
16473
+ [info2.name]: mws_render_tiddlywiki5_exports,
16474
+ [info3.name]: mws_load_wiki_folder_exports,
16475
+ [info4.name]: mws_save_archive_exports,
16476
+ [info5.name]: mws_load_archive_exports,
16477
+ [info6.name]: mws_init_store_exports,
16478
+ [info7.name]: mws_listen_exports,
16479
+ [info8.name]: divider_exports,
16480
+ [info9.name]: tests_complete_exports,
16481
+ [info10.name]: mws_client_build_exports
16327
16482
  };
16328
- this.SessionManager = config.SessionManager || SessionManager;
16329
- this.AttachmentService = config.AttachmentService || AttachmentService;
16330
- }
16331
- async init() {
16332
- this.setupRequired = false;
16333
- if (process.env.RUN_OLD_MWS_DB_SETUP_FOR_TESTING) {
16334
- await this.libsql.executeMultiple(readFileSync4(dist_resolve(
16335
- "../prisma/migrations/20250406213424_init/migration.sql"
16336
- ), "utf8"));
16337
- }
16338
- const tables = await this.libsql.batch([{
16339
- sql: `SELECT tbl_name FROM sqlite_master WHERE type='table'`,
16340
- args: []
16341
- }]).then((e) => e[0]?.rows);
16342
- const hasExisting = !!tables?.length;
16343
- const hasMigrationsTable = !!tables?.length && !!tables?.some((e) => e.tbl_name === "_prisma_migrations");
16344
- if (!hasMigrationsTable) await this.createMigrationsTable();
16345
- await this.checkMigrationsTable(hasExisting && !hasMigrationsTable);
16346
- const users = await this.engine.users.count();
16347
- if (!users) {
16348
- this.setupRequired = true;
16349
- }
16350
16483
  }
16351
- async createMigrationsTable() {
16352
- await this.libsql.execute({
16353
- sql: 'CREATE TABLE "_prisma_migrations" (\n "id" TEXT PRIMARY KEY NOT NULL,\n "checksum" TEXT NOT NULL,\n "finished_at" DATETIME,\n "migration_name" TEXT NOT NULL,\n "logs" TEXT,\n "rolled_back_at" DATETIME,\n "started_at" DATETIME NOT NULL DEFAULT current_timestamp,\n "applied_steps_count" INTEGER UNSIGNED NOT NULL DEFAULT 0\n)',
16354
- args: []
16355
- });
16356
- }
16357
- async checkMigrationsTable(migrateExisting) {
16358
- const applied_migrations = new Set(
16359
- await this.libsql.batch([{
16360
- sql: `Select migration_name from _prisma_migrations`,
16361
- args: []
16362
- }]).then((e) => e[0]?.rows.map((e2) => e2.migration_name))
16363
- );
16364
- const migrations = await readdir(dist_resolve("../prisma/migrations"));
16365
- migrations.sort();
16366
- const new_migrations = migrations.filter((m) => !applied_migrations.has(m) && m !== "migration_lock.toml");
16367
- if (!new_migrations.length) return;
16368
- function generateChecksum(fileContent) {
16369
- return createHash3("sha256").update(fileContent).digest("hex");
16370
- }
16371
- __name(generateChecksum, "generateChecksum");
16372
- console.log("New migrations found", new_migrations);
16373
- for (const migration of new_migrations) {
16374
- const migration_path = dist_resolve(`../prisma/migrations/${migration}/migration.sql`);
16375
- if (!existsSync5(migration_path)) continue;
16376
- const fileContent = await readFile(migration_path, "utf-8");
16377
- if (migrateExisting && migration === "20250406213424_init") {
16378
- console.log("Existing migration", migration, "is already applied");
16379
- } else {
16380
- console.log("Applying migration", migration);
16381
- await this.libsql.executeMultiple(fileContent);
16484
+ });
16485
+
16486
+ // src/db/sqlite-adapter.ts
16487
+ import { PrismaBetterSQLite3 } from "@prisma/adapter-better-sqlite3";
16488
+ import { readdir, readFile as readFile2 } from "fs/promises";
16489
+ import { createHash as createHash5, randomUUID } from "crypto";
16490
+ import { existsSync as existsSync5 } from "fs";
16491
+ var _SqliteAdapter, SqliteAdapter;
16492
+ var init_sqlite_adapter = __esm({
16493
+ "src/db/sqlite-adapter.ts"() {
16494
+ "use strict";
16495
+ init_esm_shims();
16496
+ init_utils2();
16497
+ _SqliteAdapter = class _SqliteAdapter {
16498
+ constructor(databasePath) {
16499
+ this.databasePath = databasePath;
16500
+ this.setupRequired = true;
16501
+ this.adapter = new PrismaBetterSQLite3({ url: "file:" + this.databasePath });
16502
+ }
16503
+ async init() {
16504
+ this.setupRequired = false;
16505
+ const libsql = await this.adapter.connect();
16506
+ if (process.env.RUN_OLD_MWS_DB_SETUP_FOR_TESTING) {
16507
+ await libsql.executeScript(await readFile2(dist_resolve(
16508
+ "../prisma/migrations/20250406213424_init/migration.sql"
16509
+ ), "utf8"));
16510
+ }
16511
+ const tables = await libsql.queryRaw({
16512
+ sql: `SELECT tbl_name FROM sqlite_master WHERE type='table'`,
16513
+ args: [],
16514
+ argTypes: []
16515
+ }).then((e) => e?.rows);
16516
+ const hasExisting = !!tables?.length;
16517
+ const hasMigrationsTable = !!tables?.length && !!tables?.some((e) => e[0] === "_prisma_migrations");
16518
+ if (!hasMigrationsTable) await this.createMigrationsTable(libsql);
16519
+ await this.checkMigrationsTable(libsql, hasExisting && !hasMigrationsTable);
16520
+ await libsql.dispose();
16521
+ }
16522
+ async createMigrationsTable(libsql) {
16523
+ await libsql.executeScript(
16524
+ 'CREATE TABLE "_prisma_migrations" (\n "id" TEXT PRIMARY KEY NOT NULL,\n "checksum" TEXT NOT NULL,\n "finished_at" DATETIME,\n "migration_name" TEXT NOT NULL,\n "logs" TEXT,\n "rolled_back_at" DATETIME,\n "started_at" DATETIME NOT NULL DEFAULT current_timestamp,\n "applied_steps_count" INTEGER UNSIGNED NOT NULL DEFAULT 0\n)'
16525
+ );
16526
+ }
16527
+ async checkMigrationsTable(libsql, migrateExisting) {
16528
+ const applied_migrations = new Set(
16529
+ await libsql.queryRaw({
16530
+ sql: `Select migration_name from _prisma_migrations`,
16531
+ args: [],
16532
+ argTypes: []
16533
+ }).then((e) => e.rows.map((e2) => e2[0]))
16534
+ );
16535
+ const migrations = await readdir(dist_resolve("../prisma/migrations"));
16536
+ migrations.sort();
16537
+ const new_migrations = migrations.filter((m) => !applied_migrations.has(m) && m !== "migration_lock.toml");
16538
+ if (!new_migrations.length) return;
16539
+ function generateChecksum(fileContent) {
16540
+ return createHash5("sha256").update(fileContent).digest("hex");
16541
+ }
16542
+ __name(generateChecksum, "generateChecksum");
16543
+ console.log("New migrations found", new_migrations);
16544
+ for (const migration of new_migrations) {
16545
+ const migration_path = dist_resolve(`../prisma/migrations/${migration}/migration.sql`);
16546
+ if (!existsSync5(migration_path)) continue;
16547
+ const fileContent = await readFile2(migration_path, "utf-8");
16548
+ if (migrateExisting && migration === "20250406213424_init") {
16549
+ console.log("Existing migration", migration, "is already applied");
16550
+ } else {
16551
+ console.log("Applying migration", migration);
16552
+ await libsql.executeScript(fileContent);
16553
+ }
16554
+ await libsql.executeRaw({
16555
+ sql: "INSERT INTO _prisma_migrations (id, migration_name, checksum, finished_at, logs, rolled_back_at, started_at, applied_steps_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
16556
+ args: [randomUUID(), migration, generateChecksum(fileContent), Date.now(), null, null, Date.now(), 1],
16557
+ argTypes: []
16558
+ // this doesn't appear to be used at the moment
16559
+ });
16560
+ }
16561
+ console.log("Migrations applied", new_migrations);
16382
16562
  }
16383
- await this.libsql.execute({
16384
- sql: "INSERT INTO _prisma_migrations (id, migration_name, checksum, finished_at, logs, rolled_back_at, started_at, applied_steps_count) VALUES (?, ?, ?, ?, ?, ?, ?, ?)",
16385
- args: [randomUUID(), migration, generateChecksum(fileContent), Date.now(), null, null, Date.now(), 1]
16386
- });
16387
- }
16388
- console.log("Migrations applied", new_migrations);
16389
- }
16390
- $transaction(fn, options) {
16391
- return this.engine.$transaction(fn, options);
16392
- }
16393
- };
16394
- __name(_StartupCommander, "StartupCommander");
16395
- var StartupCommander = _StartupCommander;
16396
- var _Commander = class _Commander extends StartupCommander {
16397
- constructor(config, $tw2, PasswordService) {
16398
- super(config, $tw2, PasswordService);
16399
- this.nextToken = 0;
16400
- this.verbose = false;
16401
- const { listeners, onListenersCreated } = config;
16402
- config.listeners = [];
16403
- config.onListenersCreated = void 0;
16404
- this.create_mws_listen = (params) => {
16405
- return new mws_listen_exports.Command(params, this, listeners, onListenersCreated);
16406
16563
  };
16564
+ __name(_SqliteAdapter, "SqliteAdapter");
16565
+ SqliteAdapter = _SqliteAdapter;
16407
16566
  }
16408
- static initCommands(moduleType) {
16409
- if (moduleType) throw new Error("moduleType is not implemented");
16410
- }
16411
- /*
16412
- Add a string of tokens to the command queue
16413
- */
16414
- addCommandTokens(params) {
16415
- if (this.verbose) console.log("Commander addCommandTokens", params);
16416
- this.commandTokens.splice(this.nextToken, 0, ...params);
16417
- }
16418
- /*
16419
- Execute the sequence of commands and invoke a callback on completion
16420
- */
16421
- execute(commandTokens) {
16422
- console.log("Commander", commandTokens);
16423
- this.commandTokens = commandTokens;
16424
- this.promise = new Promise((resolve13, reject) => {
16425
- this.callback = (err) => {
16426
- if (err) this.$tw.utils.error("Error: " + err);
16427
- err ? reject(err) : resolve13();
16428
- };
16429
- });
16430
- this.executeNextCommand();
16431
- return this.promise;
16432
- }
16433
- /*
16434
- Execute the next command in the sequence
16435
- */
16436
- executeNextCommand() {
16437
- if (this.nextToken >= this.commandTokens.length) {
16438
- this.callback(null);
16439
- return;
16440
- }
16441
- let commandName = this.commandTokens[this.nextToken++];
16442
- if (commandName.slice(0, 2) !== "--") {
16443
- console.log(this.commandTokens);
16444
- this.callback("Missing command: " + commandName);
16445
- return;
16446
- }
16447
- commandName = commandName.slice(2);
16448
- var command = commands[commandName], c, err;
16449
- if (!command) {
16450
- this.callback("Unknown command: " + commandName);
16451
- return;
16452
- }
16453
- const nextCommand = this.commandTokens.findIndex((token, i) => i >= this.nextToken && token.startsWith("--"));
16454
- const params = this.commandTokens.slice(this.nextToken, nextCommand === -1 ? void 0 : nextCommand);
16455
- this.nextToken = nextCommand === -1 ? this.commandTokens.length : nextCommand;
16456
- if (commandName !== divider_exports.info.name)
16457
- console.log("Commander executing", commandName, params);
16458
- const paramsIfMandetory = !command.info.mandatoryParameters ? params : this.extractNamedParameters(params, command.info.mandatoryParameters);
16459
- if (typeof params === "string") {
16460
- this.callback(params);
16461
- return;
16462
- }
16463
- new Promise(async (resolve13) => {
16464
- const { Command: Command10, info: info10 } = command;
16465
- try {
16466
- c = info10.name === "mws-listen" ? this.create_mws_listen(paramsIfMandetory) : new Command10(paramsIfMandetory, this, info10.synchronous ? void 0 : resolve13);
16467
- err = await c.execute();
16468
- if (err || info10.synchronous) resolve13(err);
16469
- } catch (e) {
16470
- resolve13(e);
16567
+ });
16568
+
16569
+ // src/commander.ts
16570
+ import * as path4 from "node:path";
16571
+ import { PrismaClient as PrismaClient2 } from "@prisma/client";
16572
+ import { existsSync as existsSync6, mkdirSync as mkdirSync2 } from "node:fs";
16573
+ import { ok as ok7 } from "node:assert";
16574
+ var _StartupCommander, StartupCommander, _Commander, Commander;
16575
+ var init_commander = __esm({
16576
+ "src/commander.ts"() {
16577
+ "use strict";
16578
+ init_esm_shims();
16579
+ init_sessions();
16580
+ init_attachments();
16581
+ init_commands();
16582
+ init_sqlite_adapter();
16583
+ _StartupCommander = class _StartupCommander {
16584
+ constructor(config, $tw2, PasswordService) {
16585
+ this.config = config;
16586
+ this.$tw = $tw2;
16587
+ this.PasswordService = PasswordService;
16588
+ if (config.config?.pathPrefix) {
16589
+ ok7(config.config.pathPrefix.startsWith("/"), "pathPrefix must start with a slash");
16590
+ ok7(!config.config.pathPrefix.endsWith("/"), "pathPrefix must not end with a slash");
16591
+ }
16592
+ this.wikiPath = config.wikiPath;
16593
+ this.storePath = path4.resolve(this.wikiPath, "store");
16594
+ this.databasePath = path4.resolve(this.storePath, "database.sqlite");
16595
+ this.outputPath = path4.resolve($tw2.boot.wikiPath, $tw2.config.wikiOutputSubDir);
16596
+ this.cachePath = path4.resolve(this.wikiPath, "cache");
16597
+ if (!existsSync6(this.storePath)) {
16598
+ mkdirSync2(this.storePath, { recursive: true });
16599
+ this.setupRequired = true;
16600
+ }
16601
+ this.siteConfig = {
16602
+ wikiPath: this.wikiPath,
16603
+ allowAnonReads: !!config.config?.allowAnonReads,
16604
+ allowAnonWrites: !!config.config?.allowAnonWrites,
16605
+ allowUnreadableBags: !!config.config?.allowUnreadableBags,
16606
+ attachmentsEnabled: !!config.config?.saveLargeTextToFileSystem,
16607
+ attachmentSizeLimit: config.config?.saveLargeTextToFileSystem ?? 0,
16608
+ enableBrowserCache: !!config.config?.enableBrowserCache,
16609
+ enableGzip: !!config.config?.enableGzip,
16610
+ contentTypeInfo: $tw2.config.contentTypeInfo,
16611
+ storePath: this.storePath,
16612
+ pathPrefix: config.config?.pathPrefix ?? "",
16613
+ saveLargeTextToFileSystem: void 0
16614
+ };
16615
+ this.SessionManager = config.SessionManager || SessionManager;
16616
+ this.AttachmentService = config.AttachmentService || AttachmentService;
16617
+ this.adapter = new SqliteAdapter(this.databasePath);
16618
+ this.engine = new PrismaClient2({ log: ["info", "warn"], adapter: this.adapter.adapter });
16619
+ }
16620
+ async init() {
16621
+ await this.adapter.init();
16622
+ const users = await this.engine.users.count();
16623
+ if (!users) {
16624
+ this.setupRequired = true;
16625
+ }
16471
16626
  }
16472
- }).then((err2) => {
16473
- if (err2) {
16474
- console.log(err2);
16475
- this.callback(err2);
16476
- } else {
16627
+ $transaction(fn, options) {
16628
+ return this.engine.$transaction(fn, options);
16629
+ }
16630
+ /** Signals that database setup is required. May be set to false by any qualified setup command. */
16631
+ get setupRequired() {
16632
+ return this.adapter.setupRequired;
16633
+ }
16634
+ set setupRequired(v) {
16635
+ this.adapter.setupRequired = v;
16636
+ }
16637
+ };
16638
+ __name(_StartupCommander, "StartupCommander");
16639
+ StartupCommander = _StartupCommander;
16640
+ _Commander = class _Commander extends StartupCommander {
16641
+ constructor(config, $tw2, PasswordService) {
16642
+ super(config, $tw2, PasswordService);
16643
+ this.nextToken = 0;
16644
+ this.verbose = false;
16645
+ const { listeners, onListenersCreated } = config;
16646
+ config.listeners = [];
16647
+ config.onListenersCreated = void 0;
16648
+ this.create_mws_listen = (params) => {
16649
+ return new mws_listen_exports.Command(params, this, listeners, onListenersCreated);
16650
+ };
16651
+ }
16652
+ static initCommands(moduleType) {
16653
+ if (moduleType) throw new Error("moduleType is not implemented");
16654
+ }
16655
+ /*
16656
+ Add a string of tokens to the command queue
16657
+ */
16658
+ addCommandTokens(params) {
16659
+ if (this.verbose) console.log("Commander addCommandTokens", params);
16660
+ this.commandTokens.splice(this.nextToken, 0, ...params);
16661
+ }
16662
+ /*
16663
+ Execute the sequence of commands and invoke a callback on completion
16664
+ */
16665
+ execute(commandTokens) {
16666
+ console.log("Commander", commandTokens);
16667
+ this.commandTokens = commandTokens;
16668
+ this.promise = new Promise((resolve13, reject) => {
16669
+ this.callback = (err) => {
16670
+ if (err) this.$tw.utils.error("Error: " + err);
16671
+ err ? reject(err) : resolve13();
16672
+ };
16673
+ });
16477
16674
  this.executeNextCommand();
16675
+ return this.promise;
16478
16676
  }
16479
- });
16677
+ /*
16678
+ Execute the next command in the sequence
16679
+ */
16680
+ executeNextCommand() {
16681
+ if (this.nextToken >= this.commandTokens.length) {
16682
+ this.callback(null);
16683
+ return;
16684
+ }
16685
+ let commandName = this.commandTokens[this.nextToken++];
16686
+ if (commandName.slice(0, 2) !== "--") {
16687
+ console.log(this.commandTokens);
16688
+ this.callback("Missing command: " + commandName);
16689
+ return;
16690
+ }
16691
+ commandName = commandName.slice(2);
16692
+ var command = commands[commandName], c, err;
16693
+ if (!command) {
16694
+ this.callback("Unknown command: " + commandName);
16695
+ return;
16696
+ }
16697
+ const nextCommand = this.commandTokens.findIndex((token, i) => i >= this.nextToken && token.startsWith("--"));
16698
+ const params = this.commandTokens.slice(this.nextToken, nextCommand === -1 ? void 0 : nextCommand);
16699
+ this.nextToken = nextCommand === -1 ? this.commandTokens.length : nextCommand;
16700
+ if (commandName !== divider_exports.info.name)
16701
+ console.log("Commander executing", commandName, params);
16702
+ const paramsIfMandetory = !command.info.mandatoryParameters ? params : this.extractNamedParameters(params, command.info.mandatoryParameters);
16703
+ if (typeof params === "string") {
16704
+ this.callback(params);
16705
+ return;
16706
+ }
16707
+ new Promise(async (resolve13) => {
16708
+ const { Command: Command11, info: info11 } = command;
16709
+ try {
16710
+ c = info11.name === "mws-listen" ? this.create_mws_listen(paramsIfMandetory) : new Command11(paramsIfMandetory, this, info11.synchronous ? void 0 : resolve13);
16711
+ err = await c.execute();
16712
+ if (err || info11.synchronous) resolve13(err);
16713
+ } catch (e) {
16714
+ resolve13(e);
16715
+ }
16716
+ }).then((err2) => {
16717
+ if (err2) {
16718
+ console.log(err2);
16719
+ this.callback(err2);
16720
+ } else {
16721
+ this.executeNextCommand();
16722
+ }
16723
+ });
16724
+ }
16725
+ /*
16726
+ Given an array of parameter strings `params` in name=value format, and an array of mandatory parameter names in `mandatoryParameters`, returns a hashmap of values or a string if error
16727
+ */
16728
+ extractNamedParameters(params, mandatoryParameters) {
16729
+ mandatoryParameters = mandatoryParameters || [];
16730
+ var errors = [], paramsByName = /* @__PURE__ */ Object.create(null);
16731
+ each(params, function(param) {
16732
+ var index = param.indexOf("=");
16733
+ if (index < 1) {
16734
+ errors.push("malformed named parameter: '" + param + "'");
16735
+ }
16736
+ paramsByName[param.slice(0, index)] = param.slice(index + 1).trim();
16737
+ });
16738
+ each(mandatoryParameters, function(mandatoryParameter) {
16739
+ if (!hop(paramsByName, mandatoryParameter)) {
16740
+ errors.push("missing mandatory parameter: '" + mandatoryParameter + "'");
16741
+ }
16742
+ });
16743
+ if (errors.length > 0) {
16744
+ return errors.join(" and\n");
16745
+ } else {
16746
+ return paramsByName;
16747
+ }
16748
+ }
16749
+ };
16750
+ __name(_Commander, "Commander");
16751
+ Commander = _Commander;
16480
16752
  }
16481
- /*
16482
- Given an array of parameter strings `params` in name=value format, and an array of mandatory parameter names in `mandatoryParameters`, returns a hashmap of values or a string if error
16483
- */
16484
- extractNamedParameters(params, mandatoryParameters) {
16485
- mandatoryParameters = mandatoryParameters || [];
16486
- var errors = [], paramsByName = /* @__PURE__ */ Object.create(null);
16487
- each(params, function(param) {
16488
- var index = param.indexOf("=");
16489
- if (index < 1) {
16490
- errors.push("malformed named parameter: '" + param + "'");
16491
- }
16492
- paramsByName[param.slice(0, index)] = param.slice(index + 1).trim();
16753
+ });
16754
+
16755
+ // src/services/PasswordService.ts
16756
+ import * as opaque from "@serenity-kit/opaque";
16757
+ import { randomBytes as randomBytes2 } from "node:crypto";
16758
+ async function createPasswordService(serverSetup) {
16759
+ await opaque.ready;
16760
+ const serverState = /* @__PURE__ */ new Map();
16761
+ const LoginGenerator = TypedGenerator.wrapper()(async function* ({
16762
+ user_id,
16763
+ startLoginRequest,
16764
+ registrationRecord
16765
+ }) {
16766
+ const { asV, asY } = TypedGenerator.checker();
16767
+ const { serverLoginState, loginResponse } = opaque.server.startLogin({
16768
+ serverSetup,
16769
+ userIdentifier: user_id.toString(),
16770
+ registrationRecord,
16771
+ startLoginRequest
16493
16772
  });
16494
- each(mandatoryParameters, function(mandatoryParameter) {
16495
- if (!hop(paramsByName, mandatoryParameter)) {
16496
- errors.push("missing mandatory parameter: '" + mandatoryParameter + "'");
16497
- }
16773
+ const timestamp = Date.now();
16774
+ const finishLoginRequest = asV(1, yield asY(0, loginResponse));
16775
+ if (timestamp + 1e3 * 60 * 5 < Date.now()) return;
16776
+ return asY(1, {
16777
+ session: opaque.server.finishLogin({
16778
+ finishLoginRequest,
16779
+ serverLoginState
16780
+ }),
16781
+ user_id
16498
16782
  });
16499
- if (errors.length > 0) {
16500
- return errors.join(" and\n");
16501
- } else {
16502
- return paramsByName;
16503
- }
16783
+ });
16784
+ async function PasswordCreation(userID, password) {
16785
+ const { clientRegistrationState, registrationRequest } = opaque.client.startRegistration({ password });
16786
+ const userIdentifier = userID;
16787
+ const { registrationResponse } = opaque.server.createRegistrationResponse({
16788
+ serverSetup,
16789
+ userIdentifier,
16790
+ registrationRequest
16791
+ });
16792
+ const { registrationRecord } = opaque.client.finishRegistration({
16793
+ clientRegistrationState,
16794
+ registrationResponse,
16795
+ password
16796
+ });
16797
+ return registrationRecord;
16504
16798
  }
16505
- };
16506
- __name(_Commander, "Commander");
16507
- var Commander = _Commander;
16799
+ __name(PasswordCreation, "PasswordCreation");
16800
+ async function createRegistrationResponse({ userID, registrationRequest }) {
16801
+ const { registrationResponse } = opaque.server.createRegistrationResponse({
16802
+ serverSetup,
16803
+ userIdentifier: userID.toString(),
16804
+ registrationRequest
16805
+ });
16806
+ return registrationResponse;
16807
+ }
16808
+ __name(createRegistrationResponse, "createRegistrationResponse");
16809
+ async function startLoginSession(stater) {
16810
+ let loginSession;
16811
+ do {
16812
+ loginSession = randomBytes2(16).toString("base64url");
16813
+ } while (serverState.has(loginSession));
16814
+ serverState.set(loginSession, stater);
16815
+ return loginSession;
16816
+ }
16817
+ __name(startLoginSession, "startLoginSession");
16818
+ async function finishLoginSession(loginSession) {
16819
+ const stater = serverState.get(loginSession);
16820
+ if (stater) serverState.delete(loginSession);
16821
+ return stater;
16822
+ }
16823
+ __name(finishLoginSession, "finishLoginSession");
16824
+ return {
16825
+ serverState,
16826
+ LoginGenerator,
16827
+ PasswordCreation,
16828
+ createRegistrationResponse,
16829
+ startLoginSession,
16830
+ finishLoginSession
16831
+ };
16832
+ }
16833
+ var init_PasswordService = __esm({
16834
+ "src/services/PasswordService.ts"() {
16835
+ "use strict";
16836
+ init_esm_shims();
16837
+ init_utils2();
16838
+ __name(createPasswordService, "createPasswordService");
16839
+ }
16840
+ });
16508
16841
 
16509
16842
  // src/server.ts
16510
- init_PasswordService();
16511
- init_sessions();
16843
+ import * as opaque2 from "@serenity-kit/opaque";
16844
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
16512
16845
  import { resolve as resolve12 } from "node:path";
16513
16846
  async function startServer(config) {
16514
16847
  await opaque2.ready;
16515
16848
  if (!["string", "number"].includes(typeof config.passwordMasterKeyFile)) {
16516
16849
  throw new Error("passwordMasterKeyFile must be a string or number");
16517
16850
  }
16518
- if (typeof config.passwordMasterKeyFile === "string" && config.passwordMasterKeyFile && !existsSync6(config.passwordMasterKeyFile)) {
16519
- writeFileSync3(config.passwordMasterKeyFile, opaque2.server.createSetup());
16851
+ if (typeof config.passwordMasterKeyFile === "string" && config.passwordMasterKeyFile && !existsSync7(config.passwordMasterKeyFile)) {
16852
+ writeFileSync4(config.passwordMasterKeyFile, opaque2.server.createSetup());
16520
16853
  console.log("Password master key created at", config.passwordMasterKeyFile);
16521
16854
  }
16522
16855
  const passwordMasterKey = readFileSync5(config.passwordMasterKeyFile, "utf8").trim();
@@ -16540,10 +16873,25 @@ async function startServer(config) {
16540
16873
  process.exit(1);
16541
16874
  }
16542
16875
  }
16543
- __name(startServer, "startServer");
16876
+ var init_server = __esm({
16877
+ "src/server.ts"() {
16878
+ init_esm_shims();
16879
+ init_router();
16880
+ init_StateObject();
16881
+ init_streamer();
16882
+ init_global();
16883
+ init_tiddlywiki();
16884
+ init_commander();
16885
+ init_PasswordService();
16886
+ init_sessions();
16887
+ __name(startServer, "startServer");
16888
+ }
16889
+ });
16890
+ init_server();
16544
16891
  export {
16545
16892
  SessionKeyMap,
16546
16893
  SessionManager,
16894
+ assertSignature,
16547
16895
  startServer as default,
16548
16896
  zodSession
16549
16897
  };