@tiddlywiki/mws 0.0.12 → 0.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/.env-cmdrc +5 -0
  2. package/README.md +3 -1
  3. package/dist/server.d.ts +923 -0
  4. package/dist/server.js +1763 -1415
  5. package/dist/server.js.map +1 -1
  6. package/editions/mws-docs/tiddlers/$__StoryList.tid +3 -3
  7. package/editions/mws-docs/tiddlers/MWS and SQLite.md +11 -0
  8. package/editions/mws-docs/tiddlers/Request Server.md +20 -0
  9. package/editions/mws-docs/tiddlers/Request Server.md.meta +5 -0
  10. package/package.json +17 -10
  11. package/prisma/schema.prisma +1 -0
  12. package/react-user-mgmt/package-lock.json +76 -321
  13. package/react-user-mgmt/package.json +2 -5
  14. package/react-user-mgmt/public/chunk-YALWN5OT.js +2 -0
  15. package/react-user-mgmt/public/chunk-YALWN5OT.js.map +7 -0
  16. package/react-user-mgmt/public/esm-QKDFEP3B.js +3 -0
  17. package/react-user-mgmt/public/esm-QKDFEP3B.js.map +7 -0
  18. package/react-user-mgmt/public/index.html +1 -26
  19. package/react-user-mgmt/public/main.js +68 -109
  20. package/react-user-mgmt/public/main.js.map +4 -4
  21. package/react-user-mgmt/public/stats.css +597 -0
  22. package/react-user-mgmt/public/stats.html +59 -0
  23. package/react-user-mgmt/public/stats.js +2013 -0
  24. package/react-user-mgmt/public/stats.json +1 -0
  25. package/react-user-mgmt/public/stats.svg +4 -0
  26. package/react-user-mgmt/tsconfig.json +3 -0
  27. package/dist/server.cjs +0 -16677
  28. package/dist/server.cjs.map +0 -1
  29. package/src/StateObject.ts +0 -316
  30. package/src/commander.ts +0 -417
  31. package/src/commands/divider.ts +0 -20
  32. package/src/commands/index.ts +0 -24
  33. package/src/commands/mws-init-store.ts +0 -77
  34. package/src/commands/mws-listen.ts +0 -136
  35. package/src/commands/mws-load-archive.ts +0 -281
  36. package/src/commands/mws-load-plugin-bags.ts +0 -151
  37. package/src/commands/mws-load-tiddlers.ts +0 -37
  38. package/src/commands/mws-load-wiki-folder.ts +0 -124
  39. package/src/commands/mws-render-tiddlywiki5.ts +0 -55
  40. package/src/commands/mws-save-archive.ts +0 -111
  41. package/src/commands/mws-save-tiddler-text.ts +0 -33
  42. package/src/commands/tests-complete.ts +0 -21
  43. package/src/global.ts +0 -247
  44. package/src/routes/TiddlerStore.ts +0 -722
  45. package/src/routes/bag-file-server.ts +0 -340
  46. package/src/routes/cache.ts +0 -25
  47. package/src/routes/index.ts +0 -138
  48. package/src/routes/managers/index.ts +0 -17
  49. package/src/routes/managers/manager-recipes.ts +0 -438
  50. package/src/routes/managers/manager-users.ts +0 -201
  51. package/src/routes/managers/router-tiddlers.ts +0 -313
  52. package/src/routes/router.ts +0 -429
  53. package/src/routes/services/PasswordService.ts +0 -178
  54. package/src/routes/services/attachments.ts +0 -259
  55. package/src/routes/services/sessions.ts +0 -166
  56. package/src/routes/tw-test.ts +0 -65
  57. package/src/server.ts +0 -151
  58. package/src/setupDevServer.ts +0 -71
  59. package/src/streamer.ts +0 -430
  60. package/src/tiddlywiki.ts +0 -94
  61. package/src/utils/data-checks.ts +0 -172
  62. package/src/utils/index.ts +0 -4
  63. package/src/utils/rootRoute.ts +0 -237
  64. package/src/utils/utils.ts +0 -403
  65. package/src/utils/zodAssert.ts +0 -269
  66. /package/prisma/{migrations/notes.md → notes.md} +0 -0
@@ -1,313 +0,0 @@
1
- import { StateObject } from "../../StateObject";
2
- import { STREAM_ENDED } from "../../streamer";
3
- import { tryParseJSON, ZodAssert as zodAssert } from "../../utils";
4
- import { registerZodRoutes, zodRoute, RouterKeyMap, RouterRouteMap } from "../router";
5
- import { TiddlerServer } from "../bag-file-server";
6
-
7
-
8
- export const TiddlerKeyMap: RouterKeyMap<TiddlerRouter, true> = {
9
- handleCreateRecipeTiddler: true,
10
- handleDeleteRecipeTiddler: true,
11
- handleGetBagTiddler: true,
12
- handleGetBagTiddlerBlob: true,
13
- handleGetRecipeStatus: true,
14
- handleGetRecipeTiddler: true,
15
- handleListRecipeTiddlers: true,
16
- handleSaveRecipeTiddler: true,
17
- handleGetWikiIndex: true,
18
- }
19
-
20
- export type TiddlerManagerMap = RouterRouteMap<TiddlerRouter>;
21
-
22
- export class TiddlerRouter {
23
- static defineRoutes = (root: rootRoute) => {
24
- registerZodRoutes(root, new TiddlerRouter(), Object.keys(TiddlerKeyMap));
25
- }
26
-
27
- handleGetRecipeStatus = zodRoute(
28
- ["GET", "HEAD"],
29
- "/recipes/:recipe_name/status",
30
- z => ({
31
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
32
- }),
33
- "ignore",
34
- z => z.undefined(),
35
- async (state) => {
36
-
37
- const { recipe_name } = state.pathParams;
38
-
39
- const { recipe, canRead, canWrite } = await state.getRecipeACL(recipe_name, true);
40
-
41
- if (!recipe) throw state.sendEmpty(404, { "x-reason": "recipe not found" });
42
- if (!canRead) throw state.sendEmpty(403, { "x-reason": "read access denied" });
43
-
44
- const { isAdmin, user_id, username } = state.user;
45
-
46
- return {
47
- isAdmin,
48
- user_id,
49
- username,
50
- isLoggedIn: state.user.isLoggedIn,
51
- isReadOnly: !canWrite,
52
- allowAnonReads: state.config.allowAnonReads,
53
- allowAnonWrites: state.config.allowAnonWrites,
54
- };
55
- }
56
- );
57
-
58
- handleGetRecipeTiddler = zodRoute(
59
- ["GET", "HEAD"],
60
- "/recipes/:recipe_name/tiddlers/:title",
61
- z => ({
62
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
63
- title: z.prismaField("Tiddlers", "title", "string"),
64
- }),
65
- "ignore",
66
- z => z.undefined(),
67
- async (state) => {
68
- const { recipe_name, title } = state.pathParams;
69
-
70
- await state.assertRecipeACL(recipe_name, false);
71
-
72
- throw await state.$transaction(async prisma => {
73
- const server = new TiddlerServer(state, prisma);
74
- const bag = await server.getRecipeBagWithTiddler({ recipe_name, title });
75
- return server.sendBagTiddler({ state, bag_id: bag?.bag_id, title });
76
- });
77
-
78
- }
79
- )
80
-
81
- handleGetBagTiddler = zodRoute(
82
- ["GET", "HEAD"],
83
- "/bags/:bag_name/tiddlers/:title",
84
- z => ({
85
- bag_name: z.prismaField("Bags", "bag_name", "string"),
86
- title: z.prismaField("Tiddlers", "title", "string"),
87
- }),
88
- "ignore",
89
- z => z.undefined(),
90
- async (state) => {
91
-
92
- await state.assertBagACL(state.pathParams.bag_name, false);
93
-
94
- throw await state.$transaction(async prisma => {
95
- const server = new TiddlerServer(state, prisma);
96
- // return await server.getBagTiddler(state.pathParams);
97
- return server.sendBagTiddler({ state, ...state.pathParams });
98
- });
99
-
100
- // return this.sendTiddlerInfo(state, tiddlerInfo);
101
-
102
- });
103
-
104
- handleGetBagTiddlerBlob = zodRoute(
105
- ["GET", "HEAD"],
106
- "/bags/:bag_name/tiddlers/:title/blob",
107
- z => ({
108
- bag_name: z.prismaField("Bags", "bag_name", "string"),
109
- title: z.prismaField("Tiddlers", "title", "string"),
110
- }),
111
- "ignore",
112
- z => z.undefined(),
113
- async (state) => {
114
- const { bag_name, title } = state.pathParams;
115
-
116
- await state.assertBagACL(bag_name, false);
117
-
118
- const result = await state.$transaction(async prisma => {
119
- const server = new TiddlerServer(state, prisma);
120
- return await server.getBagTiddlerStream(title, bag_name);
121
- });
122
-
123
- if (!result) throw state.sendEmpty(404, { "x-reason": "no result" });
124
-
125
- throw state.sendStream(200, {
126
- Etag: state.makeTiddlerEtag(result),
127
- "Content-Type": result.type
128
- }, result.stream);
129
- });
130
-
131
- handleListRecipeTiddlers = zodRoute(
132
- ["GET", "HEAD"],
133
- "/recipes/:recipe_name/tiddlers.json",
134
- z => ({
135
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
136
- }),
137
- "ignore",
138
- z => z.undefined(),
139
- async (state) => {
140
- zodAssert.queryParams(state, z => ({
141
- include_deleted: z.string().array().optional(),
142
- last_known_tiddler_id: z.string().array().optional(),
143
- }));
144
-
145
- const { recipe_name } = state.pathParams;
146
- const include_deleted = state.queryParams.include_deleted?.[0] === "true";
147
- const last_known_tiddler_id = +(state.queryParams.last_known_tiddler_id?.[0] ?? 0) || undefined;
148
-
149
- await state.assertRecipeACL(recipe_name, false);
150
-
151
- const result = await state.$transaction(async prisma => {
152
- const server = new TiddlerServer(state, prisma);
153
- const options = { include_deleted, last_known_tiddler_id };
154
- let result = await server.getRecipeTiddlers(recipe_name);
155
- return result
156
- .filter(tiddler => options.include_deleted || !tiddler.is_deleted)
157
- .filter(tiddler => !options.last_known_tiddler_id || tiddler.tiddler_id > options.last_known_tiddler_id);
158
- });
159
- return result;
160
- }
161
- )
162
-
163
- parseFields(input: string, ctype: string | undefined) {
164
-
165
- if (ctype?.startsWith("application/json"))
166
- return tryParseJSON<any>(input);
167
-
168
- if (ctype?.startsWith("application/x-mws-tiddler")) {
169
- //https://jsperf.app/mukuro
170
- // for a big text field (100k random characters)
171
- // splitting the string is 1000x faster!
172
- // but I don't really trust getFieldStringBlock
173
- // because it doesn't check for fields with colon names
174
-
175
- const headerEnd = input.indexOf("\n\n");
176
- if (headerEnd === -1) return tryParseJSON<any>(input);
177
- const header = input.slice(0, headerEnd);
178
- const body = input.slice(headerEnd + 2);
179
-
180
- const fields = tryParseJSON<any>(header);
181
- if (!fields) return undefined;
182
- fields.text = body;
183
- return fields;
184
- }
185
- }
186
-
187
- handleSaveRecipeTiddler = zodRoute(
188
- ["PUT"],
189
- "/recipes/:recipe_name/tiddlers/:title",
190
- z => ({
191
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
192
- title: z.prismaField("Tiddlers", "title", "string"),
193
- }),
194
- "string",
195
- z => z.string(),
196
- // z => z.object({
197
- // title: z.prismaField("Tiddlers", "title", "string", false),
198
- // }).and(z.record(z.string())),
199
- async (state) => {
200
-
201
- const { recipe_name } = state.pathParams;
202
-
203
- await state.assertRecipeACL(recipe_name, true);
204
-
205
- const fields = this.parseFields(state.data, state.headers["content-type"]);
206
-
207
- if (fields === undefined) throw state.sendEmpty(400, { "x-reason": "PUT tiddler expects a valid json or x-mws-tiddler body" })
208
-
209
- const { bag_name, tiddler_id } = await state.$transaction(async prisma => {
210
- const server = new TiddlerServer(state, prisma);
211
- return await server.saveRecipeTiddler(fields, state.pathParams.recipe_name);
212
- });
213
-
214
- return { bag_name, tiddler_id };
215
-
216
- });
217
-
218
-
219
- handleDeleteRecipeTiddler = zodRoute(
220
- ["DELETE"],
221
- "/recipes/:recipe_name/tiddlers/:title",
222
- z => ({
223
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
224
- title: z.prismaField("Tiddlers", "title", "string"),
225
- }),
226
- "json",
227
- z => z.undefined(),
228
- async (state) => {
229
-
230
- const { recipe_name, title } = state.pathParams;
231
- if (!recipe_name || !title) throw state.sendEmpty(404, { "x-reason": "bag_name or title not found" });
232
-
233
- await state.assertRecipeACL(recipe_name, true);
234
-
235
- const { bag_name, tiddler_id } = await state.$transaction(async prisma => {
236
- const server = new TiddlerServer(state, prisma);
237
- return await server.deleteRecipeTiddler(recipe_name, title);
238
- });
239
-
240
- return { bag_name, tiddler_id };
241
-
242
- });
243
-
244
- // this is not used by the sync adaptor. I'm not sure what uses it.
245
- handleCreateRecipeTiddler = zodRoute(
246
- ["POST"],
247
- "/recipes/:recipe_name/tiddlers",
248
- z => ({
249
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
250
- }),
251
- "json",
252
- z => z.object({
253
- title: z.prismaField("Tiddlers", "title", "string", false),
254
- }).and(z.record(z.string())),
255
- async (state) => {
256
-
257
- await state.assertRecipeACL(state.pathParams.recipe_name, true);
258
-
259
- const recipe_name = state.pathParams.recipe_name;
260
-
261
- return await state.$transaction(async prisma => {
262
- const server = new TiddlerServer(state, prisma);
263
- const { bag_name } = await server.getRecipeWritableBag(recipe_name) ?? {};
264
- if (!bag_name) throw state.sendEmpty(404, { "x-reason": "bag not found" });
265
- return { bag_name, results: await server.processIncomingStream(bag_name) };
266
- });
267
-
268
- });
269
-
270
- handleGetWikiIndex = zodRoute(
271
- ["GET", "HEAD"],
272
- "/wiki/:recipe_name",
273
- z => ({
274
- recipe_name: z.prismaField("Recipes", "recipe_name", "string"),
275
- }),
276
- "ignore",
277
- z => z.undefined(),
278
- async (state) => {
279
- await state.assertRecipeACL(state.pathParams.recipe_name, false);
280
-
281
- await state.$transaction(async prisma => {
282
- const server = new TiddlerServer(state, prisma);
283
- await server.serveIndexFile(state.pathParams.recipe_name);
284
- });
285
-
286
- throw STREAM_ENDED;
287
- });
288
-
289
- private sendTiddlerInfo = async (
290
- state: StateObject,
291
- tiddlerInfo: Awaited<ReturnType<TiddlerServer["getBagTiddler"]>>
292
- ) => {
293
-
294
- zodAssert.queryParams(state, z => ({
295
- fallback: z.array(z.string()).optional()
296
- }));
297
- // fallbacks are kind of slow, I'm not sure if this is a good idea
298
- if (!tiddlerInfo || !tiddlerInfo.tiddler) {
299
- // Redirect to fallback URL if tiddler not found
300
- const fallback = state.queryParams.fallback?.[0];
301
- if (fallback) {
302
- // await state.pushStream(fallback);
303
- throw state.redirect(fallback);
304
- } else {
305
- throw state.sendEmpty(404, { "x-reason": "tiddler not found (no fallback)" });
306
- }
307
- }
308
-
309
- return tiddlerInfo;
310
- }
311
-
312
-
313
- }