@tiddlywiki/mws 0.2.6 → 0.2.7

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/mws.js CHANGED
@@ -46800,9 +46800,6 @@ function zodSession(path12, zodRequest, preflight, inner) {
46800
46800
  };
46801
46801
  }
46802
46802
  __name(zodSession, "zodSession");
46803
- serverEvents.on("mws.routes", (root, config3) => {
46804
- SessionManager.defineRoutes(root);
46805
- });
46806
46803
  var RateLimiter = class {
46807
46804
  constructor(minIntervalMs) {
46808
46805
  this.minIntervalMs = minIntervalMs;
@@ -46841,6 +46838,14 @@ var SessionManager = class _SessionManager {
46841
46838
  const route = new _SessionManager();
46842
46839
  const keys = Object.keys(route).filter((e) => route[e] instanceof zodRoute);
46843
46840
  registerZodRoutes(root, route, keys);
46841
+ root.defineRoute({
46842
+ method: ["GET", "HEAD", "OPTIONS", "PUT"],
46843
+ path: /^\/(?<item>login|profile)$/,
46844
+ bodyFormat: "stream"
46845
+ }, async (state) => {
46846
+ await state.sendAdmin();
46847
+ return STREAM_ENDED;
46848
+ });
46844
46849
  }
46845
46850
  static AdminRoleName = "ADMIN";
46846
46851
  static UserRoleName = "USER";
@@ -46887,7 +46892,7 @@ var SessionManager = class _SessionManager {
46887
46892
  username: z3.prismaField("Users", "username", "string"),
46888
46893
  startLoginRequest: z3.string()
46889
46894
  }), async (state) => {
46890
- state.assertReferer(["/login"]);
46895
+ state.assertReferer(["/login", "/profile"]);
46891
46896
  }, async (state, prisma) => {
46892
46897
  const { username, startLoginRequest } = state.data;
46893
46898
  const user = await prisma.users.findUnique({
@@ -46911,7 +46916,7 @@ var SessionManager = class _SessionManager {
46911
46916
  loginSession: z3.string(),
46912
46917
  skipCookie: z3.boolean().optional().default(false)
46913
46918
  }), async (state) => {
46914
- state.assertReferer(["/login"]);
46919
+ state.assertReferer(["/login", "/profile"]);
46915
46920
  }, async (state, prisma) => {
46916
46921
  const { finishLoginRequest, skipCookie, loginSession } = state.data;
46917
46922
  if (!loginSession) throw "Login session not found.";
@@ -47139,6 +47144,218 @@ import { stat as stat2, writeFile } from "fs/promises";
47139
47144
  // packages/mws/src/utils/index.ts
47140
47145
  init_esm_shims();
47141
47146
  import { Readable as Readable5 } from "stream";
47147
+
47148
+ // packages/mws/src/utils/shared.ts
47149
+ init_esm_shims();
47150
+
47151
+ // packages/mws/browser.ts
47152
+ init_esm_shims();
47153
+
47154
+ // packages/mws/src/new-managers/TabDataTypes.ts
47155
+ init_esm_shims();
47156
+
47157
+ // packages/mws/src/new-managers/TabDataZod.ts
47158
+ init_esm_shims();
47159
+ var bagPermissionLevelSchema = v4_exports.union([v4_exports.literal("A_read"), v4_exports.literal("B_write"), v4_exports.literal("C_admin")]);
47160
+ var pageIdSchema = v4_exports.union([v4_exports.literal("wikis"), v4_exports.literal("templates"), v4_exports.literal("bags"), v4_exports.literal("roles"), v4_exports.literal("users")]);
47161
+ var writablePrefixRowSchema = v4_exports.object({
47162
+ prefix: v4_exports.string(),
47163
+ bagName: v4_exports.string()
47164
+ });
47165
+ var bagPermissionRowSchema = v4_exports.object({
47166
+ role: v4_exports.string(),
47167
+ level: bagPermissionLevelSchema
47168
+ });
47169
+ var templateTypesSchema = v4_exports.literal("simpleV1");
47170
+ var extraServerStuffSchema = v4_exports.object({
47171
+ availablePlugins: v4_exports.array(v4_exports.object({
47172
+ name: v4_exports.string(),
47173
+ description: v4_exports.string()
47174
+ }))
47175
+ });
47176
+ var templateSharedDefinitionSchema = v4_exports.object({
47177
+ description: v4_exports.string(),
47178
+ readonlyBags: v4_exports.array(v4_exports.string()),
47179
+ plugins: v4_exports.array(v4_exports.string()),
47180
+ writablePrefixBags: v4_exports.array(writablePrefixRowSchema)
47181
+ });
47182
+ var templateDefinitionSchema = templateSharedDefinitionSchema.extend({
47183
+ type: templateTypesSchema,
47184
+ requiredPluginsEnabled: v4_exports.boolean(),
47185
+ externalStore: v4_exports.boolean(),
47186
+ externalPlugins: v4_exports.boolean(),
47187
+ twVersion: v4_exports.string().nullable(),
47188
+ customHtmlEnabled: v4_exports.boolean(),
47189
+ htmlContent: v4_exports.string(),
47190
+ injectionFunction: v4_exports.string(),
47191
+ injectionLocation: v4_exports.string()
47192
+ });
47193
+ var recipeDefinitionSchema = templateSharedDefinitionSchema.extend({
47194
+ displayName: v4_exports.string()
47195
+ });
47196
+ var idStringSchema = v4_exports.any();
47197
+ var iWikiSaveSchema = recipeDefinitionSchema.extend({
47198
+ id: idStringSchema,
47199
+ slug: v4_exports.string(),
47200
+ templateName: v4_exports.string(),
47201
+ recipeUsers: v4_exports.array(v4_exports.string()),
47202
+ recipeAdmins: v4_exports.array(v4_exports.string())
47203
+ });
47204
+ var iTemplateSaveSchema = templateDefinitionSchema.extend({
47205
+ id: idStringSchema,
47206
+ name: v4_exports.string(),
47207
+ templateUsers: v4_exports.array(v4_exports.string()),
47208
+ templateAdmins: v4_exports.array(v4_exports.string())
47209
+ });
47210
+ var iBagSaveSchema = v4_exports.object({
47211
+ id: idStringSchema,
47212
+ description: v4_exports.string(),
47213
+ name: v4_exports.string(),
47214
+ bagPermissions: v4_exports.array(bagPermissionRowSchema)
47215
+ });
47216
+ var iUserSaveSchema = v4_exports.object({
47217
+ id: idStringSchema,
47218
+ username: v4_exports.string(),
47219
+ email: v4_exports.string(),
47220
+ userRoles: v4_exports.array(v4_exports.string()),
47221
+ resetCode: v4_exports.string()
47222
+ });
47223
+ var iRoleSaveSchema = v4_exports.object({
47224
+ id: idStringSchema,
47225
+ description: v4_exports.string(),
47226
+ name: v4_exports.string()
47227
+ });
47228
+ var iWikiLoadSchema = iWikiSaveSchema.extend({
47229
+ lastCompiledAt: v4_exports.string(),
47230
+ effectiveWritableBags: v4_exports.array(writablePrefixRowSchema),
47231
+ effectiveReadonlyBags: v4_exports.array(v4_exports.string()),
47232
+ effectivePluginSet: v4_exports.array(v4_exports.string())
47233
+ });
47234
+ var iTemplateLoadSchema = iTemplateSaveSchema.extend({
47235
+ lastUpdatedAt: v4_exports.string()
47236
+ });
47237
+ var iBagLoadSchema = iBagSaveSchema;
47238
+ var iUserLoadSchema = iUserSaveSchema;
47239
+ var iRoleLoadSchema = iRoleSaveSchema;
47240
+ var dataSaveSchema = v4_exports.object({
47241
+ wikis: v4_exports.array(iWikiSaveSchema),
47242
+ templates: v4_exports.array(iTemplateSaveSchema),
47243
+ bags: v4_exports.array(iBagSaveSchema),
47244
+ users: v4_exports.array(iUserSaveSchema),
47245
+ roles: v4_exports.array(iRoleSaveSchema)
47246
+ });
47247
+ var dataStoreSchema = extraServerStuffSchema.extend({
47248
+ wikis: v4_exports.array(iWikiLoadSchema),
47249
+ templates: v4_exports.array(iTemplateLoadSchema),
47250
+ bags: v4_exports.array(iBagLoadSchema),
47251
+ users: v4_exports.array(iUserLoadSchema),
47252
+ roles: v4_exports.array(iRoleLoadSchema)
47253
+ });
47254
+
47255
+ // packages/mws/src/new-managers/TabDataTypes.ts
47256
+ var checkUniquePrefixes = /* @__PURE__ */ __name((data, context) => {
47257
+ const prefixes = /* @__PURE__ */ new Set();
47258
+ data.writablePrefixBags.forEach((row, index) => {
47259
+ if (!row.bagName.trim()) return;
47260
+ if (prefixes.has(row.prefix)) {
47261
+ context.addIssue({
47262
+ code: "custom",
47263
+ message: "Writable prefixes must be unique, including the default prefix.",
47264
+ path: ["writablePrefixBags", index, "prefix"]
47265
+ });
47266
+ }
47267
+ prefixes.add(row.prefix);
47268
+ });
47269
+ }, "checkUniquePrefixes");
47270
+ var zodWikiDataSaveSchema = iWikiSaveSchema.superRefine(checkUniquePrefixes).refine((data) => data.templateName.trim().length > 0, {
47271
+ message: "Template name is required.",
47272
+ path: ["templateName"]
47273
+ }).refine((data) => data.slug.trim().length > 0, {
47274
+ message: "Slug is required.",
47275
+ path: ["slug"]
47276
+ }).refine((data) => !data.slug.startsWith("/") && !data.slug.endsWith("/"), {
47277
+ message: "Slug must not start or end with a forward slash.",
47278
+ path: ["slug"]
47279
+ }).refine((data) => data.displayName.trim().length > 0, {
47280
+ message: "Display name is required.",
47281
+ path: ["displayName"]
47282
+ });
47283
+ var zodTemplateDataSaveSchema = iTemplateSaveSchema.superRefine(checkUniquePrefixes).refine((data) => data.name.trim().length > 0, {
47284
+ message: "Template name is required.",
47285
+ path: ["templateName"]
47286
+ }).superRefine((data, context) => {
47287
+ if (!data.customHtmlEnabled) return;
47288
+ const trimmedContent = data.htmlContent.trim();
47289
+ if (!trimmedContent.length) {
47290
+ context.addIssue({
47291
+ code: "custom",
47292
+ message: "HTML Content is required.",
47293
+ path: ["htmlContent"]
47294
+ });
47295
+ }
47296
+ if (!data.injectionFunction.trim().length) {
47297
+ context.addIssue({
47298
+ code: "custom",
47299
+ message: "Injection function is required.",
47300
+ path: ["injectionFunction"]
47301
+ });
47302
+ }
47303
+ const trimmedLocation = data.injectionLocation.trim();
47304
+ if (!trimmedLocation.length) {
47305
+ context.addIssue({
47306
+ code: "custom",
47307
+ message: "Injection marker is required.",
47308
+ path: ["injectionLocation"]
47309
+ });
47310
+ }
47311
+ if (trimmedLocation && trimmedContent && trimmedContent.indexOf(trimmedLocation) === -1) {
47312
+ context.addIssue({
47313
+ code: "custom",
47314
+ message: "HTML content does not contain injection marker.",
47315
+ path: ["htmlContent"]
47316
+ });
47317
+ context.addIssue({
47318
+ code: "custom",
47319
+ message: "HTML content does not contain injection marker.",
47320
+ path: ["injectionLocation"]
47321
+ });
47322
+ }
47323
+ });
47324
+ var zodBagDataSaveSchema = iBagSaveSchema.refine((data) => data.name.trim().length > 0, {
47325
+ message: "Bag name is required.",
47326
+ path: ["name"]
47327
+ });
47328
+ var zodRoleDataSaveSchema = iRoleSaveSchema.refine((data) => data.name.trim().length > 0, {
47329
+ message: "Role name is required.",
47330
+ path: ["name"]
47331
+ });
47332
+ var zodUserDataSaveSchema = iUserSaveSchema.refine((data) => data.username.trim().length > 0, {
47333
+ message: "Username is required.",
47334
+ path: ["username"]
47335
+ });
47336
+
47337
+ // packages/mws/src/utils/shared.ts
47338
+ var IdString = class _IdString extends String {
47339
+ static {
47340
+ __name(this, "IdString");
47341
+ }
47342
+ static cast(val) {
47343
+ return val.toString();
47344
+ }
47345
+ static prefix = "IdString____";
47346
+ name = "IdString";
47347
+ constructor(value) {
47348
+ super(value);
47349
+ }
47350
+ toJSON() {
47351
+ return _IdString.prefix + this.valueOf();
47352
+ }
47353
+ };
47354
+ SendError.errorString = (error48) => {
47355
+ return error48 instanceof SendError ? error48.reason === "INVALID_REQUEST_BODY" || error48.reason === "INVALID_REQUEST_QUERY" || error48.reason === "INVALID_REQUEST_PATH" ? error48.details.prettyErrors : error48.reason : error48 instanceof Error ? error48.message : String(error48);
47356
+ };
47357
+
47358
+ // packages/mws/src/utils/index.ts
47142
47359
  function readableBuffers(sources) {
47143
47360
  return Readable5.from((async function* () {
47144
47361
  for (const src of sources) {
@@ -50949,544 +51166,6 @@ __name(startupCache, "startupCache");
50949
51166
  // packages/mws/src/new-managers/RecipeResolver.ts
50950
51167
  init_esm_shims();
50951
51168
  import { createHash as createHash4 } from "crypto";
50952
-
50953
- // packages/admin-vanilla/src/definition/tabs.ts
50954
- init_esm_shims();
50955
- var halfWidth = "half";
50956
- var fullWidth = "full";
50957
- var stackLayout = "stack";
50958
- var IdString = class _IdString extends String {
50959
- static {
50960
- __name(this, "IdString");
50961
- }
50962
- static cast(val) {
50963
- return val.toString();
50964
- }
50965
- static prefix = "IdString____";
50966
- name = "IdString";
50967
- constructor(value) {
50968
- super(value);
50969
- }
50970
- toJSON() {
50971
- return _IdString.prefix + this.valueOf();
50972
- }
50973
- };
50974
- var stringLikeFieldShape = v4_exports.union([v4_exports.string(), v4_exports.instanceof(IdString)]);
50975
- var fieldTypeZodShapes = {
50976
- "template-type": v4_exports.enum(["simpleV1"]),
50977
- "string": v4_exports.string(),
50978
- "text": v4_exports.string(),
50979
- "enter-password": v4_exports.string(),
50980
- "confirm-password": v4_exports.string(),
50981
- "search": v4_exports.string(),
50982
- "structured-preview": v4_exports.string(),
50983
- "table": v4_exports.string().array(),
50984
- "permission-table": v4_exports.array(v4_exports.object({
50985
- role: v4_exports.string(),
50986
- level: v4_exports.string()
50987
- })),
50988
- "validation-report": v4_exports.string(),
50989
- "resolver-preview": v4_exports.string(),
50990
- "search-multiselect": v4_exports.string().array(),
50991
- "search-optional": v4_exports.string().nullable(),
50992
- "prefix-table": v4_exports.array(v4_exports.object({
50993
- prefix: v4_exports.string(),
50994
- bagName: v4_exports.string()
50995
- })),
50996
- "parameter-list": v4_exports.string().array(),
50997
- "relationship-table": v4_exports.string().array(),
50998
- "summary-list": v4_exports.string().array(),
50999
- "number": v4_exports.string(),
51000
- "activity-feed": v4_exports.string().array(),
51001
- "version": v4_exports.string(),
51002
- "select": v4_exports.string(),
51003
- "switch": v4_exports.boolean(),
51004
- "metadata-table": v4_exports.string().array()
51005
- };
51006
- var writableRoutingDescription = "Set the title prefix for each bag you want to write to. Tiddlers are only read from the bag matching the prefix.";
51007
- var tabs = {
51008
- wikis: {
51009
- id: "wikis",
51010
- label: "Wikis",
51011
- createLabel: "Create wiki",
51012
- eyebrow: "Your thoughts",
51013
- description: "Final wiki instances built from a template plus per-wiki customizations.",
51014
- columns: [
51015
- { key: "slug", label: "Slug", width: 2 },
51016
- { key: "displayName", label: "Display name", width: 2 },
51017
- { key: "templateName", label: "Template" },
51018
- { key: "defaultWritableBag", label: "Default bag" },
51019
- { key: "prefixRuleCount", label: "Prefix rules" },
51020
- { key: "readonlyBagCount", label: "Readonly bags" },
51021
- { key: "pluginCount", label: "Plugins" }
51022
- // { key: "edit", label: "" }
51023
- // { key: "lastCompiledAt", label: "Compiled" },
51024
- // { key: "statusFlags", label: "Status" },
51025
- // { key: "compileValidation", label: "Validation" }
51026
- ],
51027
- fields: [
51028
- { key: "slug", label: "Slug", type: "string", section: "authored", mode: "create edit" },
51029
- { key: "displayName", label: "Display name", type: "string", section: "authored", mode: "create edit" },
51030
- { key: "description", label: "Description", type: "text", section: "authored", mode: "create edit" },
51031
- { key: "templateName", label: "Template", type: "search", section: "authored", mode: "create" },
51032
- { key: "readonlyBags", label: "Bag name", type: "search-multiselect", section: "authored", mode: "create edit" },
51033
- { key: "plugins", label: "Plugin name", type: "search-multiselect", section: "authored", mode: "create edit" },
51034
- { key: "lastCompiledAt", label: "Compiled", type: "string", section: "runtime", mode: "server" },
51035
- {
51036
- key: "writablePrefixBags",
51037
- label: "Writable prefix bags",
51038
- type: "prefix-table",
51039
- section: "authored",
51040
- mode: "create edit",
51041
- architecture: "Edits the wiki-level prefix-to-bag routing table that drives write target selection. Longest prefix wins, and the empty string row is the fallback write target. A tiddler will only be read from the single write target it matches, after that the readonly bags are used, other write targets are ignored."
51042
- },
51043
- {
51044
- key: "effectiveWritableBags",
51045
- label: "Current writable bags",
51046
- type: "prefix-table",
51047
- section: "runtime",
51048
- mode: "server",
51049
- architecture: "Read-only projection of compiled recipe-bag rows in the same slice of the pie order the resolver uses for writes."
51050
- },
51051
- {
51052
- key: "effectiveReadonlyBags",
51053
- label: "Current readonly bags",
51054
- type: "table",
51055
- section: "runtime",
51056
- mode: "server",
51057
- architecture: "Read-only projection of compiled recipe-bag rows in the same top-to-bottom order the resolver uses for reads."
51058
- },
51059
- {
51060
- key: "effectivePluginSet",
51061
- label: "Current plugin set",
51062
- type: "table",
51063
- section: "runtime",
51064
- mode: "server",
51065
- architecture: "Read-only projection of the resolved plugin rows that will actually be used by the wiki page and preload path."
51066
- },
51067
- {
51068
- key: "recipeUsers",
51069
- label: "Role name",
51070
- type: "search-multiselect",
51071
- section: "authored",
51072
- mode: "create edit",
51073
- architecture: "Edits permission rows on the wiki definition itself. These govern access to the wiki surface separately from bag-level read and write rights."
51074
- },
51075
- {
51076
- key: "recipeAdmins",
51077
- label: "Role name",
51078
- type: "search-multiselect",
51079
- section: "authored",
51080
- mode: "create edit",
51081
- architecture: "Edits permission rows on the wiki definition itself. These govern access to the wiki surface separately from bag-level read and write rights."
51082
- },
51083
- {
51084
- key: "compileValidation",
51085
- label: "Compile validation",
51086
- type: "validation-report",
51087
- section: "runtime",
51088
- mode: "",
51089
- architecture: "Read-only validation and compilation result across template, parameters, bag references, plugin references, and routing invariants."
51090
- },
51091
- {
51092
- key: "titleResolutionPreview",
51093
- label: "Title routing test",
51094
- type: "resolver-preview",
51095
- section: "operations",
51096
- mode: "edit temp",
51097
- architecture: "Diagnostic resolver output for a title entered by the user: computed prefix match and authored write target selection only. Read answers and final write permission would require live server state."
51098
- }
51099
- ],
51100
- fieldGroups: {
51101
- authored: [
51102
- { title: "Basic Info", keys: ["slug", "displayName", "description", "templateName"], width: fullWidth, layout: stackLayout },
51103
- {
51104
- title: "Writable bags",
51105
- description: "Tiddlers are written to and read from the longest matching prefix; unmatched titles use the default bag.",
51106
- keys: ["writablePrefixBags"],
51107
- width: fullWidth
51108
- },
51109
- {
51110
- title: "Readonly bags",
51111
- description: "Checked when the tiddler is not in the writable bag matching the prefix.",
51112
- keys: ["readonlyBags"],
51113
- width: halfWidth
51114
- },
51115
- { title: "Plugins", description: "Add wiki-specific plugins on top of the template plugin set.", keys: ["plugins"], width: halfWidth },
51116
- { title: "Recipe Users", description: "Users able to open this wiki, assuming they have read permission on every bag as well.", keys: ["recipeUsers"], width: halfWidth },
51117
- { title: "Recipe Admins", description: "Users able to make changes on this page.", keys: ["recipeAdmins"], width: halfWidth },
51118
- { title: "Access", description: "Controls who can edit the wiki settings.", keys: ["recipePermissions"], width: fullWidth }
51119
- ],
51120
- runtime: [
51121
- // { title: "Computed Write Prefix", description: "", keys: ["effectiveWritableBags"], width: fullWidth },
51122
- // { title: "Computed Bag Order", description: "", keys: ["effectiveReadonlyBags"], width: halfWidth },
51123
- // { title: "Computed Plugin Set", description: "", keys: ["effectivePluginSet"], width: halfWidth },
51124
- // { title: "Compilation status", description: "Validation and compilation outcome for the current authored state.", keys: ["compileValidation"], width: fullWidth },
51125
- ],
51126
- operations: [
51127
- {
51128
- title: "Title routing test",
51129
- description: "Test a title against the wiki's current prefix rules to see which bag would receive writes.",
51130
- keys: ["titleResolutionPreview"],
51131
- width: fullWidth
51132
- }
51133
- ]
51134
- },
51135
- sidebarDisplay: [
51136
- "displayName",
51137
- "slug",
51138
- "templateName",
51139
- "effectiveWritableBags",
51140
- "effectiveReadonlyBags",
51141
- "effectivePluginSet"
51142
- ]
51143
- },
51144
- templates: {
51145
- id: "templates",
51146
- label: "Templates",
51147
- createLabel: "Create template",
51148
- eyebrow: "Wiki Blueprints",
51149
- description: "Reusable recipe definitions. Changes made to a template apply to every wiki using it.",
51150
- columns: [
51151
- { key: "name", label: "Name", width: 2 },
51152
- { key: "description", label: "Description", width: 3 },
51153
- { key: "readonlyBagsSummary", label: "Readonly bags" },
51154
- // { key: "writablePrefixSummary", label: "Writable prefixes" },
51155
- { key: "dependentWikiCount", label: "Dependent wikis" },
51156
- { key: "lastUpdatedAt", label: "Updated", width: 2 }
51157
- // { key: "validationStatus", label: "Validation" },
51158
- ],
51159
- fields: [
51160
- { key: "type", label: "Type", type: "template-type", section: "authored", mode: "create" },
51161
- { key: "name", label: "Name", type: "string", section: "authored", mode: "create edit" },
51162
- { key: "description", label: "Description", type: "text", section: "authored", mode: "create edit" },
51163
- { key: "lastUpdatedAt", label: "Updated", type: "string", section: "runtime", mode: "server" },
51164
- {
51165
- key: "writablePrefixBags",
51166
- label: "Writable prefix bags",
51167
- type: "prefix-table",
51168
- section: "authored",
51169
- mode: "create edit",
51170
- architecture: "Edits the template-level prefix-to-bag routing table that wikis inherit first. Longest prefix wins, and the empty string row is the fallback write target when no wiki-level override matches."
51171
- },
51172
- { key: "readonlyBags", label: "Bag name", type: "search-multiselect", section: "authored", mode: "create edit" },
51173
- { key: "plugins", label: "Plugin name", type: "search-multiselect", section: "authored", mode: "create edit" },
51174
- {
51175
- key: "templateUsers",
51176
- label: "Role name",
51177
- type: "search-multiselect",
51178
- section: "authored",
51179
- mode: "create edit",
51180
- architecture: "Edits permission rows on the wiki definition itself. These govern access to the wiki surface separately from bag-level read and write rights."
51181
- },
51182
- {
51183
- key: "templateAdmins",
51184
- label: "Role name",
51185
- type: "search-multiselect",
51186
- section: "authored",
51187
- mode: "create edit",
51188
- architecture: "Edits permission rows on the wiki definition itself. These govern access to the wiki surface separately from bag-level read and write rights."
51189
- },
51190
- {
51191
- key: "requiredPluginsEnabled",
51192
- label: "Include Required Plugins",
51193
- type: "switch",
51194
- section: "authored",
51195
- mode: "create edit",
51196
- description: "Core plugins enable wiki sync functionality. Disabling removes the plugins, but does not disable the endpoints."
51197
- },
51198
- {
51199
- key: "externalStore",
51200
- label: "External JS Store",
51201
- type: "switch",
51202
- section: "authored",
51203
- mode: "create edit",
51204
- description: "Loads the entire store, including plugins, via a script tag."
51205
- },
51206
- {
51207
- key: "externalPlugins",
51208
- label: "Enable Plugin Caching",
51209
- type: "switch",
51210
- section: "authored",
51211
- mode: "create edit",
51212
- description: "Serves plugins separately, allowing the browser to cache plugins separate from the store."
51213
- },
51214
- {
51215
- key: "twVersion",
51216
- label: "TiddlyWiki Version",
51217
- type: "search-optional",
51218
- section: "authored",
51219
- mode: "create edit",
51220
- description: "TW5 version pinning. Leave blank to use site default."
51221
- },
51222
- {
51223
- key: "customHtmlEnabled",
51224
- label: "Custom HTML shell",
51225
- type: "switch",
51226
- section: "authored",
51227
- mode: "create edit",
51228
- description: "Enable custom HTML shell settings when this template should serve authored HTML instead of the default page shell."
51229
- },
51230
- {
51231
- key: "htmlContent",
51232
- label: "HTML content",
51233
- type: "text",
51234
- section: "authored",
51235
- mode: "create edit",
51236
- description: "Store the raw HTML that will be served for this template. All HTTP endpoints still work, but any boot, library, or raw markup tiddlers must be included here manually."
51237
- },
51238
- {
51239
- key: "injectionFunction",
51240
- label: "Injection function",
51241
- type: "string",
51242
- section: "authored",
51243
- mode: "create edit",
51244
- description: "Name of the JavaScript function to call with each tiddler, for example $tw.preloadTiddler."
51245
- },
51246
- {
51247
- key: "injectionLocation",
51248
- label: "Injection marker",
51249
- type: "string",
51250
- section: "authored",
51251
- mode: "create edit",
51252
- description: "Inject the tiddlers before this string in the HTML file, for example <!-- INJECT STORE TIDDLERS HERE -->. It must not be inside a script tag."
51253
- },
51254
- {
51255
- key: "defaultWritableBag",
51256
- label: "Default writable bag",
51257
- type: "string",
51258
- section: "runtime",
51259
- mode: "",
51260
- architecture: "Read-only convenience projection of the writablePrefixBags row whose prefix is the empty string."
51261
- },
51262
- {
51263
- key: "dependentWikis",
51264
- label: "Dependent wikis",
51265
- type: "relationship-table",
51266
- section: "runtime",
51267
- mode: "",
51268
- architecture: "Read-only relationship view listing all wikis that reference this template and will be revalidated or recompiled if it changes."
51269
- },
51270
- {
51271
- key: "validationReport",
51272
- label: "Validation result",
51273
- type: "validation-report",
51274
- section: "runtime",
51275
- mode: "",
51276
- architecture: "Read-only summary of whether the definition can compile cleanly against current bag and plugin references."
51277
- }
51278
- ],
51279
- fieldGroups: {
51280
- authored: [
51281
- { title: "Template basics", keys: ["name", "description", "twVersion"], width: fullWidth, layout: stackLayout },
51282
- { title: "Writable routing", description: writableRoutingDescription, keys: ["writablePrefixBags"], width: fullWidth },
51283
- { title: "Bags", keys: ["readonlyBags"], width: halfWidth },
51284
- { title: "Plugins", keys: ["plugins", "requiredPluginsEnabled", "externalPlugins"], width: halfWidth, layout: stackLayout },
51285
- { title: "Template Users", description: "Users who can set this template on a recipe. This only applies to the user creating the recipe.", keys: ["templateUsers"], width: halfWidth },
51286
- { title: "Template Admins", description: "Users able to make changes on this page. This affects all recipes that use the template, regardless of any other permissions.", keys: ["templateAdmins"], width: halfWidth },
51287
- { title: "Custom HTML shell", keys: ["htmlContent", "injectionFunction", "injectionLocation"], headerFieldKey: "customHtmlEnabled", disabledWhenHeaderOff: true, width: fullWidth, layout: stackLayout }
51288
- ],
51289
- runtime: [
51290
- // { keys: ["defaultWritableBag"], width: halfWidth },
51291
- // { keys: ["dependentWikis"], width: halfWidth },
51292
- // { keys: ["validationReport"], width: halfWidth },
51293
- ]
51294
- },
51295
- sidebarDisplay: [
51296
- "name",
51297
- "description",
51298
- "dependentWikiCount"
51299
- ]
51300
- },
51301
- bags: {
51302
- id: "bags",
51303
- label: "Bags",
51304
- createLabel: "Create bag",
51305
- eyebrow: "Tiddler Storage",
51306
- description: "Concrete tiddler storage with role-based access control.",
51307
- columns: [
51308
- { key: "name", label: "Name", width: 2 },
51309
- { key: "description", label: "Description", width: 2 },
51310
- { key: "usedByCount", label: "Used by" },
51311
- { key: "readonlyUsageCount", label: "Readonly" },
51312
- { key: "writableUsageCount", label: "Writable" },
51313
- { key: "defaultUsageCount", label: "Default" },
51314
- { key: "permissionSummary", label: "Permissions" }
51315
- // { key: "tiddlerCount", label: "Tiddlers" },
51316
- // { key: "lastActivityAt", label: "Last activity" },
51317
- ],
51318
- fields: [
51319
- { key: "name", label: "Name", type: "string", section: "authored", mode: "create edit" },
51320
- { key: "description", label: "Description", type: "text", section: "authored", mode: "create edit" },
51321
- {
51322
- key: "bagPermissions",
51323
- label: "Permissions",
51324
- type: "permission-table",
51325
- section: "authored",
51326
- mode: "create edit",
51327
- architecture: "Edits bag permission rows. These rows are consulted directly by the resolver when deciding who can read from or write to the storage container."
51328
- },
51329
- {
51330
- key: "referencedByTemplates",
51331
- label: "Referenced by templates",
51332
- type: "relationship-table",
51333
- section: "runtime",
51334
- mode: "",
51335
- architecture: "Read-only relationship view derived from authored template definition JSON that mentions this bag in readonly or writable routing positions."
51336
- },
51337
- {
51338
- key: "referencedByWikis",
51339
- label: "Referenced by wikis",
51340
- type: "relationship-table",
51341
- section: "runtime",
51342
- mode: "",
51343
- architecture: "Read-only relationship view derived from compiled recipe-bag rows, reflecting the effective runtime routing topology."
51344
- },
51345
- {
51346
- key: "routingRoles",
51347
- label: "Routing roles",
51348
- type: "summary-list",
51349
- section: "runtime",
51350
- mode: "",
51351
- architecture: "Derived routing summary classifying how this bag participates across compiled wikis, such as readonly layer, writable prefix target, or default fallback."
51352
- }
51353
- // { key: "tiddlerCount", label: "Tiddler count", type: "number", section: "runtime", mode: "", },
51354
- // {
51355
- // key: "recentActivity",
51356
- // label: "Recent activity",
51357
- // type: "activity-feed",
51358
- // section: "runtime",
51359
- // mode: "",
51360
- // architecture: "Read-only operational summary built from recent tiddler event rows for this bag.",
51361
- // },
51362
- ],
51363
- fieldGroups: {
51364
- authored: [
51365
- { title: "Bag basics", keys: ["name", "description"], width: fullWidth, layout: stackLayout },
51366
- { keys: ["bagPermissions"], width: fullWidth }
51367
- ],
51368
- runtime: [
51369
- { keys: ["referencedByTemplates"], width: halfWidth },
51370
- { keys: ["referencedByWikis"], width: halfWidth }
51371
- // { keys: ["routingRoles"], width: halfWidth },
51372
- // { keys: ["tiddlerCount"], width: halfWidth },
51373
- // { keys: ["recentActivity"], width: fullWidth },
51374
- ]
51375
- },
51376
- sidebarDisplay: [
51377
- "name",
51378
- "description",
51379
- "referencedByTemplates",
51380
- "referencedByWikis"
51381
- ]
51382
- },
51383
- // plugins: {
51384
- // id: "plugins",
51385
- // label: "Plugins",
51386
- // createLabel: "Create plugin",
51387
- // eyebrow: "Managed Assets",
51388
- // description: "Separately versioned plugins compiled into each wiki’s resolved plugin set. Still work in progress.",
51389
- // columns: [
51390
- // { key: "name", label: "Name" },
51391
- // { key: "description", label: "Description" },
51392
- // { key: "pluginPath", label: "Plugin Path" },
51393
- // { key: "usageCount", label: "Usage" },
51394
- // ],
51395
- // fields: [
51396
- // { key: "name", label: "Name", type: "string", section: "authored", mode: "server" },
51397
- // { key: "description", label: "Description", type: "text", section: "authored", mode: "server" },
51398
- // { key: "pluginPath", label: "Path", type: "string", section: "authored", mode: "server" },
51399
- // { key: "usageCount", label: "Wiki Count", type: "number", section: "runtime", mode: "" },
51400
- // { key: "usedByWikis", label: "Active Wikis", type: "table", section: "runtime", mode: "" },
51401
- // ],
51402
- // fieldGroups: {
51403
- // runtime: [
51404
- // { title: "Used in", description: "List of wikis this plugin is used in. Only includes templates that are in use.", keys: ["usedByWikis"], width: fullWidth, layout: "grid" },
51405
- // ],
51406
- // },
51407
- // sidebarDisplay: [
51408
- // "name",
51409
- // "description",
51410
- // "usageCount",
51411
- // "pluginPath",
51412
- // ],
51413
- // },
51414
- roles: {
51415
- id: "roles",
51416
- label: "Roles",
51417
- createLabel: "Create role",
51418
- eyebrow: "Access profiles",
51419
- description: "Named access profiles that can be assigned to user accounts.",
51420
- columns: [
51421
- { key: "name", label: "Role name", width: 2 },
51422
- { key: "description", label: "Role description", width: 7 }
51423
- ],
51424
- fields: [
51425
- { key: "name", label: "Role name", type: "string", section: "authored", mode: "create edit" },
51426
- { key: "description", label: "Role description", type: "text", section: "authored", mode: "create edit" }
51427
- ],
51428
- fieldGroups: {
51429
- authored: [
51430
- { title: "Role basics", keys: ["name", "description"], width: fullWidth, layout: stackLayout }
51431
- ]
51432
- },
51433
- sidebarDisplay: ["name", "description"]
51434
- },
51435
- // #region users
51436
- users: {
51437
- id: "users",
51438
- label: "Users",
51439
- createLabel: "Create user",
51440
- eyebrow: "Account logins",
51441
- description: "User accounts with assigned roles.",
51442
- columns: [
51443
- { key: "username", label: "Username", width: 2 },
51444
- { key: "email", label: "Email", width: 7 }
51445
- ],
51446
- fields: [
51447
- { key: "username", label: "Username", type: "string", section: "authored", mode: "create edit" },
51448
- { key: "email", label: "Email", type: "string", section: "authored", mode: "create edit" },
51449
- { key: "userRoles", label: "Roles", type: "search-multiselect", section: "authored", mode: "create edit" },
51450
- { key: "resetCode", label: "Reset Code", type: "string", section: "authored", mode: "create edit" }
51451
- // { key: "password", label: "Password", type: "string", section: "authored", mode: "create edit" },
51452
- // { key: "confirmPassword", label: "Confirm password", type: "string", section: "authored", mode: "create edit temp" },
51453
- ],
51454
- fieldGroups: {
51455
- authored: [
51456
- { title: "User identity", keys: ["username", "email"], width: fullWidth, layout: stackLayout },
51457
- { title: "Roles", description: "Assign one or more role ids to this user account.", keys: ["userRoles"], width: halfWidth },
51458
- { title: "Reset Code", description: "Allow the user to reset their password with this code.", keys: ["resetCode"], width: halfWidth },
51459
- { title: "Credentials", keys: ["password", "confirmPassword"], width: halfWidth, layout: stackLayout }
51460
- ]
51461
- },
51462
- sidebarDisplay: [
51463
- "username",
51464
- "email",
51465
- "userRoles"
51466
- ]
51467
- }
51468
- };
51469
- function shouldIncludeFieldInTabZodObject(mode, filter) {
51470
- if (filter === "DataStore") {
51471
- return mode !== "" && mode !== "create edit temp" && mode !== "create temp" && mode !== "edit temp";
51472
- }
51473
- if (filter === "DataSave") {
51474
- return mode !== "" && mode !== "create edit temp" && mode !== "create temp" && mode !== "edit temp" && mode !== "server";
51475
- }
51476
- return true;
51477
- }
51478
- __name(shouldIncludeFieldInTabZodObject, "shouldIncludeFieldInTabZodObject");
51479
- function buildTabZodObject(tabId, filter) {
51480
- const tab = tabs[tabId];
51481
- const fieldEntries = tab.fields.filter((field) => shouldIncludeFieldInTabZodObject(field.mode, filter)).map((field) => [field.key, fieldTypeZodShapes[field.type]]);
51482
- return v4_exports.object({
51483
- id: stringLikeFieldShape,
51484
- ...Object.fromEntries(fieldEntries)
51485
- });
51486
- }
51487
- __name(buildTabZodObject, "buildTabZodObject");
51488
-
51489
- // packages/mws/src/new-managers/RecipeResolver.ts
51490
51169
  var WRITE_LEVELS = ["B_write", "C_admin"];
51491
51170
  var RecipeResolver = class {
51492
51171
  // #region constructor
@@ -52608,7 +52287,8 @@ var RecipeRoutes = class _RecipeRoutes {
52608
52287
  state.assertWikiReferer(recipe_slug);
52609
52288
  const recipe = await RecipeResolver.assertRecipe({
52610
52289
  state,
52611
- recipe_slug
52290
+ recipe_slug,
52291
+ sendNotFound: true
52612
52292
  }).then((e) => {
52613
52293
  state.asserted = true;
52614
52294
  return e;
@@ -52647,7 +52327,8 @@ var RecipeRoutes = class _RecipeRoutes {
52647
52327
  state.assertWikiReferer(recipe_slug);
52648
52328
  const recipe = await RecipeResolver.assertRecipe({
52649
52329
  state,
52650
- recipe_slug
52330
+ recipe_slug,
52331
+ sendNotFound: true
52651
52332
  }).then((e) => {
52652
52333
  state.asserted = true;
52653
52334
  return e;
@@ -52671,7 +52352,7 @@ var RecipeRoutes = class _RecipeRoutes {
52671
52352
  inner: /* @__PURE__ */ __name(async (state) => {
52672
52353
  const { recipe_slug } = state.pathParams;
52673
52354
  state.assertWikiReferer(recipe_slug);
52674
- throw await serveWikiIndex(state, recipe_slug, "store.js");
52355
+ throw await serveWikiIndex(state, recipe_slug, "store.js", true);
52675
52356
  }, "inner")
52676
52357
  });
52677
52358
  // #region RecipeStore
@@ -52687,7 +52368,7 @@ var RecipeRoutes = class _RecipeRoutes {
52687
52368
  inner: /* @__PURE__ */ __name(async (state) => {
52688
52369
  const { recipe_slug } = state.pathParams;
52689
52370
  state.assertWikiReferer(recipe_slug);
52690
- throw await serveWikiIndex(state, recipe_slug, "store.json");
52371
+ throw await serveWikiIndex(state, recipe_slug, "store.json", true);
52691
52372
  }, "inner")
52692
52373
  });
52693
52374
  // #region RecipeUpdates
@@ -52706,7 +52387,8 @@ var RecipeRoutes = class _RecipeRoutes {
52706
52387
  state.assertWikiReferer(recipe_slug);
52707
52388
  const recipe = await RecipeResolver.assertRecipe({
52708
52389
  state,
52709
- recipe_slug
52390
+ recipe_slug,
52391
+ sendNotFound: true
52710
52392
  }).then((e) => {
52711
52393
  state.asserted = true;
52712
52394
  return e;
@@ -52763,7 +52445,8 @@ var RecipeRoutes = class _RecipeRoutes {
52763
52445
  state.assertWikiReferer(recipe_slug);
52764
52446
  const recipe = await RecipeResolver.assertRecipe({
52765
52447
  state,
52766
- recipe_slug
52448
+ recipe_slug,
52449
+ sendNotFound: true
52767
52450
  }).then((e) => {
52768
52451
  state.asserted = true;
52769
52452
  return e;
@@ -53649,6 +53332,11 @@ var AdminRoutes = class _AdminRoutes {
53649
53332
  registerZodRoutes(root, route, keys);
53650
53333
  }
53651
53334
  static AdminPrefix;
53335
+ okIsLoggedIn(state) {
53336
+ state.asserted = state.user.isLoggedIn;
53337
+ if (!state.asserted)
53338
+ throw new SendError("UNAUTHORIZED", 401, null);
53339
+ }
53652
53340
  // #region AdminSave
53653
53341
  AdminSave = zodRoute({
53654
53342
  method: ["PUT"],
@@ -53662,13 +53350,30 @@ var AdminRoutes = class _AdminRoutes {
53662
53350
  zodRequestBody: /* @__PURE__ */ __name((z3) => z3.any(), "zodRequestBody"),
53663
53351
  inner: /* @__PURE__ */ __name(async (state) => {
53664
53352
  state.assertReferer(["/"]);
53665
- state.asserted = state.user.isLoggedIn;
53353
+ this.okIsLoggedIn(state);
53666
53354
  state.data = JSON.parse(JSON.stringify(state.data), (key, val) => {
53667
53355
  if (typeof val === "string" && val.startsWith(IdString.prefix))
53668
53356
  return new IdString(val.slice(IdString.prefix.length));
53669
53357
  return val;
53670
53358
  });
53671
- checkData(state, () => buildTabZodObject(state.pathParams.tab, "DataSave"), new Error());
53359
+ checkData(state, () => {
53360
+ switch (state.pathParams.tab) {
53361
+ case "wikis":
53362
+ return zodWikiDataSaveSchema;
53363
+ case "templates":
53364
+ return zodTemplateDataSaveSchema;
53365
+ case "bags":
53366
+ return zodBagDataSaveSchema;
53367
+ case "roles":
53368
+ return zodRoleDataSaveSchema;
53369
+ case "users":
53370
+ return zodUserDataSaveSchema;
53371
+ default: {
53372
+ const _exhaustive = state.pathParams.tab;
53373
+ throw new Error(`Unsupported admin tab: ${_exhaustive}`);
53374
+ }
53375
+ }
53376
+ }, new Error());
53672
53377
  const res = await state.$transaction(async (prisma) => {
53673
53378
  const { pathParams: { op, tab }, data } = state;
53674
53379
  switch (op) {
@@ -53695,7 +53400,24 @@ var AdminRoutes = class _AdminRoutes {
53695
53400
  }
53696
53401
  }
53697
53402
  });
53698
- const { success: success2, data: res2, error: error48 } = buildTabZodObject(state.pathParams.tab, "DataStore").safeParse(res);
53403
+ const { success: success2, data: res2, error: error48 } = (() => {
53404
+ switch (state.pathParams.tab) {
53405
+ case "wikis":
53406
+ return iWikiLoadSchema;
53407
+ case "templates":
53408
+ return iTemplateLoadSchema;
53409
+ case "bags":
53410
+ return iBagLoadSchema;
53411
+ case "roles":
53412
+ return iRoleLoadSchema;
53413
+ case "users":
53414
+ return iUserLoadSchema;
53415
+ default: {
53416
+ const _exhaustive = state.pathParams.tab;
53417
+ throw new Error(`Unsupported admin tab: ${_exhaustive}`);
53418
+ }
53419
+ }
53420
+ })().safeParse(res);
53699
53421
  if (!success2) console.log("Response validation: ", error48);
53700
53422
  return res2;
53701
53423
  }, "inner")
@@ -53709,7 +53431,7 @@ var AdminRoutes = class _AdminRoutes {
53709
53431
  zodPathParams: /* @__PURE__ */ __name((z3) => ({}), "zodPathParams"),
53710
53432
  inner: /* @__PURE__ */ __name(async (state) => {
53711
53433
  state.assertReferer(["/"]);
53712
- state.asserted = state.user.isLoggedIn;
53434
+ this.okIsLoggedIn(state);
53713
53435
  const res = await state.$transaction(async (prisma) => {
53714
53436
  const roles = await new RoleImportWriter(prisma, false).getIdMapper();
53715
53437
  return {
@@ -53724,17 +53446,7 @@ var AdminRoutes = class _AdminRoutes {
53724
53446
  }))
53725
53447
  };
53726
53448
  });
53727
- const { success: success2, data, error: error48 } = v4_exports.object({
53728
- wikis: buildTabZodObject("wikis", "DataStore").array(),
53729
- templates: buildTabZodObject("templates", "DataStore").array(),
53730
- bags: buildTabZodObject("bags", "DataStore").array(),
53731
- roles: buildTabZodObject("roles", "DataStore").array(),
53732
- users: buildTabZodObject("users", "DataStore").array(),
53733
- availablePlugins: v4_exports.array(v4_exports.object({
53734
- name: v4_exports.string(),
53735
- description: v4_exports.string()
53736
- }))
53737
- }).safeParse(res);
53449
+ const { success: success2, data, error: error48 } = dataStoreSchema.safeParse(res);
53738
53450
  if (!success2) throw error48;
53739
53451
  return data;
53740
53452
  }, "inner")
@@ -53746,7 +53458,7 @@ init_esm_shims();
53746
53458
 
53747
53459
  // packages/mws/src/new-managers/index.ts
53748
53460
  serverEvents.on("mws.routes", (root, config3) => {
53749
- config3.rootRoutes;
53461
+ SessionManager.defineRoutes(root);
53750
53462
  const parent = root.defineRoute({
53751
53463
  method: [],
53752
53464
  denyFinal: true,
@@ -55153,6 +54865,7 @@ SendError.oninstance.push((e) => {
55153
54865
  case "TIDDLER_WIRE_FORMAT_UNKNOWN":
55154
54866
  case "WRITE_NOT_PERMITTED":
55155
54867
  case "ACCESS_DENIED":
54868
+ case "UNAUTHORIZED":
55156
54869
  case "NOT_FOUND": {
55157
54870
  e.skiplog = true;
55158
54871
  break;