@tiddlywiki/mws 0.0.12 → 0.0.13
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/README.md +3 -1
- package/dist/server.d.ts +923 -0
- package/dist/server.js +1763 -1415
- package/dist/server.js.map +1 -1
- package/editions/mws-docs/tiddlers/$__StoryList.tid +3 -3
- package/editions/mws-docs/tiddlers/MWS and SQLite.md +11 -0
- package/editions/mws-docs/tiddlers/Request Server.md +20 -0
- package/editions/mws-docs/tiddlers/Request Server.md.meta +5 -0
- package/package.json +16 -10
- package/prisma/schema.prisma +1 -0
- package/react-user-mgmt/package-lock.json +76 -321
- package/react-user-mgmt/package.json +2 -5
- package/react-user-mgmt/public/chunk-YALWN5OT.js +2 -0
- package/react-user-mgmt/public/chunk-YALWN5OT.js.map +7 -0
- package/react-user-mgmt/public/esm-QKDFEP3B.js +3 -0
- package/react-user-mgmt/public/esm-QKDFEP3B.js.map +7 -0
- package/react-user-mgmt/public/index.html +1 -26
- package/react-user-mgmt/public/main.js +68 -109
- package/react-user-mgmt/public/main.js.map +4 -4
- package/react-user-mgmt/public/stats.css +597 -0
- package/react-user-mgmt/public/stats.html +59 -0
- package/react-user-mgmt/public/stats.js +2013 -0
- package/react-user-mgmt/public/stats.json +1 -0
- package/react-user-mgmt/public/stats.svg +4 -0
- package/react-user-mgmt/tsconfig.json +3 -0
- package/dist/server.cjs +0 -16677
- package/dist/server.cjs.map +0 -1
- package/src/StateObject.ts +0 -316
- package/src/commander.ts +0 -417
- package/src/commands/divider.ts +0 -20
- package/src/commands/index.ts +0 -24
- package/src/commands/mws-init-store.ts +0 -77
- package/src/commands/mws-listen.ts +0 -136
- package/src/commands/mws-load-archive.ts +0 -281
- package/src/commands/mws-load-plugin-bags.ts +0 -151
- package/src/commands/mws-load-tiddlers.ts +0 -37
- package/src/commands/mws-load-wiki-folder.ts +0 -124
- package/src/commands/mws-render-tiddlywiki5.ts +0 -55
- package/src/commands/mws-save-archive.ts +0 -111
- package/src/commands/mws-save-tiddler-text.ts +0 -33
- package/src/commands/tests-complete.ts +0 -21
- package/src/global.ts +0 -247
- package/src/routes/TiddlerStore.ts +0 -722
- package/src/routes/bag-file-server.ts +0 -340
- package/src/routes/cache.ts +0 -25
- package/src/routes/index.ts +0 -138
- package/src/routes/managers/index.ts +0 -17
- package/src/routes/managers/manager-recipes.ts +0 -438
- package/src/routes/managers/manager-users.ts +0 -201
- package/src/routes/managers/router-tiddlers.ts +0 -313
- package/src/routes/router.ts +0 -429
- package/src/routes/services/PasswordService.ts +0 -178
- package/src/routes/services/attachments.ts +0 -259
- package/src/routes/services/sessions.ts +0 -166
- package/src/routes/tw-test.ts +0 -65
- package/src/server.ts +0 -151
- package/src/setupDevServer.ts +0 -71
- package/src/streamer.ts +0 -430
- package/src/tiddlywiki.ts +0 -94
- package/src/utils/data-checks.ts +0 -172
- package/src/utils/index.ts +0 -4
- package/src/utils/rootRoute.ts +0 -237
- package/src/utils/utils.ts +0 -403
- package/src/utils/zodAssert.ts +0 -269
- /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
|
-
}
|