@crowi/api 2.0.0-alpha.0 → 2.0.0-alpha.1

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 (70) hide show
  1. package/dist/hono/handlers/access-token.d.ts +55 -55
  2. package/dist/hono/handlers/activation.d.ts +27 -27
  3. package/dist/hono/handlers/admin/app.d.ts +26 -26
  4. package/dist/hono/handlers/admin/auth.d.ts +24 -24
  5. package/dist/hono/handlers/admin/mail.d.ts +30 -30
  6. package/dist/hono/handlers/admin/plugins.d.ts +112 -112
  7. package/dist/hono/handlers/admin/search.d.ts +21 -21
  8. package/dist/hono/handlers/admin/security.d.ts +24 -24
  9. package/dist/hono/handlers/admin/storage.d.ts +19 -19
  10. package/dist/hono/handlers/admin/users.d.ts +305 -305
  11. package/dist/hono/handlers/adminCrypto.d.ts +32 -32
  12. package/dist/hono/handlers/app.d.ts +11 -8
  13. package/dist/hono/handlers/app.js +31 -1
  14. package/dist/hono/handlers/app.js.map +1 -1
  15. package/dist/hono/handlers/attachment.d.ts +180 -180
  16. package/dist/hono/handlers/autocomplete.d.ts +45 -45
  17. package/dist/hono/handlers/backlink.d.ts +33 -33
  18. package/dist/hono/handlers/bookmark.d.ts +95 -95
  19. package/dist/hono/handlers/comment.d.ts +55 -55
  20. package/dist/hono/handlers/draft.d.ts +27 -27
  21. package/dist/hono/handlers/emailChange.d.ts +25 -25
  22. package/dist/hono/handlers/installer.d.ts +16 -16
  23. package/dist/hono/handlers/inviteAccept.d.ts +37 -37
  24. package/dist/hono/handlers/me.d.ts +92 -92
  25. package/dist/hono/handlers/notification.d.ts +94 -94
  26. package/dist/hono/handlers/oauth.d.ts +58 -58
  27. package/dist/hono/handlers/page-collab.d.ts +20 -20
  28. package/dist/hono/handlers/page-preview.d.ts +7 -7
  29. package/dist/hono/handlers/page.d.ts +333 -333
  30. package/dist/hono/handlers/passwordReset.d.ts +37 -37
  31. package/dist/hono/handlers/presence.d.ts +44 -44
  32. package/dist/hono/handlers/revision.d.ts +99 -99
  33. package/dist/hono/handlers/search.d.ts +64 -64
  34. package/dist/hono/handlers/tokenAuth.d.ts +80 -80
  35. package/dist/hono/handlers/user.d.ts +102 -102
  36. package/dist/hono/handlers/user.js +15 -5
  37. package/dist/hono/handlers/user.js.map +1 -1
  38. package/dist/hono/index.d.ts +94 -94
  39. package/dist/mcp/result.d.ts +15 -0
  40. package/dist/mcp/result.js +20 -1
  41. package/dist/mcp/result.js.map +1 -1
  42. package/dist/mcp/tools/page.js +9 -4
  43. package/dist/mcp/tools/page.js.map +1 -1
  44. package/dist/migration/migrations/index.js +2 -0
  45. package/dist/migration/migrations/index.js.map +1 -1
  46. package/dist/migration/migrations/relocate-reserved-api-paths.d.ts +3 -0
  47. package/dist/migration/migrations/relocate-reserved-api-paths.js +135 -0
  48. package/dist/migration/migrations/relocate-reserved-api-paths.js.map +1 -0
  49. package/dist/models/page.js +9 -2
  50. package/dist/models/page.js.map +1 -1
  51. package/dist/util/replace-url.d.ts +85 -0
  52. package/dist/util/replace-url.js +251 -0
  53. package/dist/util/replace-url.js.map +1 -0
  54. package/package.json +6 -4
  55. package/public/images/file-not-found.png +0 -0
  56. package/views/mail/activation.mjml +9 -0
  57. package/views/mail/activation.text +13 -0
  58. package/views/mail/adminApprovalPending.mjml +7 -0
  59. package/views/mail/adminApprovalPending.text +11 -0
  60. package/views/mail/emailChange.mjml +9 -0
  61. package/views/mail/emailChange.text +13 -0
  62. package/views/mail/invite.mjml +9 -0
  63. package/views/mail/invite.text +13 -0
  64. package/views/mail/layout.mjml +36 -0
  65. package/views/mail/passwordChanged.mjml +4 -0
  66. package/views/mail/passwordChanged.text +9 -0
  67. package/views/mail/passwordReset.mjml +9 -0
  68. package/views/mail/passwordReset.text +13 -0
  69. package/views/mail/test.mjml +2 -0
  70. package/views/mail/test.text +7 -0
@@ -18,6 +18,37 @@ export type { CrowiHonoBindings } from './app';
18
18
  export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi").OpenAPIHono<import("./app").CrowiHonoBindings, {
19
19
  "/notifications": {
20
20
  $get: {
21
+ input: {
22
+ query: {
23
+ limit?: unknown;
24
+ offset?: unknown;
25
+ };
26
+ };
27
+ output: {
28
+ error: {
29
+ code: "INTERNAL_ERROR";
30
+ message: "Internal server error";
31
+ };
32
+ };
33
+ outputFormat: "json";
34
+ status: 500;
35
+ } | {
36
+ input: {
37
+ query: {
38
+ limit?: unknown;
39
+ offset?: unknown;
40
+ };
41
+ };
42
+ output: {
43
+ error: {
44
+ code: "AUTHENTICATION_REQUIRED";
45
+ message: "Authentication is required";
46
+ redirectTo?: string | undefined;
47
+ };
48
+ };
49
+ outputFormat: "json";
50
+ status: 401;
51
+ } | {
21
52
  input: {
22
53
  query: {
23
54
  limit?: unknown;
@@ -32,7 +63,7 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
32
63
  target: {
33
64
  path: string;
34
65
  _id: string;
35
- status?: "deleted" | "deprecated" | "published" | "wip" | "draft" | null | undefined;
66
+ status?: "published" | "wip" | "deleted" | "deprecated" | "draft" | null | undefined;
36
67
  };
37
68
  action: "COMMENT" | "LIKE" | "MENTION" | "UPDATE";
38
69
  status: "UNREAD" | "UNOPENED" | "OPENED";
@@ -58,37 +89,6 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
58
89
  };
59
90
  outputFormat: "json";
60
91
  status: 200;
61
- } | {
62
- input: {
63
- query: {
64
- limit?: unknown;
65
- offset?: unknown;
66
- };
67
- };
68
- output: {
69
- error: {
70
- code: "AUTHENTICATION_REQUIRED";
71
- message: "Authentication is required";
72
- redirectTo?: string | undefined;
73
- };
74
- };
75
- outputFormat: "json";
76
- status: 401;
77
- } | {
78
- input: {
79
- query: {
80
- limit?: unknown;
81
- offset?: unknown;
82
- };
83
- };
84
- output: {
85
- error: {
86
- code: "INTERNAL_ERROR";
87
- message: "Internal server error";
88
- };
89
- };
90
- outputFormat: "json";
91
- status: 500;
92
92
  };
93
93
  };
94
94
  } & {
@@ -96,10 +96,13 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
96
96
  $post: {
97
97
  input: {};
98
98
  output: {
99
- ok: true;
99
+ error: {
100
+ code: "INTERNAL_ERROR";
101
+ message: "Internal server error";
102
+ };
100
103
  };
101
104
  outputFormat: "json";
102
- status: 200;
105
+ status: 500;
103
106
  } | {
104
107
  input: {};
105
108
  output: {
@@ -114,13 +117,10 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
114
117
  } | {
115
118
  input: {};
116
119
  output: {
117
- error: {
118
- code: "INTERNAL_ERROR";
119
- message: "Internal server error";
120
- };
120
+ ok: true;
121
121
  };
122
122
  outputFormat: "json";
123
- status: 500;
123
+ status: 200;
124
124
  };
125
125
  };
126
126
  } & {
@@ -128,12 +128,13 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
128
128
  $get: {
129
129
  input: {};
130
130
  output: {
131
- token: string;
132
- selfUserId: string;
133
- expiresAt: string;
131
+ error: {
132
+ code: "INTERNAL_ERROR";
133
+ message: "Internal server error";
134
+ };
134
135
  };
135
136
  outputFormat: "json";
136
- status: 200;
137
+ status: 500;
137
138
  } | {
138
139
  input: {};
139
140
  output: {
@@ -148,13 +149,12 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
148
149
  } | {
149
150
  input: {};
150
151
  output: {
151
- error: {
152
- code: "INTERNAL_ERROR";
153
- message: "Internal server error";
154
- };
152
+ token: string;
153
+ selfUserId: string;
154
+ expiresAt: string;
155
155
  };
156
156
  outputFormat: "json";
157
- status: 500;
157
+ status: 200;
158
158
  };
159
159
  };
160
160
  } & {
@@ -162,10 +162,13 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
162
162
  $get: {
163
163
  input: {};
164
164
  output: {
165
- count: number;
165
+ error: {
166
+ code: "INTERNAL_ERROR";
167
+ message: "Internal server error";
168
+ };
166
169
  };
167
170
  outputFormat: "json";
168
- status: 200;
171
+ status: 500;
169
172
  } | {
170
173
  input: {};
171
174
  output: {
@@ -180,13 +183,10 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
180
183
  } | {
181
184
  input: {};
182
185
  output: {
183
- error: {
184
- code: "INTERNAL_ERROR";
185
- message: "Internal server error";
186
- };
186
+ count: number;
187
187
  };
188
188
  outputFormat: "json";
189
- status: 500;
189
+ status: 200;
190
190
  };
191
191
  };
192
192
  } & {
@@ -198,34 +198,13 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
198
198
  };
199
199
  };
200
200
  output: {
201
- notification: {
202
- _id: string;
203
- user: string;
204
- targetModel: "Page";
205
- target: {
206
- path: string;
207
- _id: string;
208
- status?: "deleted" | "deprecated" | "published" | "wip" | "draft" | null | undefined;
209
- };
210
- action: "COMMENT" | "LIKE" | "MENTION" | "UPDATE";
211
- status: "UNREAD" | "UNOPENED" | "OPENED";
212
- actionUsers: {
213
- _id: string;
214
- username: string;
215
- name: string;
216
- email: string;
217
- createdAt: string;
218
- id?: string | undefined;
219
- image?: string | null | undefined;
220
- introduction?: string | undefined;
221
- admin?: boolean | undefined;
222
- status?: 1 | 2 | 3 | 4 | 5 | undefined;
223
- }[];
224
- createdAt: string;
201
+ error: {
202
+ code: "INTERNAL_ERROR";
203
+ message: "Internal server error";
225
204
  };
226
205
  };
227
206
  outputFormat: "json";
228
- status: 200;
207
+ status: 500;
229
208
  } | {
230
209
  input: {
231
210
  param: {
@@ -234,12 +213,12 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
234
213
  };
235
214
  output: {
236
215
  error: {
237
- code: "INVALID_REQUEST";
238
- message: string;
216
+ code: "NOTIFICATION_NOT_FOUND";
217
+ message: "Notification not found";
239
218
  };
240
219
  };
241
220
  outputFormat: "json";
242
- status: 400;
221
+ status: 404;
243
222
  } | {
244
223
  input: {
245
224
  param: {
@@ -248,13 +227,12 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
248
227
  };
249
228
  output: {
250
229
  error: {
251
- code: "AUTHENTICATION_REQUIRED";
252
- message: "Authentication is required";
253
- redirectTo?: string | undefined;
230
+ code: "INVALID_REQUEST";
231
+ message: string;
254
232
  };
255
233
  };
256
234
  outputFormat: "json";
257
- status: 401;
235
+ status: 400;
258
236
  } | {
259
237
  input: {
260
238
  param: {
@@ -263,12 +241,13 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
263
241
  };
264
242
  output: {
265
243
  error: {
266
- code: "NOTIFICATION_NOT_FOUND";
267
- message: "Notification not found";
244
+ code: "AUTHENTICATION_REQUIRED";
245
+ message: "Authentication is required";
246
+ redirectTo?: string | undefined;
268
247
  };
269
248
  };
270
249
  outputFormat: "json";
271
- status: 404;
250
+ status: 401;
272
251
  } | {
273
252
  input: {
274
253
  param: {
@@ -276,13 +255,34 @@ export declare const buildHonoApp: (crowi: Crowi) => import("@hono/zod-openapi")
276
255
  };
277
256
  };
278
257
  output: {
279
- error: {
280
- code: "INTERNAL_ERROR";
281
- message: "Internal server error";
258
+ notification: {
259
+ _id: string;
260
+ user: string;
261
+ targetModel: "Page";
262
+ target: {
263
+ path: string;
264
+ _id: string;
265
+ status?: "published" | "wip" | "deleted" | "deprecated" | "draft" | null | undefined;
266
+ };
267
+ action: "COMMENT" | "LIKE" | "MENTION" | "UPDATE";
268
+ status: "UNREAD" | "UNOPENED" | "OPENED";
269
+ actionUsers: {
270
+ _id: string;
271
+ username: string;
272
+ name: string;
273
+ email: string;
274
+ createdAt: string;
275
+ id?: string | undefined;
276
+ image?: string | null | undefined;
277
+ introduction?: string | undefined;
278
+ admin?: boolean | undefined;
279
+ status?: 1 | 2 | 3 | 4 | 5 | undefined;
280
+ }[];
281
+ createdAt: string;
282
282
  };
283
283
  };
284
284
  outputFormat: "json";
285
- status: 500;
285
+ status: 200;
286
286
  };
287
287
  };
288
288
  }, "/">;
@@ -23,6 +23,21 @@ export interface McpToolResult {
23
23
  type Structured = Record<string, unknown>;
24
24
  /** Build a success result: a text block plus optional structured data. */
25
25
  export declare const okResult: (text: string, structuredContent?: Structured) => McpToolResult;
26
+ /**
27
+ * Build a success result for a single page/revision read whose primary
28
+ * payload IS the body. Carries `body` in BOTH places (belt-and-suspenders,
29
+ * RFC-0011 §9):
30
+ *
31
+ * - `content[0].text` = the body — for clients that read the text block.
32
+ * - `structuredContent` = `{ body, ...meta }` — for clients that prefer
33
+ * `structuredContent` and hide the text block. Without this, those
34
+ * clients lose the body entirely (the original bug).
35
+ *
36
+ * The small duplication is acceptable: read tools are single, non-streamed
37
+ * calls. List/search mappers keep using `okResult` — their useful payload
38
+ * already lives in `structuredContent`, so there is nothing to duplicate.
39
+ */
40
+ export declare const okResultWithBody: (body: string, meta: Structured) => McpToolResult;
26
41
  /**
27
42
  * Build an error result from an `ApiToolError`. The text is the API
28
43
  * error envelope's `code` + `message` (RFC-0011 §9) so the model gets a
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runTool = exports.errorResult = exports.okResult = void 0;
3
+ exports.runTool = exports.errorResult = exports.okResultWithBody = exports.okResult = void 0;
4
4
  /**
5
5
  * RFC-0011 §9 — mapping in-process dispatch results into MCP tool
6
6
  * results.
@@ -19,6 +19,25 @@ const okResult = (text, structuredContent) => ({
19
19
  ...(structuredContent ? { structuredContent } : {}),
20
20
  });
21
21
  exports.okResult = okResult;
22
+ /**
23
+ * Build a success result for a single page/revision read whose primary
24
+ * payload IS the body. Carries `body` in BOTH places (belt-and-suspenders,
25
+ * RFC-0011 §9):
26
+ *
27
+ * - `content[0].text` = the body — for clients that read the text block.
28
+ * - `structuredContent` = `{ body, ...meta }` — for clients that prefer
29
+ * `structuredContent` and hide the text block. Without this, those
30
+ * clients lose the body entirely (the original bug).
31
+ *
32
+ * The small duplication is acceptable: read tools are single, non-streamed
33
+ * calls. List/search mappers keep using `okResult` — their useful payload
34
+ * already lives in `structuredContent`, so there is nothing to duplicate.
35
+ */
36
+ const okResultWithBody = (body, meta) => ({
37
+ content: [{ type: 'text', text: body }],
38
+ structuredContent: { body, ...meta },
39
+ });
40
+ exports.okResultWithBody = okResultWithBody;
22
41
  /**
23
42
  * Build an error result from an `ApiToolError`. The text is the API
24
43
  * error envelope's `code` + `message` (RFC-0011 §9) so the model gets a
@@ -1 +1 @@
1
- {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/mcp/result.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;GAUG;AACH,yCAA0C;AAY1C,0EAA0E;AACnE,MAAM,QAAQ,GAAG,CAAC,IAAY,EAAE,iBAA8B,EAAiB,EAAE,CAAC,CAAC;IACxF,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IACjC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;CACpD,CAAC,CAAC;AAHU,QAAA,QAAQ,YAGlB;AAEH;;;;;GAKG;AACI,MAAM,WAAW,GAAG,CAAC,GAAiB,EAAiB,EAAE;IAC9D,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC;IACnD,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,qCAAqC,CAAC;IAC1E,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,IAAI,MAAM,OAAO,EAAE,EAAE,CAAC;QAChE,iBAAiB,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACnE,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC,CAAC;AATW,QAAA,WAAW,eAStB;AAEF;;;;;GAKG;AACI,MAAM,OAAO,GAAG,KAAK,EAAE,IAAkC,EAA0B,EAAE;IAC1F,IAAI,CAAC;QACH,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,uBAAY,EAAE,CAAC;YAChC,OAAO,IAAA,mBAAW,EAAC,GAAG,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC,CAAC;AATW,QAAA,OAAO,WASlB;AAEF,gEAAgE;AAChE,MAAM,oBAAoB,GAAG,CAAC,IAAa,EAAuC,EAAE;IAClF,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACxD,MAAM,KAAK,GAAI,IAA2B,CAAC,KAAK,CAAC;QACjD,mEAAmE;QACnE,gEAAgE;QAChE,2BAA2B;QAC3B,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,KAA8C,CAAC;YACzD,OAAO;gBACL,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;gBACrD,OAAO,EAAE,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;aAC/D,CAAC;QACJ,CAAC;QACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,OAAO,GAAI,IAA8B,CAAC,OAAO,CAAC;YACxD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;QACrF,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC,CAAC"}
1
+ {"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/mcp/result.ts"],"names":[],"mappings":"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"}
@@ -57,12 +57,17 @@ const DeletePageShape = {
57
57
  const RevertPageShape = {
58
58
  page_id: zod_1.z.string().describe('The id of the soft-deleted (trash) page to restore.'),
59
59
  };
60
- /** Pull the revision body + structured meta from a `{ page }` envelope. */
60
+ /**
61
+ * Pull the revision body + structured meta from a `{ page }` envelope. The
62
+ * body is the primary payload, so it is carried in both `content[0].text`
63
+ * and `structuredContent.body` (RFC-0011 §9, `okResultWithBody`) — clients
64
+ * that prefer `structuredContent` would otherwise lose it.
65
+ */
61
66
  const mapPageResult = (body) => {
62
67
  const page = body.page ?? {};
63
68
  const revision = page.revision ?? {};
64
69
  const text = typeof revision.body === 'string' ? revision.body : JSON.stringify(page, null, 2);
65
- return (0, result_1.okResult)(text, {
70
+ return (0, result_1.okResultWithBody)(text, {
66
71
  path: page.path,
67
72
  page_id: page._id,
68
73
  revision_id: revision._id,
@@ -70,11 +75,11 @@ const mapPageResult = (body) => {
70
75
  updatedAt: page.updatedAt,
71
76
  });
72
77
  };
73
- /** `{ revision }` single revision body. */
78
+ /** `{ revision }` single revision body (carried in both places, see above). */
74
79
  const mapRevisionResult = (body) => {
75
80
  const revision = body.revision ?? {};
76
81
  const text = typeof revision.body === 'string' ? revision.body : JSON.stringify(revision, null, 2);
77
- return (0, result_1.okResult)(text, { revision_id: revision._id, path: revision.path, createdAt: revision.createdAt });
82
+ return (0, result_1.okResultWithBody)(text, { revision_id: revision._id, path: revision.path, createdAt: revision.createdAt });
78
83
  };
79
84
  /**
80
85
  * Build a list result mapper: extract `field` from the envelope, render a
@@ -1 +1 @@
1
- {"version":3,"file":"page.js","sourceRoot":"","sources":["../../../src/mcp/tools/page.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../../src/mcp/tools/page.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.allMigrations = void 0;
4
4
  const page_status_default_1 = require("./page-status-default");
5
+ const relocate_reserved_api_paths_1 = require("./relocate-reserved-api-paths");
5
6
  const revisions_schema_unify_1 = require("./revisions-schema-unify");
6
7
  const user_unique_prepare_1 = require("./user-unique-prepare");
7
8
  const wikilink_format_1 = require("./wikilink-format");
@@ -20,5 +21,6 @@ exports.allMigrations = [
20
21
  wikilink_format_1.wikilinkFormat, // phase 3 (preflight)
21
22
  user_unique_prepare_1.userUniquePrepare, // phase 5 (preflight)
22
23
  revisions_schema_unify_1.revisionsSchemaUnify, // phase 6 (boot — RFC-classified preflight, see migration JSDoc)
24
+ relocate_reserved_api_paths_1.relocateReservedApiPaths, // fix/mcp-endpoint (preflight) — v2 /api namespace reservation
23
25
  ];
24
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/migration/migrations/index.ts"],"names":[],"mappings":";;;AACA,+DAA0D;AAC1D,qEAAgE;AAChE,+DAA0D;AAC1D,uDAAmD;AAEnD;;;;;;;;;GASG;AACU,QAAA,aAAa,GAA0B;IAClD,uCAAiB,EAAE,iBAAiB;IACpC,gCAAc,EAAE,sBAAsB;IACtC,uCAAiB,EAAE,sBAAsB;IACzC,6CAAoB,EAAE,iEAAiE;CACxF,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/migration/migrations/index.ts"],"names":[],"mappings":";;;AACA,+DAA0D;AAC1D,+EAAyE;AACzE,qEAAgE;AAChE,+DAA0D;AAC1D,uDAAmD;AAEnD;;;;;;;;;GASG;AACU,QAAA,aAAa,GAA0B;IAClD,uCAAiB,EAAE,iBAAiB;IACpC,gCAAc,EAAE,sBAAsB;IACtC,uCAAiB,EAAE,sBAAsB;IACzC,6CAAoB,EAAE,iEAAiE;IACvF,sDAAwB,EAAE,+DAA+D;CAC1F,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** `/api` → `/api-legacy`, `/api/foo` → `/api-legacy/foo`, `/api/` → `/api-legacy/`. */
2
+ export declare function relocatedApiPath(oldPath: string): string;
3
+ export declare const relocateReservedApiPaths: import("../types").MigrationDefinition;
@@ -0,0 +1,135 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.relocateReservedApiPaths = void 0;
4
+ exports.relocatedApiPath = relocatedApiPath;
5
+ const types_1 = require("../types");
6
+ /**
7
+ * v1 → v2.0 — `relocate-reserved-api-paths` (preflight layer).
8
+ *
9
+ * v2 reserves the `/api` namespace as the reverse-proxied backend route
10
+ * surface: the front proxy forwards `/api/v2/*` to the api, and
11
+ * `Page.isCreatableName` now refuses to create / rename a page under
12
+ * `/api`. v1, however, served its API at `/_api/*` (note the leading
13
+ * underscore — reserved by the `/_*` rule in `Page.isCreatableName`), so
14
+ * `/api/*` was a perfectly ordinary wiki page path. An upgraded wiki may hold
15
+ * legitimate v1 pages under `/api/*` that v2 would strand: the web app
16
+ * 404s the reserved namespace, and any page that happened to live at
17
+ * `/api/v2/*` is shadowed by the proxy entirely.
18
+ *
19
+ * This migration moves every surviving page out of `/api/*` into
20
+ * `/api-legacy/*` (preserving the rest of the path) so nothing is lost.
21
+ * `/api-legacy` is itself creatable (the reserved match is segment-bounded,
22
+ * so `api-legacy` does not collide). A pre-existing page at the relocation
23
+ * target is avoided by appending a `-N` suffix.
24
+ *
25
+ * It is `preflight` because it rewrites user-visible page paths: boot
26
+ * blocks until an operator runs `crowi-admin migrate apply` in a
27
+ * maintenance window. The move is done with plain `updateOne` /
28
+ * `updateMany` on the Page + Revision collections rather than
29
+ * `Page.rename`, deliberately bypassing the `pageEvent('update')` chain
30
+ * (mention dispatch / render-cache / backlink) — a path-only relocation of
31
+ * a legacy page must not re-notify mentioned users. No redirect stub is
32
+ * left at the old path: it sits inside the reserved namespace (unreachable
33
+ * by the web app, and `createPage` would itself reject it).
34
+ */
35
+ /**
36
+ * The reserved backend namespace, segment-bounded: matches `/api` and
37
+ * `/api/...` but never `/apiary`. Mirrors the `api` arm of the server's
38
+ * `Page.isCreatableName` forbidden list.
39
+ */
40
+ const RESERVED_API_PATH = /^\/api(\/|$)/;
41
+ /** Relocation root for displaced `/api/*` pages. */
42
+ const RELOCATE_ROOT = '/api-legacy';
43
+ /** Cap on suffix probing when the relocation target is already taken. */
44
+ const MAX_SUFFIX_ATTEMPTS = 1000;
45
+ /** `/api` → `/api-legacy`, `/api/foo` → `/api-legacy/foo`, `/api/` → `/api-legacy/`. */
46
+ function relocatedApiPath(oldPath) {
47
+ return RELOCATE_ROOT + oldPath.slice('/api'.length);
48
+ }
49
+ /**
50
+ * The first relocation target not already occupied by another page. Tries
51
+ * the bare relocated path, then `-1`, `-2`, … . Collisions are near-
52
+ * impossible in practice (`/api-legacy` is a fresh namespace), so this is
53
+ * defensive; it throws rather than loop unboundedly.
54
+ */
55
+ async function findFreeTarget(Page, candidate) {
56
+ if (!(await Page.exists({ path: candidate })))
57
+ return candidate;
58
+ for (let i = 1; i <= MAX_SUFFIX_ATTEMPTS; i++) {
59
+ const next = `${candidate}-${i}`;
60
+ if (!(await Page.exists({ path: next })))
61
+ return next;
62
+ }
63
+ throw new Error(`relocate-reserved-api-paths: could not find a free relocation target for '${candidate}' after ${MAX_SUFFIX_ATTEMPTS} attempts`);
64
+ }
65
+ /** Pages still living under the reserved `/api` namespace, `_id` + `path` only. */
66
+ async function collectApiPages(ctx) {
67
+ const Page = ctx.crowi.model('Page');
68
+ const rows = await Page.find({ path: RESERVED_API_PATH }).select('_id path').lean().exec();
69
+ return rows.map((r) => ({ _id: r._id, path: r.path }));
70
+ }
71
+ exports.relocateReservedApiPaths = (0, types_1.defineMigration)({
72
+ id: 'relocate-reserved-api-paths',
73
+ fromVersion: '1.x',
74
+ toVersion: '2.0',
75
+ layer: 'preflight',
76
+ description: 'Relocate v1 pages out of the v2-reserved /api namespace into /api-legacy',
77
+ /**
78
+ * Pending iff any page still lives under `/api/*`. The anchored regex on
79
+ * the unique-indexed `path` field lets the planner use the index for the
80
+ * `/api` literal prefix, so this stays an index-assisted existence probe
81
+ * rather than a full-collection scan (§4.2.1).
82
+ */
83
+ isPending: async (ctx) => {
84
+ const Page = ctx.crowi.model('Page');
85
+ // Crowi's `Page.exists` resolves to a boolean (see `checkPagesRenamable`),
86
+ // not Mongoose's `{ _id } | null` — `Boolean(...)` is correct either way.
87
+ return Boolean(await Page.exists({ path: RESERVED_API_PATH }));
88
+ },
89
+ /** Full scan for `plan`: count the pages that would move. Not called at boot. */
90
+ detect: async (ctx) => {
91
+ const pages = await collectApiPages(ctx);
92
+ return {
93
+ summary: `${pages.length} page(s) under the reserved /api namespace would move to ${RELOCATE_ROOT}/*`,
94
+ counts: { pages: pages.length },
95
+ };
96
+ },
97
+ stages: [
98
+ {
99
+ name: 'relocate-api-pages',
100
+ fn: async (ctx) => {
101
+ const Page = ctx.crowi.model('Page');
102
+ const Revision = ctx.crowi.model('Revision');
103
+ // Materialise the work-list up front: moving a page out of `/api/*`
104
+ // removes it from the query, so a live cursor could skip or double-
105
+ // count mid-iteration. The set is small (pages under one namespace).
106
+ const pages = await collectApiPages(ctx);
107
+ ctx.progress.setTotal(pages.length);
108
+ if (ctx.dryRun) {
109
+ // Preview only — resolve targets (read-only) so the report reflects
110
+ // collision handling, but perform no writes.
111
+ let wouldMove = 0;
112
+ for (const page of pages) {
113
+ await findFreeTarget(Page, relocatedApiPath(page.path));
114
+ wouldMove += 1;
115
+ ctx.progress.increment();
116
+ }
117
+ return { name: 'relocate-api-pages', transformed: 0, stats: { wouldMove } };
118
+ }
119
+ let moved = 0;
120
+ for (const page of pages) {
121
+ const target = await findFreeTarget(Page, relocatedApiPath(page.path));
122
+ // Page + its revisions both carry `path`; update both. Plain
123
+ // updateOne/updateMany so no pageEvent fires (see module JSDoc).
124
+ await Page.updateOne({ _id: page._id }, { $set: { path: target } });
125
+ await Revision.updateMany({ path: page.path }, { $set: { path: target } });
126
+ ctx.logger.info(`relocate-reserved-api-paths: moved '${page.path}' -> '${target}'`);
127
+ moved += 1;
128
+ ctx.progress.increment();
129
+ }
130
+ return { name: 'relocate-api-pages', transformed: moved };
131
+ },
132
+ },
133
+ ],
134
+ });
135
+ //# sourceMappingURL=relocate-reserved-api-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relocate-reserved-api-paths.js","sourceRoot":"","sources":["../../../src/migration/migrations/relocate-reserved-api-paths.ts"],"names":[],"mappings":"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"}
@@ -448,7 +448,7 @@ exports.default = (crowi) => {
448
448
  /\s+\/\s+/, // avoid miss in renaming
449
449
  /.+\/edit$/,
450
450
  /.+\.md$/,
451
- /^\/(installer|register|login|logout|admin|me|files|trash|paste|comments)(\/.*|$)/,
451
+ /^\/(installer|register|login|logout|admin|me|files|trash|paste|comments|api)(\/.*|$)/, // `api` is the reverse-proxied backend namespace
452
452
  ];
453
453
  let isCreatable = true;
454
454
  forbiddenPages.forEach(function (page) {
@@ -855,7 +855,14 @@ exports.default = (crowi) => {
855
855
  pageSchema.statics.updatePage = async function (pageData, body, user, options = {}) {
856
856
  const Revision = crowi.model('Revision');
857
857
  const Bookmark = crowi.model('Bookmark');
858
- const grant = options.grant || null;
858
+ // Default to the page's CURRENT grant when the caller doesn't pass one, so a
859
+ // body-only update leaves visibility untouched. A previous `options.grant ||
860
+ // null` turned every grant-less call (e.g. `updatePage(page, body, user, {})`
861
+ // from `rewritePageBody` / migrations) into `null != pageData.grant` → true,
862
+ // which re-granted the page to `null` + `grantedUsers=[user]` — silently
863
+ // dropping a public page out of `grant: GRANT_PUBLIC` listings. `??` keeps an
864
+ // explicit grant change working while making "no grant option" mean "keep".
865
+ const grant = options.grant ?? pageData.grant;
859
866
  // update existing page
860
867
  const newRevision = await Revision.prepareRevision(pageData, body, user, { editVia: options.editVia });
861
868
  // This is the external (REST / API) edit path — it bypasses the