@tiddlywiki/mws 0.0.17 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.js CHANGED
@@ -15,10 +15,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
15
15
  if (typeof require !== "undefined") return require.apply(this, arguments);
16
16
  throw Error('Dynamic require of "' + x + '" is not supported');
17
17
  });
18
- var __glob = (map) => (path5) => {
19
- var fn = map[path5];
18
+ var __glob = (map) => (path6) => {
19
+ var fn = map[path6];
20
20
  if (fn) return fn();
21
- throw new Error("Module not found in bundle: " + path5);
21
+ throw new Error("Module not found in bundle: " + path6);
22
22
  };
23
23
  var __esm = (fn, res) => function __init() {
24
24
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -195,7 +195,7 @@ var require_depd = __commonJS({
195
195
  "node_modules/depd/index.js"(exports, module2) {
196
196
  "use strict";
197
197
  init_esm_shims();
198
- var relative = __require("path").relative;
198
+ var relative2 = __require("path").relative;
199
199
  module2.exports = depd;
200
200
  var basePath = process.cwd();
201
201
  function containsNamespace(str, namespace) {
@@ -401,7 +401,7 @@ var require_depd = __commonJS({
401
401
  }
402
402
  __name(formatColor, "formatColor");
403
403
  function formatLocation(callSite) {
404
- return relative(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
404
+ return relative2(basePath, callSite[0]) + ":" + callSite[1] + ":" + callSite[2];
405
405
  }
406
406
  __name(formatLocation, "formatLocation");
407
407
  function getStack() {
@@ -1786,14 +1786,14 @@ var require_etag = __commonJS({
1786
1786
  "use strict";
1787
1787
  init_esm_shims();
1788
1788
  module2.exports = etag;
1789
- var crypto = __require("crypto");
1789
+ var crypto2 = __require("crypto");
1790
1790
  var Stats = __require("fs").Stats;
1791
1791
  var toString = Object.prototype.toString;
1792
1792
  function entitytag(entity) {
1793
1793
  if (entity.length === 0) {
1794
1794
  return '"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"';
1795
1795
  }
1796
- var hash = crypto.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
1796
+ var hash = crypto2.createHash("sha1").update(entity, "utf8").digest("base64").substring(0, 27);
1797
1797
  var len = typeof entity === "string" ? Buffer.byteLength(entity, "utf8") : entity.length;
1798
1798
  return '"' + len.toString(16) + "-" + hash + '"';
1799
1799
  }
@@ -10497,11 +10497,11 @@ var require_mime_types = __commonJS({
10497
10497
  return exts[0];
10498
10498
  }
10499
10499
  __name(extension, "extension");
10500
- function lookup(path5) {
10501
- if (!path5 || typeof path5 !== "string") {
10500
+ function lookup(path6) {
10501
+ if (!path6 || typeof path6 !== "string") {
10502
10502
  return false;
10503
10503
  }
10504
- var extension2 = extname("x." + path5).toLowerCase().substr(1);
10504
+ var extension2 = extname("x." + path6).toLowerCase().substr(1);
10505
10505
  if (!extension2) {
10506
10506
  return false;
10507
10507
  }
@@ -10812,33 +10812,33 @@ var require_send = __commonJS({
10812
10812
  var escapeHtml = require_escape_html();
10813
10813
  var etag = require_etag();
10814
10814
  var fresh = require_fresh();
10815
- var fs3 = __require("fs");
10815
+ var fs4 = __require("fs");
10816
10816
  var mime = require_mime_types();
10817
10817
  var ms = require_ms();
10818
10818
  var onFinished = require_on_finished();
10819
10819
  var parseRange = require_range_parser();
10820
- var path5 = __require("path");
10820
+ var path6 = __require("path");
10821
10821
  var statuses = require_statuses();
10822
10822
  var Stream = __require("stream");
10823
10823
  var util = __require("util");
10824
- var extname = path5.extname;
10825
- var join3 = path5.join;
10826
- var normalize = path5.normalize;
10827
- var resolve13 = path5.resolve;
10828
- var sep2 = path5.sep;
10824
+ var extname = path6.extname;
10825
+ var join4 = path6.join;
10826
+ var normalize2 = path6.normalize;
10827
+ var resolve13 = path6.resolve;
10828
+ var sep2 = path6.sep;
10829
10829
  var BYTES_RANGE_REGEXP = /^ *bytes=/;
10830
10830
  var MAX_MAXAGE = 60 * 60 * 24 * 365 * 1e3;
10831
10831
  var UP_PATH_REGEXP = /(?:^|[\\/])\.\.(?:[\\/]|$)/;
10832
10832
  module2.exports = send2;
10833
- function send2(req, path6, options) {
10834
- return new SendStream(req, path6, options);
10833
+ function send2(req, path7, options) {
10834
+ return new SendStream(req, path7, options);
10835
10835
  }
10836
10836
  __name(send2, "send");
10837
- function SendStream(req, path6, options) {
10837
+ function SendStream(req, path7, options) {
10838
10838
  Stream.call(this);
10839
10839
  var opts = options || {};
10840
10840
  this.options = opts;
10841
- this.path = path6;
10841
+ this.path = path7;
10842
10842
  this.req = req;
10843
10843
  this._acceptRanges = opts.acceptRanges !== void 0 ? Boolean(opts.acceptRanges) : true;
10844
10844
  this._cacheControl = opts.cacheControl !== void 0 ? Boolean(opts.cacheControl) : true;
@@ -10953,10 +10953,10 @@ var require_send = __commonJS({
10953
10953
  var lastModified = this.res.getHeader("Last-Modified");
10954
10954
  return parseHttpDate(lastModified) <= parseHttpDate(ifRange);
10955
10955
  }, "isRangeFresh");
10956
- SendStream.prototype.redirect = /* @__PURE__ */ __name(function redirect(path6) {
10956
+ SendStream.prototype.redirect = /* @__PURE__ */ __name(function redirect(path7) {
10957
10957
  var res = this.res;
10958
10958
  if (hasListeners(this, "directory")) {
10959
- this.emit("directory", res, path6);
10959
+ this.emit("directory", res, path7);
10960
10960
  return;
10961
10961
  }
10962
10962
  if (this.hasTrailingSlash()) {
@@ -10976,38 +10976,38 @@ var require_send = __commonJS({
10976
10976
  SendStream.prototype.pipe = /* @__PURE__ */ __name(function pipe(res) {
10977
10977
  var root = this._root;
10978
10978
  this.res = res;
10979
- var path6 = decode(this.path);
10980
- if (path6 === -1) {
10979
+ var path7 = decode(this.path);
10980
+ if (path7 === -1) {
10981
10981
  this.error(400);
10982
10982
  return res;
10983
10983
  }
10984
- if (~path6.indexOf("\0")) {
10984
+ if (~path7.indexOf("\0")) {
10985
10985
  this.error(400);
10986
10986
  return res;
10987
10987
  }
10988
10988
  var parts;
10989
10989
  if (root !== null) {
10990
- if (path6) {
10991
- path6 = normalize("." + sep2 + path6);
10990
+ if (path7) {
10991
+ path7 = normalize2("." + sep2 + path7);
10992
10992
  }
10993
- if (UP_PATH_REGEXP.test(path6)) {
10994
- debug('malicious path "%s"', path6);
10993
+ if (UP_PATH_REGEXP.test(path7)) {
10994
+ debug('malicious path "%s"', path7);
10995
10995
  this.error(403);
10996
10996
  return res;
10997
10997
  }
10998
- parts = path6.split(sep2);
10999
- path6 = normalize(join3(root, path6));
10998
+ parts = path7.split(sep2);
10999
+ path7 = normalize2(join4(root, path7));
11000
11000
  } else {
11001
- if (UP_PATH_REGEXP.test(path6)) {
11002
- debug('malicious path "%s"', path6);
11001
+ if (UP_PATH_REGEXP.test(path7)) {
11002
+ debug('malicious path "%s"', path7);
11003
11003
  this.error(403);
11004
11004
  return res;
11005
11005
  }
11006
- parts = normalize(path6).split(sep2);
11007
- path6 = resolve13(path6);
11006
+ parts = normalize2(path7).split(sep2);
11007
+ path7 = resolve13(path7);
11008
11008
  }
11009
11009
  if (containsDotFile(parts)) {
11010
- debug('%s dotfile "%s"', this._dotfiles, path6);
11010
+ debug('%s dotfile "%s"', this._dotfiles, path7);
11011
11011
  switch (this._dotfiles) {
11012
11012
  case "allow":
11013
11013
  break;
@@ -11021,13 +11021,13 @@ var require_send = __commonJS({
11021
11021
  }
11022
11022
  }
11023
11023
  if (this._index.length && this.hasTrailingSlash()) {
11024
- this.sendIndex(path6);
11024
+ this.sendIndex(path7);
11025
11025
  return res;
11026
11026
  }
11027
- this.sendFile(path6);
11027
+ this.sendFile(path7);
11028
11028
  return res;
11029
11029
  }, "pipe");
11030
- SendStream.prototype.send = /* @__PURE__ */ __name(function send3(path6, stat) {
11030
+ SendStream.prototype.send = /* @__PURE__ */ __name(function send3(path7, stat) {
11031
11031
  var len = stat.size;
11032
11032
  var options = this.options;
11033
11033
  var opts = {};
@@ -11039,9 +11039,9 @@ var require_send = __commonJS({
11039
11039
  this.headersAlreadySent();
11040
11040
  return;
11041
11041
  }
11042
- debug('pipe "%s"', path6);
11043
- this.setHeader(path6, stat);
11044
- this.type(path6);
11042
+ debug('pipe "%s"', path7);
11043
+ this.setHeader(path7, stat);
11044
+ this.type(path7);
11045
11045
  if (this.isConditionalGET()) {
11046
11046
  if (this.isPreconditionFailure()) {
11047
11047
  this.error(412);
@@ -11090,30 +11090,30 @@ var require_send = __commonJS({
11090
11090
  res.end();
11091
11091
  return;
11092
11092
  }
11093
- this.stream(path6, opts);
11093
+ this.stream(path7, opts);
11094
11094
  }, "send");
11095
- SendStream.prototype.sendFile = /* @__PURE__ */ __name(function sendFile(path6) {
11095
+ SendStream.prototype.sendFile = /* @__PURE__ */ __name(function sendFile(path7) {
11096
11096
  var i = 0;
11097
11097
  var self = this;
11098
- debug('stat "%s"', path6);
11099
- fs3.stat(path6, /* @__PURE__ */ __name(function onstat(err, stat) {
11100
- var pathEndsWithSep = path6[path6.length - 1] === sep2;
11101
- if (err && err.code === "ENOENT" && !extname(path6) && !pathEndsWithSep) {
11098
+ debug('stat "%s"', path7);
11099
+ fs4.stat(path7, /* @__PURE__ */ __name(function onstat(err, stat) {
11100
+ var pathEndsWithSep = path7[path7.length - 1] === sep2;
11101
+ if (err && err.code === "ENOENT" && !extname(path7) && !pathEndsWithSep) {
11102
11102
  return next(err);
11103
11103
  }
11104
11104
  if (err) return self.onStatError(err);
11105
- if (stat.isDirectory()) return self.redirect(path6);
11105
+ if (stat.isDirectory()) return self.redirect(path7);
11106
11106
  if (pathEndsWithSep) return self.error(404);
11107
- self.emit("file", path6, stat);
11108
- self.send(path6, stat);
11107
+ self.emit("file", path7, stat);
11108
+ self.send(path7, stat);
11109
11109
  }, "onstat"));
11110
11110
  function next(err) {
11111
11111
  if (self._extensions.length <= i) {
11112
11112
  return err ? self.onStatError(err) : self.error(404);
11113
11113
  }
11114
- var p = path6 + "." + self._extensions[i++];
11114
+ var p = path7 + "." + self._extensions[i++];
11115
11115
  debug('stat "%s"', p);
11116
- fs3.stat(p, function(err2, stat) {
11116
+ fs4.stat(p, function(err2, stat) {
11117
11117
  if (err2) return next(err2);
11118
11118
  if (stat.isDirectory()) return next();
11119
11119
  self.emit("file", p, stat);
@@ -11122,7 +11122,7 @@ var require_send = __commonJS({
11122
11122
  }
11123
11123
  __name(next, "next");
11124
11124
  }, "sendFile");
11125
- SendStream.prototype.sendIndex = /* @__PURE__ */ __name(function sendIndex(path6) {
11125
+ SendStream.prototype.sendIndex = /* @__PURE__ */ __name(function sendIndex(path7) {
11126
11126
  var i = -1;
11127
11127
  var self = this;
11128
11128
  function next(err) {
@@ -11130,9 +11130,9 @@ var require_send = __commonJS({
11130
11130
  if (err) return self.onStatError(err);
11131
11131
  return self.error(404);
11132
11132
  }
11133
- var p = join3(path6, self._index[i]);
11133
+ var p = join4(path7, self._index[i]);
11134
11134
  debug('stat "%s"', p);
11135
- fs3.stat(p, function(err2, stat) {
11135
+ fs4.stat(p, function(err2, stat) {
11136
11136
  if (err2) return next(err2);
11137
11137
  if (stat.isDirectory()) return next();
11138
11138
  self.emit("file", p, stat);
@@ -11142,10 +11142,10 @@ var require_send = __commonJS({
11142
11142
  __name(next, "next");
11143
11143
  next();
11144
11144
  }, "sendIndex");
11145
- SendStream.prototype.stream = /* @__PURE__ */ __name(function stream(path6, options) {
11145
+ SendStream.prototype.stream = /* @__PURE__ */ __name(function stream(path7, options) {
11146
11146
  var self = this;
11147
11147
  var res = this.res;
11148
- var stream2 = fs3.createReadStream(path6, options);
11148
+ var stream2 = fs4.createReadStream(path7, options);
11149
11149
  this.emit("stream", stream2);
11150
11150
  stream2.pipe(res);
11151
11151
  function cleanup() {
@@ -11161,17 +11161,17 @@ var require_send = __commonJS({
11161
11161
  self.emit("end");
11162
11162
  }, "onend"));
11163
11163
  }, "stream");
11164
- SendStream.prototype.type = /* @__PURE__ */ __name(function type(path6) {
11164
+ SendStream.prototype.type = /* @__PURE__ */ __name(function type(path7) {
11165
11165
  var res = this.res;
11166
11166
  if (res.getHeader("Content-Type")) return;
11167
- var ext = extname(path6);
11167
+ var ext = extname(path7);
11168
11168
  var type2 = mime.contentType(ext) || "application/octet-stream";
11169
11169
  debug("content-type %s", type2);
11170
11170
  res.setHeader("Content-Type", type2);
11171
11171
  }, "type");
11172
- SendStream.prototype.setHeader = /* @__PURE__ */ __name(function setHeader(path6, stat) {
11172
+ SendStream.prototype.setHeader = /* @__PURE__ */ __name(function setHeader(path7, stat) {
11173
11173
  var res = this.res;
11174
- this.emit("headers", res, path6, stat);
11174
+ this.emit("headers", res, path7, stat);
11175
11175
  if (this._acceptRanges && !res.getHeader("Accept-Ranges")) {
11176
11176
  debug("accept ranges");
11177
11177
  res.setHeader("Accept-Ranges", "bytes");
@@ -11236,9 +11236,9 @@ var require_send = __commonJS({
11236
11236
  return err instanceof Error ? createError(status, err, { expose: false }) : createError(status, err);
11237
11237
  }
11238
11238
  __name(createHttpError, "createHttpError");
11239
- function decode(path6) {
11239
+ function decode(path7) {
11240
11240
  try {
11241
- return decodeURIComponent(path6);
11241
+ return decodeURIComponent(path7);
11242
11242
  } catch (err) {
11243
11243
  return -1;
11244
11244
  }
@@ -11662,14 +11662,6 @@ var init_data_checks = __esm({
11662
11662
  // allow owner for user
11663
11663
  user_id && { owner_id: { equals: user_id, not: null } },
11664
11664
  // allow acl for user
11665
- user_id && role_ids?.length && {
11666
- acl: {
11667
- some: {
11668
- permission: { in: checkPerms },
11669
- role_id: { in: role_ids }
11670
- }
11671
- }
11672
- },
11673
11665
  user_id && role_ids?.length && {
11674
11666
  acl: {
11675
11667
  some: {
@@ -11857,9 +11849,6 @@ var init_streamer = __esm({
11857
11849
  this.isSecure = !!req.socket.encrypted;
11858
11850
  this.urlInfo = new URL(`https://${this.headers.host}${this.url}`);
11859
11851
  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
- }
11863
11852
  }
11864
11853
  // RIP Push Stream. it was a great idea.
11865
11854
  // async pushStream(path: string) {
@@ -14268,7 +14257,7 @@ var init_bag_file_server = __esm({
14268
14257
  if (!recipe_name) {
14269
14258
  return state.sendEmpty(404);
14270
14259
  }
14271
- const bagTiddlers = await this.prisma.recipe_bags.findMany({
14260
+ const bags = await this.prisma.recipe_bags.findMany({
14272
14261
  where: { recipe: { recipe_name } },
14273
14262
  select: {
14274
14263
  position: true,
@@ -14276,36 +14265,28 @@ var init_bag_file_server = __esm({
14276
14265
  select: {
14277
14266
  bag_id: true,
14278
14267
  bag_name: true,
14279
- is_plugin: true,
14280
- tiddlers: {
14281
- select: {
14282
- title: true,
14283
- tiddler_id: true,
14284
- is_deleted: true,
14285
- attachment_hash: true,
14286
- fields: true
14287
- },
14288
- where: {
14289
- is_deleted: false
14290
- }
14291
- }
14268
+ is_plugin: true
14292
14269
  }
14293
14270
  }
14294
14271
  }
14295
14272
  });
14296
- bagTiddlers.sort((a, b) => a.position - b.position);
14297
- const recipeTiddlers = Array.from(new Map(bagTiddlers.flatMap(
14298
- (bag) => bag.bag.tiddlers.map((tiddler) => [tiddler.title, { bag: bag.bag, tiddler }])
14299
- )).values());
14273
+ const lastTiddlerId = await this.prisma.tiddlers.aggregate({
14274
+ _max: { tiddler_id: true },
14275
+ where: { bag_id: { in: bags.map((e) => e.bag.bag_id) } }
14276
+ });
14300
14277
  const template = readFileSync(resolve2(this.state.config.wikiPath, "tiddlywiki5.html"), "utf8");
14301
14278
  const hash = createHash2("md5");
14302
14279
  hash.update(template);
14303
- hash.update(recipeTiddlers.map((e) => e.tiddler.tiddler_id).join("|"));
14280
+ hash.update(bags.map((e) => e.bag.bag_name).join(","));
14281
+ hash.update(`${lastTiddlerId._max.tiddler_id}`);
14304
14282
  const contentDigest = hash.digest("hex");
14283
+ if ('"' + contentDigest + '"' === state.headers["if-none-match"])
14284
+ return state.sendEmpty(304, { "x-reason": "if-none-match" });
14305
14285
  state.writeHead(200, {
14306
14286
  "Content-Type": "text/html",
14307
14287
  "Etag": '"' + contentDigest + '"',
14308
- "Cache-Control": "max-age=0, must-revalidate"
14288
+ // TODO: WHY IS THIS DISABLED???
14289
+ "Cache-Control": "max-age=1000, must-revalidate"
14309
14290
  });
14310
14291
  if (state.method === "HEAD") return state.end();
14311
14292
  var marker = `<script class="tiddlywiki-tiddler-store" type="application/json">[`, markerPos = template.indexOf(marker);
@@ -14317,7 +14298,89 @@ var init_bag_file_server = __esm({
14317
14298
  state.write(",\n");
14318
14299
  }
14319
14300
  __name(writeTiddler, "writeTiddler");
14320
- state.write(template.substring(0, markerPos + marker.length));
14301
+ state.write(template.substring(0, markerPos));
14302
+ if (state.config.enablePluginCache) {
14303
+ const preloadMarkup = `
14304
+ ${"<"}script>
14305
+ window.$tw = window.$tw || Object.create(null);
14306
+ $tw.preloadTiddlers = $tw.preloadTiddlers || [];
14307
+ $tw.preloadTiddler = function(fields) {
14308
+ $tw.preloadTiddlers.push(fields);
14309
+ };
14310
+ ${"</"}script>
14311
+ `;
14312
+ state.write(preloadMarkup);
14313
+ const pluginMarkup = /* @__PURE__ */ __name((plugin, hash2) => `
14314
+ <script
14315
+ src="${state.config.pathPrefix}/$cache/${plugin}/plugin.js"
14316
+ integrity="${hash2}"
14317
+ crossorigin="anonymous"></script>
14318
+ `, "pluginMarkup");
14319
+ const plugins = [...(/* @__PURE__ */ new Set([
14320
+ "$:/core",
14321
+ "$:/plugins/tiddlywiki/multiwikiclient",
14322
+ "$:/plugins/tiddlywiki/tiddlyweb",
14323
+ "$:/themes/tiddlywiki/snowwhite",
14324
+ "$:/themes/tiddlywiki/vanilla",
14325
+ ...bags.map((e) => e.bag.bag_name)
14326
+ ])).values()].filter((e) => state.tiddlerCache.tiddlerFiles.has(e)).map((e) => pluginMarkup(
14327
+ state.tiddlerCache.tiddlerFiles.get(e),
14328
+ state.tiddlerCache.tiddlerHashes.get(e)
14329
+ ));
14330
+ state.write(plugins.join("\n"));
14331
+ }
14332
+ state.write(marker);
14333
+ const bagOrder = new Map(bags.map((e) => [e.bag.bag_id, e.position]));
14334
+ const bagIDs = bags.filter((e) => !state.tiddlerCache.tiddlerFiles.has(e.bag.bag_name)).map((e) => e.bag.bag_id);
14335
+ await this.serveStoreTiddlers(bagIDs, bagOrder, writeTiddler);
14336
+ writeTiddler({
14337
+ title: "$:/config/multiwikiclient/recipe",
14338
+ text: recipe_name
14339
+ });
14340
+ writeTiddler({
14341
+ title: "$:/state/multiwikiclient/recipe/last_tiddler_id",
14342
+ text: (lastTiddlerId._max.tiddler_id ?? 0).toString()
14343
+ });
14344
+ writeTiddler({
14345
+ title: "$:/config/multiwikiclient/host",
14346
+ text: "$protocol$//$host$" + this.state.config.pathPrefix + "/"
14347
+ });
14348
+ state.write(template.substring(markerPos + marker.length));
14349
+ return state.end();
14350
+ }
14351
+ async serveStoreTiddlers(bagKeys, bagOrder, writeTiddler) {
14352
+ const bagTiddlers = await this.prisma.bags.findMany({
14353
+ where: { bag_id: { in: bagKeys } },
14354
+ select: {
14355
+ bag_id: true,
14356
+ bag_name: true,
14357
+ is_plugin: true,
14358
+ description: true,
14359
+ owner_id: true,
14360
+ tiddlers: {
14361
+ select: {
14362
+ title: true,
14363
+ tiddler_id: true,
14364
+ is_deleted: true,
14365
+ attachment_hash: true,
14366
+ fields: true
14367
+ },
14368
+ where: {
14369
+ is_deleted: false,
14370
+ bag: { is_plugin: false }
14371
+ }
14372
+ }
14373
+ }
14374
+ });
14375
+ if (!bagTiddlers.every((e) => bagOrder.has(e.bag_id))) {
14376
+ console.log(bagTiddlers.map((e) => e.bag_id));
14377
+ console.log(bagOrder);
14378
+ throw new Error("Bags missing from bag order");
14379
+ }
14380
+ bagTiddlers.sort((a, b) => bagOrder.get(b.bag_id) - bagOrder.get(a.bag_id));
14381
+ const recipeTiddlers = Array.from(new Map(bagTiddlers.flatMap(
14382
+ (bag) => bag.tiddlers.map((tiddler) => [tiddler.title, { bag, tiddler }])
14383
+ )).values());
14321
14384
  const bagInfo = {}, revisionInfo = {};
14322
14385
  for (const recipeTiddlerInfo of recipeTiddlers) {
14323
14386
  const { title, tiddler_id, attachment_hash, fields } = recipeTiddlerInfo.tiddler;
@@ -14346,21 +14409,6 @@ var init_bag_file_server = __esm({
14346
14409
  text: JSON.stringify(revisionInfo),
14347
14410
  type: "application/json"
14348
14411
  });
14349
- writeTiddler({
14350
- title: "$:/config/multiwikiclient/recipe",
14351
- text: recipe_name
14352
- });
14353
- const lastTiddlerId = await this.prisma.tiddlers.aggregate({ _max: { tiddler_id: true } });
14354
- writeTiddler({
14355
- title: "$:/state/multiwikiclient/recipe/last_tiddler_id",
14356
- text: (lastTiddlerId._max.tiddler_id ?? 0).toString()
14357
- });
14358
- writeTiddler({
14359
- title: "$:/config/multiwikiclient/host",
14360
- text: "$protocol$//$host$" + this.state.config.pathPrefix + "/"
14361
- });
14362
- state.write(template.substring(markerPos + marker.length));
14363
- return state.end();
14364
14412
  }
14365
14413
  };
14366
14414
  __name(_TiddlerServer, "TiddlerServer");
@@ -14627,26 +14675,27 @@ var init_router_tiddlers = __esm({
14627
14675
  }
14628
14676
  });
14629
14677
 
14630
- // src/routes/tw-test.ts
14678
+ // src/routes/tw-routes.ts
14631
14679
  import { TiddlyWiki } from "tiddlywiki";
14632
14680
  function DocsRoute(parent, config) {
14633
14681
  const wikiRouter = new TWRouter(config);
14682
+ console.log("The mws-docs tiddlywiki is being served at " + config.pathPrefix + "/mws-docs");
14634
14683
  parent.defineRoute({
14635
14684
  method: ["OPTIONS", "GET", "HEAD", "POST", "PUT", "DELETE"],
14636
14685
  bodyFormat: "stream",
14637
- path: /^\/mws(\/|$)/,
14686
+ path: /^\/mwsp-docs(\/|$)/,
14638
14687
  pathParams: []
14639
14688
  }, async (state) => {
14640
- if (state.urlInfo.pathname === "/mws") throw state.redirect("/mws/");
14689
+ if (state.urlInfo.pathname === "/mws-docs") throw state.redirect("/mws-docs/");
14641
14690
  const { req, res } = state.streamer;
14642
- if (req.url === "/mws") req.url = "/mws/";
14691
+ if (req.url === "/mws-docs") req.url = "/mws-docs/";
14643
14692
  wikiRouter.twserver.requestHandler(req, res, {});
14644
14693
  return new Promise((r, c) => res.on("finish", r).on("error", c));
14645
14694
  });
14646
14695
  }
14647
14696
  var _TWRouter, TWRouter;
14648
- var init_tw_test = __esm({
14649
- "src/routes/tw-test.ts"() {
14697
+ var init_tw_routes = __esm({
14698
+ "src/routes/tw-routes.ts"() {
14650
14699
  "use strict";
14651
14700
  init_esm_shims();
14652
14701
  __name(DocsRoute, "DocsRoute");
@@ -14723,7 +14772,6 @@ async function RootRoute(root, config) {
14723
14772
  return state.sendJSON(200, await fn.call(table, state.data.arg));
14724
14773
  });
14725
14774
  });
14726
- await importEsbuild(root);
14727
14775
  }
14728
14776
  async function importEsbuild(root) {
14729
14777
  root.defineRoute({
@@ -14759,7 +14807,7 @@ var init_routes = __esm({
14759
14807
  init_utils2();
14760
14808
  init_managers();
14761
14809
  init_router_tiddlers();
14762
- init_tw_test();
14810
+ init_tw_routes();
14763
14811
  init_();
14764
14812
  __name(RootRoute, "RootRoute");
14765
14813
  __name(importEsbuild, "importEsbuild");
@@ -14944,7 +14992,10 @@ var init_setupDevServer = __esm({
14944
14992
 
14945
14993
  // src/routes/cache.ts
14946
14994
  import { ok as ok4 } from "assert";
14947
- async function startupCache(commander2) {
14995
+ import * as fs2 from "fs";
14996
+ import * as path3 from "path";
14997
+ import * as crypto from "crypto";
14998
+ async function startupCache(rootRoute2, commander2) {
14948
14999
  const $tw2 = commander2.$tw;
14949
15000
  const bootTiddlers = $tw2.loadTiddlersFromPath($tw2.boot.bootPath).flatMap((file) => file.tiddlers);
14950
15001
  const coreTiddler = $tw2.loadPluginFolder($tw2.boot.corePath);
@@ -14954,7 +15005,71 @@ async function startupCache(commander2) {
14954
15005
  [coreTiddler.title, JSON.stringify(coreTiddler)]
14955
15006
  ]);
14956
15007
  const tiddlerFileCache = /* @__PURE__ */ new Map();
14957
- return { tiddlerFileCache, tiddlerMemoryCache };
15008
+ const { tiddlerFiles, tiddlerHashes } = await importTW5(path3.join($tw2.boot.corePath, ".."), commander2.cachePath, "client", $tw2);
15009
+ rootRoute2.defineRoute({
15010
+ method: ["GET", "HEAD"],
15011
+ path: /^\/\$cache\/(.*)\/plugin\.js$/,
15012
+ bodyFormat: "ignore",
15013
+ pathParams: ["plugin"]
15014
+ }, async (state) => {
15015
+ ZodAssert.pathParams(state, (z5) => ({
15016
+ plugin: z5.string()
15017
+ }));
15018
+ return state.sendFile(200, {}, {
15019
+ root: commander2.cachePath,
15020
+ reqpath: state.pathParams.plugin + "/plugin.js"
15021
+ });
15022
+ });
15023
+ return { tiddlerFileCache, tiddlerMemoryCache, tiddlerFiles, tiddlerHashes };
15024
+ }
15025
+ async function importTW5(twFolder, cacheFolder, type, $tw2) {
15026
+ const readLevel = /* @__PURE__ */ __name((d) => {
15027
+ return fs2.readdirSync(path3.join(twFolder, d)).filter((e) => !$tw2.boot.excludeRegExp.test(e)).map((e) => path3.join(d, e));
15028
+ }, "readLevel");
15029
+ const plugins = [
15030
+ ...[
15031
+ ...[
15032
+ "plugins",
15033
+ "themes"
15034
+ ].flatMap(readLevel),
15035
+ "languages"
15036
+ ].flatMap(readLevel),
15037
+ "core"
15038
+ ].map((e) => {
15039
+ const oldPath = path3.join(twFolder, e);
15040
+ const relativePluginPath = path3.normalize(path3.relative(twFolder, oldPath));
15041
+ return [oldPath, relativePluginPath];
15042
+ });
15043
+ plugins.push([
15044
+ dist_resolve("../plugins/client"),
15045
+ "plugins/mws/client"
15046
+ ]);
15047
+ const hashes = {};
15048
+ const tiddlerFiles = /* @__PURE__ */ new Map();
15049
+ const tiddlerHashes = /* @__PURE__ */ new Map();
15050
+ plugins.forEach(([oldPath, relativePluginPath]) => {
15051
+ const plugin = $tw2.loadPluginFolder(oldPath);
15052
+ const newPath = path3.join(cacheFolder, relativePluginPath);
15053
+ fs2.mkdirSync(newPath, { recursive: true });
15054
+ if (plugin && plugin.title) {
15055
+ plugin.text = JSON.stringify(JSON.parse(plugin.text));
15056
+ if (type === "server") {
15057
+ plugin.tiddlers = JSON.parse(plugin.text).tiddlers;
15058
+ delete plugin.text;
15059
+ fs2.writeFileSync(path3.join(newPath, "plugin.info"), JSON.stringify(plugin));
15060
+ } else if (type === "client") {
15061
+ let js = Buffer.from(`$tw.preloadTiddler(${JSON.stringify(plugin)});`, "utf8");
15062
+ let hash = crypto.createHash("sha384").update(js).digest("base64");
15063
+ fs2.writeFileSync(path3.join(newPath, "plugin.js"), js);
15064
+ tiddlerFiles.set(plugin.title, relativePluginPath);
15065
+ tiddlerHashes.set(plugin.title, "sha384-" + hash);
15066
+ }
15067
+ } else {
15068
+ console.log("Info: No plugin found at", oldPath);
15069
+ }
15070
+ });
15071
+ fs2.writeFileSync(path3.join(cacheFolder, "hashes.json"), JSON.stringify(hashes, null, 2));
15072
+ return { tiddlerFiles, tiddlerHashes };
14958
15073
  }
14959
15074
  var init_cache = __esm({
14960
15075
  "src/routes/cache.ts"() {
@@ -14962,6 +15077,7 @@ var init_cache = __esm({
14962
15077
  init_esm_shims();
14963
15078
  init_utils2();
14964
15079
  __name(startupCache, "startupCache");
15080
+ __name(importTW5, "importTW5");
14965
15081
  }
14966
15082
  });
14967
15083
 
@@ -14982,10 +15098,10 @@ function defineRoute(parent, route, handler) {
14982
15098
  route.handler = handler;
14983
15099
  return route;
14984
15100
  }
14985
- function zodRoute(method, path5, zodPathParams, bodyFormat, zodRequest, inner) {
15101
+ function zodRoute(method, path6, zodPathParams, bodyFormat, zodRequest, inner) {
14986
15102
  return {
14987
15103
  method,
14988
- path: path5,
15104
+ path: path6,
14989
15105
  bodyFormat,
14990
15106
  inner,
14991
15107
  zodRequest,
@@ -15056,7 +15172,8 @@ var init_router = __esm({
15056
15172
  });
15057
15173
  await commander2.SessionManager.defineRoutes(rootRoute2);
15058
15174
  await RootRoute(rootRoute2, commander2.siteConfig);
15059
- const cache = await startupCache(commander2);
15175
+ const cache = await startupCache(rootRoute2, commander2);
15176
+ await importEsbuild(rootRoute2);
15060
15177
  return new _Router(rootRoute2, commander2, cache);
15061
15178
  }
15062
15179
  get pathPrefix() {
@@ -15189,11 +15306,11 @@ var init_router = __esm({
15189
15306
  registerZodRoutes = /* @__PURE__ */ __name((root, router, keys) => {
15190
15307
  keys.forEach((key) => {
15191
15308
  const route = router[key];
15192
- const { method, path: path5, bodyFormat, zodPathParams, zodRequest, inner } = route;
15193
- const pathParams = path5.split("/").filter((e) => e.startsWith(":")).map((e) => e.substring(1));
15194
- if (!path5.startsWith("/")) throw new Error(`Path ${path5} must start with a forward slash`);
15309
+ const { method, path: path6, bodyFormat, zodPathParams, zodRequest, inner } = route;
15310
+ const pathParams = path6.split("/").filter((e) => e.startsWith(":")).map((e) => e.substring(1));
15311
+ if (!path6.startsWith("/")) throw new Error(`Path ${path6} must start with a forward slash`);
15195
15312
  if (key.startsWith(":")) throw new Error(`Key ${key} must not start with a colon`);
15196
- const pathregex = "^" + path5.split("/").map(
15313
+ const pathregex = "^" + path6.split("/").map(
15197
15314
  (e) => e === "$key" ? key : e.startsWith(":") ? "([^/]+)" : e
15198
15315
  ).join("\\/") + "$";
15199
15316
  root.defineRoute({
@@ -15298,13 +15415,13 @@ var init_tiddlywiki = __esm({
15298
15415
  });
15299
15416
 
15300
15417
  // src/services/sessions.ts
15301
- import { createHash as createHash4, randomBytes } from "node:crypto";
15302
- function zodSession(path5, zodRequest, inner) {
15418
+ import { createHash as createHash5, randomBytes } from "node:crypto";
15419
+ function zodSession(path6, zodRequest, inner) {
15303
15420
  return {
15304
- ...zodRoute(["POST"], path5, (z5) => ({}), "json", zodRequest, async (state) => {
15421
+ ...zodRoute(["POST"], path6, (z5) => ({}), "json", zodRequest, async (state) => {
15305
15422
  return state.$transaction(async (prisma) => await inner(state, prisma));
15306
15423
  }),
15307
- path: path5
15424
+ path: path6
15308
15425
  };
15309
15426
  }
15310
15427
  async function createSession(prisma, user_id, session_key) {
@@ -15319,7 +15436,7 @@ async function createSession(prisma, user_id, session_key) {
15319
15436
  }).then(({ session_id: session_id2 }) => session_id2);
15320
15437
  }
15321
15438
  function assertSignature({ session_id, signature, session_key }) {
15322
- const hash = createHash4("sha256").update(session_key + session_id).digest("base64");
15439
+ const hash = createHash5("sha256").update(session_key + session_id).digest("base64");
15323
15440
  if (hash !== signature) throw "Invalid session signature.";
15324
15441
  }
15325
15442
  var SessionKeyMap, _SessionManager, SessionManager;
@@ -15412,17 +15529,17 @@ var init_sessions = __esm({
15412
15529
  registerZodRoutes(root, new _SessionManager(), Object.keys(SessionKeyMap));
15413
15530
  }
15414
15531
  static async parseIncomingRequest(streamer, router) {
15415
- const sessionId = streamer.cookies.get("session");
15416
- const session = sessionId && await router.engine.sessions.findUnique({
15417
- where: { session_id: sessionId },
15418
- select: { user: { select: { user_id: true, username: true, roles: { select: { role_id: true } } } } }
15532
+ const sessionId = streamer.cookies.getAll("session");
15533
+ const session = sessionId && await router.engine.sessions.findFirst({
15534
+ where: { session_id: { in: sessionId } },
15535
+ select: { session_id: true, user: { select: { user_id: true, username: true, roles: { select: { role_id: true } } } } }
15419
15536
  });
15420
15537
  if (sessionId && session) return {
15421
15538
  user_id: session.user.user_id,
15422
15539
  username: session.user.username,
15423
15540
  isAdmin: session.user.roles.some((e) => e.role_id === 1),
15424
15541
  role_ids: session.user.roles.map((e) => e.role_id),
15425
- sessionId,
15542
+ sessionId: session.session_id,
15426
15543
  isLoggedIn: true
15427
15544
  };
15428
15545
  else return {
@@ -15443,8 +15560,8 @@ var init_sessions = __esm({
15443
15560
  });
15444
15561
 
15445
15562
  // src/services/attachments.ts
15446
- import * as path3 from "path";
15447
- import * as fs2 from "fs";
15563
+ import * as path4 from "path";
15564
+ import * as fs3 from "fs";
15448
15565
  var import_sjcl2, $tw, _AttachmentService, AttachmentService;
15449
15566
  var init_attachments = __esm({
15450
15567
  "src/services/attachments.ts"() {
@@ -15543,15 +15660,15 @@ var init_attachments = __esm({
15543
15660
  async saveAttachment(options) {
15544
15661
  const contentHash = import_sjcl2.default.codec.hex.fromBits($tw.sjcl.hash.sha256.hash(options.text)).slice(0, 64).toString();
15545
15662
  const contentTypeInfo = this.config.contentTypeInfo[options.type] || this.config.contentTypeInfo["application/octet-stream"];
15546
- const attachmentPath = path3.resolve(this.config.storePath, "files", contentHash);
15663
+ const attachmentPath = path4.resolve(this.config.storePath, "files", contentHash);
15547
15664
  createDirectory(attachmentPath);
15548
15665
  const dataFilename = "data" + contentTypeInfo.extension;
15549
- fs2.writeFileSync(path3.resolve(attachmentPath, dataFilename), options.text, contentTypeInfo.encoding);
15550
- this.writeMetaFile(fs2, path3, attachmentPath, options, contentHash, dataFilename);
15666
+ fs3.writeFileSync(path4.resolve(attachmentPath, dataFilename), options.text, contentTypeInfo.encoding);
15667
+ this.writeMetaFile(fs3, path4, attachmentPath, options, contentHash, dataFilename);
15551
15668
  return contentHash;
15552
15669
  }
15553
- writeMetaFile(fs3, path5, attachmentPath, options, contentHash, dataFilename) {
15554
- fs3.writeFileSync(path5.resolve(attachmentPath, "meta.json"), JSON.stringify({
15670
+ writeMetaFile(fs4, path6, attachmentPath, options, contentHash, dataFilename) {
15671
+ fs4.writeFileSync(path6.resolve(attachmentPath, "meta.json"), JSON.stringify({
15555
15672
  _canonical_uri: options._canonical_uri,
15556
15673
  created: (/* @__PURE__ */ new Date()).toISOString(),
15557
15674
  modified: (/* @__PURE__ */ new Date()).toISOString(),
@@ -15565,11 +15682,11 @@ var init_attachments = __esm({
15565
15682
  */
15566
15683
  async adoptAttachment({ incomingFilepath, type, hash, _canonical_uri }) {
15567
15684
  const contentTypeInfo = this.config.contentTypeInfo[type] || this.config.contentTypeInfo["application/octet-stream"];
15568
- const attachmentPath = path3.resolve(this.config.storePath, "files", hash);
15685
+ const attachmentPath = path4.resolve(this.config.storePath, "files", hash);
15569
15686
  createDirectory(attachmentPath);
15570
- const dataFilename = "data" + contentTypeInfo.extension, dataFilepath = path3.resolve(attachmentPath, dataFilename);
15571
- fs2.renameSync(incomingFilepath, dataFilepath);
15572
- fs2.writeFileSync(path3.resolve(attachmentPath, "meta.json"), JSON.stringify({
15687
+ const dataFilename = "data" + contentTypeInfo.extension, dataFilepath = path4.resolve(attachmentPath, dataFilename);
15688
+ fs3.renameSync(incomingFilepath, dataFilepath);
15689
+ fs3.writeFileSync(path4.resolve(attachmentPath, "meta.json"), JSON.stringify({
15573
15690
  _canonical_uri,
15574
15691
  created: (/* @__PURE__ */ new Date()).toISOString(),
15575
15692
  modified: (/* @__PURE__ */ new Date()).toISOString(),
@@ -15586,15 +15703,15 @@ var init_attachments = __esm({
15586
15703
  */
15587
15704
  async getAttachmentStream(content_hash) {
15588
15705
  if (!this.isValidAttachmentName(content_hash)) return null;
15589
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15590
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15591
- if (!fs2.existsSync(metaJsonPath) || !fs2.statSync(metaJsonPath).isFile()) return null;
15592
- const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
15706
+ const attachmentPath = path4.resolve(this.config.storePath, "files", content_hash);
15707
+ const metaJsonPath = path4.resolve(attachmentPath, "meta.json");
15708
+ if (!fs3.existsSync(metaJsonPath) || !fs3.statSync(metaJsonPath).isFile()) return null;
15709
+ const meta = tryParseJSON(fs3.readFileSync(metaJsonPath, "utf8"));
15593
15710
  if (!meta) return null;
15594
- const dataFilepath = path3.resolve(attachmentPath, meta.filename);
15595
- if (!fs2.existsSync(dataFilepath) || !fs2.statSync(dataFilepath).isFile()) return null;
15711
+ const dataFilepath = path4.resolve(attachmentPath, meta.filename);
15712
+ if (!fs3.existsSync(dataFilepath) || !fs3.statSync(dataFilepath).isFile()) return null;
15596
15713
  return {
15597
- stream: fs2.createReadStream(dataFilepath),
15714
+ stream: fs3.createReadStream(dataFilepath),
15598
15715
  type: meta.type
15599
15716
  };
15600
15717
  }
@@ -15603,20 +15720,20 @@ var init_attachments = __esm({
15603
15720
  Returns the size in bytes, or null if the file doesn't exist.
15604
15721
  */
15605
15722
  async getAttachmentFileSize(content_hash) {
15606
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15607
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15608
- if (!(fs2.existsSync(metaJsonPath) && fs2.statSync(metaJsonPath).isFile())) return null;
15609
- const meta = tryParseJSON(fs2.readFileSync(metaJsonPath, "utf8"));
15723
+ const attachmentPath = path4.resolve(this.config.storePath, "files", content_hash);
15724
+ const metaJsonPath = path4.resolve(attachmentPath, "meta.json");
15725
+ if (!(fs3.existsSync(metaJsonPath) && fs3.statSync(metaJsonPath).isFile())) return null;
15726
+ const meta = tryParseJSON(fs3.readFileSync(metaJsonPath, "utf8"));
15610
15727
  if (!meta) return null;
15611
- const dataFilepath = path3.resolve(attachmentPath, meta.filename);
15612
- if (!(fs2.existsSync(dataFilepath) && fs2.statSync(dataFilepath).isFile())) return null;
15613
- return fs2.statSync(dataFilepath).size;
15728
+ const dataFilepath = path4.resolve(attachmentPath, meta.filename);
15729
+ if (!(fs3.existsSync(dataFilepath) && fs3.statSync(dataFilepath).isFile())) return null;
15730
+ return fs3.statSync(dataFilepath).size;
15614
15731
  }
15615
15732
  async getAttachmentMetadata(content_hash) {
15616
- const attachmentPath = path3.resolve(this.config.storePath, "files", content_hash);
15617
- const metaJsonPath = path3.resolve(attachmentPath, "meta.json");
15618
- if (!fs2.existsSync(metaJsonPath)) return null;
15619
- return JSON.parse(fs2.readFileSync(metaJsonPath, "utf8"));
15733
+ const attachmentPath = path4.resolve(this.config.storePath, "files", content_hash);
15734
+ const metaJsonPath = path4.resolve(attachmentPath, "meta.json");
15735
+ if (!fs3.existsSync(metaJsonPath)) return null;
15736
+ return JSON.parse(fs3.readFileSync(metaJsonPath, "utf8"));
15620
15737
  }
15621
15738
  };
15622
15739
  __name(_AttachmentService, "AttachmentService");
@@ -16772,8 +16889,8 @@ var require_command = __commonJS({
16772
16889
  init_esm_shims();
16773
16890
  var EventEmitter = __require("node:events").EventEmitter;
16774
16891
  var childProcess = __require("node:child_process");
16775
- var path5 = __require("node:path");
16776
- var fs3 = __require("node:fs");
16892
+ var path6 = __require("node:path");
16893
+ var fs4 = __require("node:fs");
16777
16894
  var process2 = __require("node:process");
16778
16895
  var { Argument: Argument2, humanReadableArgName } = require_argument();
16779
16896
  var { CommanderError: CommanderError2 } = require_error();
@@ -17754,7 +17871,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
17754
17871
  * @param {string} subcommandName
17755
17872
  */
17756
17873
  _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
17757
- if (fs3.existsSync(executableFile)) return;
17874
+ if (fs4.existsSync(executableFile)) return;
17758
17875
  const executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory";
17759
17876
  const executableMissing = `'${executableFile}' does not exist
17760
17877
  - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
@@ -17772,11 +17889,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
17772
17889
  let launchWithNode = false;
17773
17890
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
17774
17891
  function findFile(baseDir, baseName) {
17775
- const localBin = path5.resolve(baseDir, baseName);
17776
- if (fs3.existsSync(localBin)) return localBin;
17777
- if (sourceExt.includes(path5.extname(baseName))) return void 0;
17892
+ const localBin = path6.resolve(baseDir, baseName);
17893
+ if (fs4.existsSync(localBin)) return localBin;
17894
+ if (sourceExt.includes(path6.extname(baseName))) return void 0;
17778
17895
  const foundExt = sourceExt.find(
17779
- (ext) => fs3.existsSync(`${localBin}${ext}`)
17896
+ (ext) => fs4.existsSync(`${localBin}${ext}`)
17780
17897
  );
17781
17898
  if (foundExt) return `${localBin}${foundExt}`;
17782
17899
  return void 0;
@@ -17789,21 +17906,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
17789
17906
  if (this._scriptPath) {
17790
17907
  let resolvedScriptPath;
17791
17908
  try {
17792
- resolvedScriptPath = fs3.realpathSync(this._scriptPath);
17909
+ resolvedScriptPath = fs4.realpathSync(this._scriptPath);
17793
17910
  } catch {
17794
17911
  resolvedScriptPath = this._scriptPath;
17795
17912
  }
17796
- executableDir = path5.resolve(
17797
- path5.dirname(resolvedScriptPath),
17913
+ executableDir = path6.resolve(
17914
+ path6.dirname(resolvedScriptPath),
17798
17915
  executableDir
17799
17916
  );
17800
17917
  }
17801
17918
  if (executableDir) {
17802
17919
  let localFile = findFile(executableDir, executableFile);
17803
17920
  if (!localFile && !subcommand._executableFile && this._scriptPath) {
17804
- const legacyName = path5.basename(
17921
+ const legacyName = path6.basename(
17805
17922
  this._scriptPath,
17806
- path5.extname(this._scriptPath)
17923
+ path6.extname(this._scriptPath)
17807
17924
  );
17808
17925
  if (legacyName !== this._name) {
17809
17926
  localFile = findFile(
@@ -17814,7 +17931,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
17814
17931
  }
17815
17932
  executableFile = localFile || executableFile;
17816
17933
  }
17817
- launchWithNode = sourceExt.includes(path5.extname(executableFile));
17934
+ launchWithNode = sourceExt.includes(path6.extname(executableFile));
17818
17935
  let proc;
17819
17936
  if (process2.platform !== "win32") {
17820
17937
  if (launchWithNode) {
@@ -18662,7 +18779,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
18662
18779
  * @return {Command}
18663
18780
  */
18664
18781
  nameFromFilename(filename) {
18665
- this._name = path5.basename(filename, path5.extname(filename));
18782
+ this._name = path6.basename(filename, path6.extname(filename));
18666
18783
  return this;
18667
18784
  }
18668
18785
  /**
@@ -18676,9 +18793,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
18676
18793
  * @param {string} [path]
18677
18794
  * @return {(string|null|Command)}
18678
18795
  */
18679
- executableDir(path6) {
18680
- if (path6 === void 0) return this._executableDir;
18681
- this._executableDir = path6;
18796
+ executableDir(path7) {
18797
+ if (path7 === void 0) return this._executableDir;
18798
+ this._executableDir = path7;
18682
18799
  return this;
18683
18800
  }
18684
18801
  /**
@@ -19093,12 +19210,12 @@ __export(render_tiddlywiki5_exports, {
19093
19210
  info: () => info2
19094
19211
  });
19095
19212
  import { resolve as resolve6 } from "node:path";
19096
- var writeFileSync3, info2, _Command2, Command3;
19213
+ var writeFileSync4, info2, _Command2, Command3;
19097
19214
  var init_render_tiddlywiki5 = __esm({
19098
19215
  "src/commands/render-tiddlywiki5.ts"() {
19099
19216
  "use strict";
19100
19217
  init_esm_shims();
19101
- ({ writeFileSync: writeFileSync3 } = __require("fs"));
19218
+ ({ writeFileSync: writeFileSync4 } = __require("fs"));
19102
19219
  info2 = {
19103
19220
  name: "render-tiddlywiki5",
19104
19221
  description: "Render the TiddlyWiki5 HTML file",
@@ -19114,12 +19231,13 @@ var init_render_tiddlywiki5 = __esm({
19114
19231
  async execute() {
19115
19232
  const result = this.commander.$tw.wiki.renderTiddler("text/plain", "$:/core/templates/tiddlywiki5.html", {
19116
19233
  variables: {
19117
- saveTiddlerFilter: `
19118
- $:/boot/boot.css
19119
- $:/boot/boot.js
19120
- $:/boot/bootprefix.js
19234
+ // the boot and library tiddlers get rendered into the page
19235
+ // this list gets saved in the store array
19236
+ // we have to render at least one tiddler
19237
+ saveTiddlerFilter: this.commander.siteConfig.enablePluginCache ? `
19238
+ $:/temp/nothing
19239
+ ` : `
19121
19240
  $:/core
19122
- $:/library/sjcl.js
19123
19241
  $:/plugins/tiddlywiki/tiddlyweb
19124
19242
  $:/plugins/tiddlywiki/multiwikiclient
19125
19243
  $:/themes/tiddlywiki/snowwhite
@@ -19128,7 +19246,7 @@ var init_render_tiddlywiki5 = __esm({
19128
19246
  }
19129
19247
  });
19130
19248
  const filepath = resolve6(this.commander.wikiPath, "tiddlywiki5.html");
19131
- writeFileSync3(filepath, result);
19249
+ writeFileSync4(filepath, result);
19132
19250
  }
19133
19251
  };
19134
19252
  __name(_Command2, "Command");
@@ -19147,11 +19265,11 @@ function makePluginBagName(type, publisher, name) {
19147
19265
  return "$:/" + type + "/" + (publisher ? publisher + "/" : "") + name;
19148
19266
  }
19149
19267
  function loadWikiFolder({ $tw: $tw2, store, ...options }) {
19150
- const path5 = __require("path"), fs3 = __require("fs");
19151
- const wikiInfoPath = path5.resolve(options.wikiPath, $tw2.config.wikiInfo);
19268
+ const path6 = __require("path"), fs4 = __require("fs");
19269
+ const wikiInfoPath = path6.resolve(options.wikiPath, $tw2.config.wikiInfo);
19152
19270
  let wikiInfo;
19153
- if (fs3.existsSync(wikiInfoPath)) {
19154
- wikiInfo = $tw2.utils.parseJSONSafe(fs3.readFileSync(wikiInfoPath, "utf8"), function() {
19271
+ if (fs4.existsSync(wikiInfoPath)) {
19272
+ wikiInfo = $tw2.utils.parseJSONSafe(fs4.readFileSync(wikiInfoPath, "utf8"), function() {
19155
19273
  return null;
19156
19274
  });
19157
19275
  }
@@ -19178,7 +19296,7 @@ function loadWikiFolder({ $tw: $tw2, store, ...options }) {
19178
19296
  with_acl: true
19179
19297
  });
19180
19298
  recipeList.reverse();
19181
- const tiddler_files_path = path5.resolve(options.wikiPath, $tw2.config.wikiTiddlersSubDir);
19299
+ const tiddler_files_path = path6.resolve(options.wikiPath, $tw2.config.wikiTiddlersSubDir);
19182
19300
  const tiddlersFromPath = $tw2.loadTiddlersFromPath(
19183
19301
  resolve7($tw2.boot.corePath, $tw2.config.editionsPath, tiddler_files_path)
19184
19302
  );
@@ -19360,7 +19478,7 @@ __export(load_archive_exports, {
19360
19478
  Command: () => Command6,
19361
19479
  info: () => info5
19362
19480
  });
19363
- import { join as join2, resolve as resolve9 } from "path";
19481
+ import { join as join3, resolve as resolve9 } from "path";
19364
19482
  import * as _fsp2 from "fs/promises";
19365
19483
  import { PrismaClientKnownRequestError } from "@prisma/client/runtime/library";
19366
19484
  import { existsSync as existsSync3 } from "fs";
@@ -19465,7 +19583,7 @@ var init_load_archive = __esm({
19465
19583
  });
19466
19584
  }
19467
19585
  async restoreBag(folder, prisma) {
19468
- const bagInfo = JSON.parse(await fsp2.readFile(join2(folder, "meta.json"), "utf8"));
19586
+ const bagInfo = JSON.parse(await fsp2.readFile(join3(folder, "meta.json"), "utf8"));
19469
19587
  await prisma.bags.create({
19470
19588
  data: {
19471
19589
  bag_id: bagInfo.bag_id,
@@ -19476,10 +19594,10 @@ var init_load_archive = __esm({
19476
19594
  acl: { createMany: { data: bagInfo.acl } }
19477
19595
  }
19478
19596
  });
19479
- const tiddlerFiles = await fsp2.readdir(join2(folder, "tiddlers"));
19597
+ const tiddlerFiles = await fsp2.readdir(join3(folder, "tiddlers"));
19480
19598
  const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
19481
19599
  if (!tiddlerFilename.endsWith(".json")) return;
19482
- const value = await fsp2.readFile(join2(folder, "tiddlers", tiddlerFilename), "utf8");
19600
+ const value = await fsp2.readFile(join3(folder, "tiddlers", tiddlerFilename), "utf8");
19483
19601
  return JSON.parse(value);
19484
19602
  }));
19485
19603
  await prisma.tiddlers.createMany({
@@ -19563,7 +19681,7 @@ var init_load_archive = __esm({
19563
19681
  });
19564
19682
  }
19565
19683
  async restoreBag(folder, prisma) {
19566
- const bagInfo = JSON.parse(await fsp2.readFile(join2(folder, "meta.json"), "utf8"));
19684
+ const bagInfo = JSON.parse(await fsp2.readFile(join3(folder, "meta.json"), "utf8"));
19567
19685
  await prisma.bags.create({
19568
19686
  data: {
19569
19687
  bag_id: bagInfo.bag_id,
@@ -19574,10 +19692,10 @@ var init_load_archive = __esm({
19574
19692
  acl: { createMany: { data: bagInfo.acl } }
19575
19693
  }
19576
19694
  });
19577
- const tiddlerFiles = await fsp2.readdir(join2(folder, "tiddlers"));
19695
+ const tiddlerFiles = await fsp2.readdir(join3(folder, "tiddlers"));
19578
19696
  const tiddlers = await Promise.all(tiddlerFiles.map(async (tiddlerFilename) => {
19579
19697
  if (!tiddlerFilename.endsWith(".json")) return;
19580
- const value = await fsp2.readFile(join2(folder, "tiddlers", tiddlerFilename), "utf8");
19698
+ const value = await fsp2.readFile(join3(folder, "tiddlers", tiddlerFilename), "utf8");
19581
19699
  return JSON.parse(value);
19582
19700
  }));
19583
19701
  await prisma.tiddlers.createMany({
@@ -19981,7 +20099,7 @@ var init_commands = __esm({
19981
20099
  // src/db/sqlite-adapter.ts
19982
20100
  import { PrismaBetterSQLite3 } from "@prisma/adapter-better-sqlite3";
19983
20101
  import { readdir, readFile as readFile2 } from "fs/promises";
19984
- import { createHash as createHash5, randomUUID } from "crypto";
20102
+ import { createHash as createHash6, randomUUID } from "crypto";
19985
20103
  import { existsSync as existsSync5 } from "fs";
19986
20104
  var _SqliteAdapter, SqliteAdapter;
19987
20105
  var init_sqlite_adapter = __esm({
@@ -20030,7 +20148,7 @@ var init_sqlite_adapter = __esm({
20030
20148
  const new_migrations = migrations.filter((m) => !applied_migrations.has(m) && m !== "migration_lock.toml");
20031
20149
  if (!new_migrations.length) return;
20032
20150
  function generateChecksum(fileContent) {
20033
- return createHash5("sha256").update(fileContent).digest("hex");
20151
+ return createHash6("sha256").update(fileContent).digest("hex");
20034
20152
  }
20035
20153
  __name(generateChecksum, "generateChecksum");
20036
20154
  console.log("New migrations found", new_migrations);
@@ -20060,9 +20178,9 @@ var init_sqlite_adapter = __esm({
20060
20178
  });
20061
20179
 
20062
20180
  // src/commander.ts
20063
- import * as path4 from "node:path";
20181
+ import * as path5 from "node:path";
20064
20182
  import { PrismaClient as PrismaClient2 } from "@prisma/client";
20065
- import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4 } from "node:fs";
20183
+ import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync4 } from "node:fs";
20066
20184
  import { ok as ok7 } from "node:assert";
20067
20185
  var _StartupCommander, StartupCommander, _Commander, Commander;
20068
20186
  var init_commander = __esm({
@@ -20088,12 +20206,12 @@ var init_commander = __esm({
20088
20206
  ok7(!config.config.pathPrefix.endsWith("/"), "pathPrefix must not end with a slash");
20089
20207
  }
20090
20208
  this.wikiPath = config.wikiPath;
20091
- this.storePath = path4.resolve(this.wikiPath, "store");
20092
- this.databasePath = path4.resolve(this.storePath, "database.sqlite");
20093
- this.outputPath = path4.resolve($tw2.boot.wikiPath, $tw2.config.wikiOutputSubDir);
20094
- this.cachePath = path4.resolve(this.wikiPath, "cache");
20209
+ this.storePath = path5.resolve(this.wikiPath, "store");
20210
+ this.databasePath = path5.resolve(this.storePath, "database.sqlite");
20211
+ this.outputPath = path5.resolve($tw2.boot.wikiPath, $tw2.config.wikiOutputSubDir);
20212
+ this.cachePath = path5.resolve(this.wikiPath, "cache");
20095
20213
  if (!existsSync6(this.storePath)) {
20096
- mkdirSync2(this.storePath, { recursive: true });
20214
+ mkdirSync3(this.storePath, { recursive: true });
20097
20215
  this.setupRequired = true;
20098
20216
  }
20099
20217
  this.siteConfig = {
@@ -20375,7 +20493,7 @@ var init_PasswordService = __esm({
20375
20493
 
20376
20494
  // src/server.ts
20377
20495
  import * as opaque2 from "@serenity-kit/opaque";
20378
- import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
20496
+ import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "node:fs";
20379
20497
  import { resolve as resolve12 } from "node:path";
20380
20498
  async function startServer(config) {
20381
20499
  await opaque2.ready;
@@ -20383,7 +20501,7 @@ async function startServer(config) {
20383
20501
  throw new Error("passwordMasterKeyFile must be a string or number");
20384
20502
  }
20385
20503
  if (typeof config.passwordMasterKeyFile === "string" && config.passwordMasterKeyFile && !existsSync7(config.passwordMasterKeyFile)) {
20386
- writeFileSync4(config.passwordMasterKeyFile, opaque2.server.createSetup());
20504
+ writeFileSync5(config.passwordMasterKeyFile, opaque2.server.createSetup());
20387
20505
  console.log("Password master key created at", config.passwordMasterKeyFile);
20388
20506
  }
20389
20507
  const passwordMasterKey = readFileSync5(config.passwordMasterKeyFile, "utf8").trim();