payload-mcp-toolkit 0.3.0 → 0.3.2

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 (45) hide show
  1. package/README.md +3 -3
  2. package/dist/draft-workflow.d.ts +5 -4
  3. package/dist/draft-workflow.js +15 -7
  4. package/dist/draft-workflow.js.map +1 -1
  5. package/dist/index.js +6 -19
  6. package/dist/index.js.map +1 -1
  7. package/dist/introspection.d.ts +4 -0
  8. package/dist/introspection.js +7 -2
  9. package/dist/introspection.js.map +1 -1
  10. package/dist/resources.js +1 -8
  11. package/dist/resources.js.map +1 -1
  12. package/dist/tools/_helpers.d.ts +14 -0
  13. package/dist/tools/_helpers.js +35 -0
  14. package/dist/tools/_helpers.js.map +1 -0
  15. package/dist/tools/patch-layout.d.ts +3 -9
  16. package/dist/tools/patch-layout.js +29 -48
  17. package/dist/tools/patch-layout.js.map +1 -1
  18. package/dist/tools/publish-draft.d.ts +1 -11
  19. package/dist/tools/publish-draft.js +8 -39
  20. package/dist/tools/publish-draft.js.map +1 -1
  21. package/dist/tools/resolve-reference.d.ts +1 -12
  22. package/dist/tools/resolve-reference.js +45 -85
  23. package/dist/tools/resolve-reference.js.map +1 -1
  24. package/dist/tools/safe-delete.d.ts +8 -13
  25. package/dist/tools/safe-delete.js +68 -100
  26. package/dist/tools/safe-delete.js.map +1 -1
  27. package/dist/tools/schedule-publish.d.ts +11 -21
  28. package/dist/tools/schedule-publish.js +18 -61
  29. package/dist/tools/schedule-publish.js.map +1 -1
  30. package/dist/tools/search-content.d.ts +1 -6
  31. package/dist/tools/search-content.js +52 -64
  32. package/dist/tools/search-content.js.map +1 -1
  33. package/dist/tools/update-document.d.ts +4 -14
  34. package/dist/tools/update-document.js +23 -72
  35. package/dist/tools/update-document.js.map +1 -1
  36. package/dist/tools/upload-media.d.ts +1 -10
  37. package/dist/tools/upload-media.js +11 -54
  38. package/dist/tools/upload-media.js.map +1 -1
  39. package/dist/tools/versions.d.ts +7 -20
  40. package/dist/tools/versions.js +25 -82
  41. package/dist/tools/versions.js.map +1 -1
  42. package/package.json +1 -1
  43. package/dist/rate-limiter.d.ts +0 -25
  44. package/dist/rate-limiter.js +0 -51
  45. package/dist/rate-limiter.js.map +0 -1
@@ -1,10 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import type { PayloadRequest } from 'payload';
3
3
  /**
4
- * Creates the listVersions MCP tool that returns recent saved versions of a draft document.
5
- *
6
- * Only works on collections in `draftCollections`. Returns id, _status, updatedAt, and a
7
- * compact display name per version so an LLM can pick one to restore.
4
+ * Lists recent saved versions of a draft document. Returns id, _status,
5
+ * updatedAt, and a compact display name per version so an LLM can pick one
6
+ * to restore.
8
7
  */
9
8
  export declare function createListVersionsTool(draftCollections: Set<string>): {
10
9
  name: string;
@@ -18,18 +17,11 @@ export declare function createListVersionsTool(draftCollections: Set<string>): {
18
17
  collection: string;
19
18
  documentId: string;
20
19
  limit?: number;
21
- }, req: PayloadRequest, _extra: unknown) => Promise<{
22
- content: {
23
- type: "text";
24
- text: string;
25
- }[];
26
- }>;
20
+ }, req: PayloadRequest, _extra: unknown) => Promise<import("./_helpers").McpTextResponse>;
27
21
  };
28
22
  /**
29
- * Creates the restoreVersion MCP tool that rolls a document back to a saved version.
30
- *
31
- * Restoring a version creates a new version on top — the old current state is preserved
32
- * so the operation is itself reversible via another restore.
23
+ * Restoring a version creates a new version on top the previous current
24
+ * state is preserved so the operation is itself reversible.
33
25
  */
34
26
  export declare function createRestoreVersionTool(draftCollections: Set<string>): {
35
27
  name: string;
@@ -41,10 +33,5 @@ export declare function createRestoreVersionTool(draftCollections: Set<string>):
41
33
  handler: (args: {
42
34
  collection: string;
43
35
  versionId: string;
44
- }, req: PayloadRequest, _extra: unknown) => Promise<{
45
- content: {
46
- type: "text";
47
- text: string;
48
- }[];
49
- }>;
36
+ }, req: PayloadRequest, _extra: unknown) => Promise<import("./_helpers").McpTextResponse>;
50
37
  };
@@ -1,10 +1,10 @@
1
1
  import { z } from 'zod';
2
+ import { errorMessage, getDocDisplayName, jsonResponse, requireDraftCollection, stampMcpContext, textResponse } from './_helpers';
2
3
  const DEFAULT_LIST_LIMIT = 10;
3
4
  /**
4
- * Creates the listVersions MCP tool that returns recent saved versions of a draft document.
5
- *
6
- * Only works on collections in `draftCollections`. Returns id, _status, updatedAt, and a
7
- * compact display name per version so an LLM can pick one to restore.
5
+ * Lists recent saved versions of a draft document. Returns id, _status,
6
+ * updatedAt, and a compact display name per version so an LLM can pick one
7
+ * to restore.
8
8
  */ export function createListVersionsTool(draftCollections) {
9
9
  return {
10
10
  name: 'listVersions',
@@ -20,22 +20,9 @@ const DEFAULT_LIST_LIMIT = 10;
20
20
  },
21
21
  handler: async (args, req, _extra)=>{
22
22
  const { collection, documentId, limit = DEFAULT_LIST_LIMIT } = args;
23
- if (!draftCollections.has(collection)) {
24
- return {
25
- content: [
26
- {
27
- type: 'text',
28
- text: `Error: Collection "${collection}" does not support versions. ` + `Draft-enabled collections: ${[
29
- ...draftCollections
30
- ].join(', ') || 'none'}`
31
- }
32
- ]
33
- };
34
- }
35
- req.context = {
36
- ...req.context,
37
- source: 'mcp'
38
- };
23
+ const guard = requireDraftCollection(collection, draftCollections, 'versions');
24
+ if (guard) return guard;
25
+ stampMcpContext(req);
39
26
  try {
40
27
  const result = await req.payload.findVersions({
41
28
  collection: collection,
@@ -57,43 +44,26 @@ const DEFAULT_LIST_LIMIT = 10;
57
44
  updatedAt: v.updatedAt,
58
45
  createdAt: v.createdAt,
59
46
  status: snapshot._status ?? 'unknown',
60
- displayName: snapshot.name || snapshot.title || snapshot.slug || `${collection}#${documentId}`,
47
+ displayName: getDocDisplayName(snapshot, `${collection}#${documentId}`),
61
48
  autosave: v.autosave === true
62
49
  };
63
50
  });
64
- return {
65
- content: [
66
- {
67
- type: 'text',
68
- text: JSON.stringify({
69
- collection,
70
- documentId,
71
- totalDocs: result.totalDocs,
72
- returned: versions.length,
73
- versions
74
- })
75
- }
76
- ]
77
- };
51
+ return jsonResponse({
52
+ collection,
53
+ documentId,
54
+ totalDocs: result.totalDocs,
55
+ returned: versions.length,
56
+ versions
57
+ });
78
58
  } catch (error) {
79
- const message = error instanceof Error ? error.message : String(error);
80
- return {
81
- content: [
82
- {
83
- type: 'text',
84
- text: `Error listing versions for ${collection}#${documentId}: ${message}`
85
- }
86
- ]
87
- };
59
+ return textResponse(`Error listing versions for ${collection}#${documentId}: ${errorMessage(error)}`);
88
60
  }
89
61
  }
90
62
  };
91
63
  }
92
64
  /**
93
- * Creates the restoreVersion MCP tool that rolls a document back to a saved version.
94
- *
95
- * Restoring a version creates a new version on top — the old current state is preserved
96
- * so the operation is itself reversible via another restore.
65
+ * Restoring a version creates a new version on top the previous current
66
+ * state is preserved so the operation is itself reversible.
97
67
  */ export function createRestoreVersionTool(draftCollections) {
98
68
  return {
99
69
  name: 'restoreVersion',
@@ -108,22 +78,9 @@ const DEFAULT_LIST_LIMIT = 10;
108
78
  },
109
79
  handler: async (args, req, _extra)=>{
110
80
  const { collection, versionId } = args;
111
- if (!draftCollections.has(collection)) {
112
- return {
113
- content: [
114
- {
115
- type: 'text',
116
- text: `Error: Collection "${collection}" does not support versions. ` + `Draft-enabled collections: ${[
117
- ...draftCollections
118
- ].join(', ') || 'none'}`
119
- }
120
- ]
121
- };
122
- }
123
- req.context = {
124
- ...req.context,
125
- source: 'mcp'
126
- };
81
+ const guard = requireDraftCollection(collection, draftCollections, 'versions');
82
+ if (guard) return guard;
83
+ stampMcpContext(req);
127
84
  try {
128
85
  const restored = await req.payload.restoreVersion({
129
86
  collection: collection,
@@ -132,25 +89,11 @@ const DEFAULT_LIST_LIMIT = 10;
132
89
  overrideAccess: false,
133
90
  user: req.user
134
91
  });
135
- const displayName = restored.name || restored.title || restored.slug || restored.id;
136
- return {
137
- content: [
138
- {
139
- type: 'text',
140
- text: `Restored ${collection} document "${displayName}" (ID: ${restored.id}) ` + `from version ${versionId}. The document is now in draft status — ` + `use publishDraft to make the restored content live.`
141
- }
142
- ]
143
- };
92
+ const restoredId = String(restored.id);
93
+ const displayName = getDocDisplayName(restored, restoredId);
94
+ return textResponse(`Restored ${collection} document "${displayName}" (ID: ${restoredId}) ` + `from version ${versionId}. The document is now in draft status — ` + `use publishDraft to make the restored content live.`);
144
95
  } catch (error) {
145
- const message = error instanceof Error ? error.message : String(error);
146
- return {
147
- content: [
148
- {
149
- type: 'text',
150
- text: `Error restoring ${collection} from version ${versionId}: ${message}`
151
- }
152
- ]
153
- };
96
+ return textResponse(`Error restoring ${collection} from version ${versionId}: ${errorMessage(error)}`);
154
97
  }
155
98
  }
156
99
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tools/versions.ts"],"sourcesContent":["import { z } from 'zod'\nimport type { PayloadRequest } from 'payload'\n\nconst DEFAULT_LIST_LIMIT = 10\n\n/**\n * Creates the listVersions MCP tool that returns recent saved versions of a draft document.\n *\n * Only works on collections in `draftCollections`. Returns id, _status, updatedAt, and a\n * compact display name per version so an LLM can pick one to restore.\n */\nexport function createListVersionsTool(draftCollections: Set<string>) {\n return {\n name: 'listVersions',\n description:\n 'List recent saved versions of a document on a draft-enabled collection. ' +\n 'Use before restoreVersion to pick the right point in time. ' +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n parameters: {\n collection: z\n .string()\n .describe(\n `The collection slug. Must be one of: ${[...draftCollections].join(', ') || 'none'}`,\n ),\n documentId: z.string().describe('The ID of the document whose versions you want to list'),\n limit: z\n .number()\n .optional()\n .default(DEFAULT_LIST_LIMIT)\n .describe(`Maximum number of versions to return (default ${DEFAULT_LIST_LIMIT})`),\n },\n handler: async (\n args: { collection: string; documentId: string; limit?: number },\n req: PayloadRequest,\n _extra: unknown,\n ) => {\n const { collection, documentId, limit = DEFAULT_LIST_LIMIT } = args\n\n if (!draftCollections.has(collection)) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Error: Collection \"${collection}\" does not support versions. ` +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n },\n ],\n }\n }\n\n req.context = { ...req.context, source: 'mcp' }\n\n try {\n const result = await req.payload.findVersions({\n collection: collection as any,\n where: { parent: { equals: documentId } },\n sort: '-updatedAt',\n limit,\n req,\n overrideAccess: false,\n user: req.user,\n })\n\n const versions = result.docs.map((v: any) => {\n const snapshot = v.version || {}\n return {\n id: v.id,\n updatedAt: v.updatedAt,\n createdAt: v.createdAt,\n status: snapshot._status ?? 'unknown',\n displayName:\n snapshot.name ||\n snapshot.title ||\n snapshot.slug ||\n `${collection}#${documentId}`,\n autosave: v.autosave === true,\n }\n })\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify({\n collection,\n documentId,\n totalDocs: result.totalDocs,\n returned: versions.length,\n versions,\n }),\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error listing versions for ${collection}#${documentId}: ${message}`,\n },\n ],\n }\n }\n },\n }\n}\n\n/**\n * Creates the restoreVersion MCP tool that rolls a document back to a saved version.\n *\n * Restoring a version creates a new version on top — the old current state is preserved\n * so the operation is itself reversible via another restore.\n */\nexport function createRestoreVersionTool(draftCollections: Set<string>) {\n return {\n name: 'restoreVersion',\n description:\n 'Restore a document to a previously saved version. ' +\n 'Use listVersions first to find the version ID. ' +\n 'Restoring creates a new version on top, so the previous current state is also recoverable. ' +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n parameters: {\n collection: z\n .string()\n .describe(\n `The collection slug. Must be one of: ${[...draftCollections].join(', ') || 'none'}`,\n ),\n versionId: z\n .string()\n .describe('The version ID returned by listVersions (NOT the document ID)'),\n },\n handler: async (\n args: { collection: string; versionId: string },\n req: PayloadRequest,\n _extra: unknown,\n ) => {\n const { collection, versionId } = args\n\n if (!draftCollections.has(collection)) {\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Error: Collection \"${collection}\" does not support versions. ` +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n },\n ],\n }\n }\n\n req.context = { ...req.context, source: 'mcp' }\n\n try {\n const restored = await req.payload.restoreVersion({\n collection: collection as any,\n id: versionId,\n req,\n overrideAccess: false,\n user: req.user,\n })\n\n const displayName =\n (restored as any).name ||\n (restored as any).title ||\n (restored as any).slug ||\n (restored as any).id\n\n return {\n content: [\n {\n type: 'text' as const,\n text:\n `Restored ${collection} document \"${displayName}\" (ID: ${(restored as any).id}) ` +\n `from version ${versionId}. The document is now in draft status — ` +\n `use publishDraft to make the restored content live.`,\n },\n ],\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error)\n return {\n content: [\n {\n type: 'text' as const,\n text: `Error restoring ${collection} from version ${versionId}: ${message}`,\n },\n ],\n }\n }\n },\n }\n}\n"],"names":["z","DEFAULT_LIST_LIMIT","createListVersionsTool","draftCollections","name","description","join","parameters","collection","string","describe","documentId","limit","number","optional","default","handler","args","req","_extra","has","content","type","text","context","source","result","payload","findVersions","where","parent","equals","sort","overrideAccess","user","versions","docs","map","v","snapshot","version","id","updatedAt","createdAt","status","_status","displayName","title","slug","autosave","JSON","stringify","totalDocs","returned","length","error","message","Error","String","createRestoreVersionTool","versionId","restored","restoreVersion"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/tools/versions.ts"],"sourcesContent":["import { z } from 'zod'\nimport type { PayloadRequest } from 'payload'\nimport {\n errorMessage,\n getDocDisplayName,\n jsonResponse,\n requireDraftCollection,\n stampMcpContext,\n textResponse,\n} from './_helpers'\n\nconst DEFAULT_LIST_LIMIT = 10\n\n/**\n * Lists recent saved versions of a draft document. Returns id, _status,\n * updatedAt, and a compact display name per version so an LLM can pick one\n * to restore.\n */\nexport function createListVersionsTool(draftCollections: Set<string>) {\n return {\n name: 'listVersions',\n description:\n 'List recent saved versions of a document on a draft-enabled collection. ' +\n 'Use before restoreVersion to pick the right point in time. ' +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n parameters: {\n collection: z\n .string()\n .describe(\n `The collection slug. Must be one of: ${[...draftCollections].join(', ') || 'none'}`,\n ),\n documentId: z.string().describe('The ID of the document whose versions you want to list'),\n limit: z\n .number()\n .optional()\n .default(DEFAULT_LIST_LIMIT)\n .describe(`Maximum number of versions to return (default ${DEFAULT_LIST_LIMIT})`),\n },\n handler: async (\n args: { collection: string; documentId: string; limit?: number },\n req: PayloadRequest,\n _extra: unknown,\n ) => {\n const { collection, documentId, limit = DEFAULT_LIST_LIMIT } = args\n\n const guard = requireDraftCollection(collection, draftCollections, 'versions')\n if (guard) return guard\n\n stampMcpContext(req)\n\n try {\n const result = await req.payload.findVersions({\n collection: collection as any,\n where: { parent: { equals: documentId } },\n sort: '-updatedAt',\n limit,\n req,\n overrideAccess: false,\n user: req.user,\n })\n\n const versions = result.docs.map((v: any) => {\n const snapshot = v.version || {}\n return {\n id: v.id,\n updatedAt: v.updatedAt,\n createdAt: v.createdAt,\n status: snapshot._status ?? 'unknown',\n displayName: getDocDisplayName(snapshot, `${collection}#${documentId}`),\n autosave: v.autosave === true,\n }\n })\n\n return jsonResponse({\n collection,\n documentId,\n totalDocs: result.totalDocs,\n returned: versions.length,\n versions,\n })\n } catch (error) {\n return textResponse(\n `Error listing versions for ${collection}#${documentId}: ${errorMessage(error)}`,\n )\n }\n },\n }\n}\n\n/**\n * Restoring a version creates a new version on top — the previous current\n * state is preserved so the operation is itself reversible.\n */\nexport function createRestoreVersionTool(draftCollections: Set<string>) {\n return {\n name: 'restoreVersion',\n description:\n 'Restore a document to a previously saved version. ' +\n 'Use listVersions first to find the version ID. ' +\n 'Restoring creates a new version on top, so the previous current state is also recoverable. ' +\n `Draft-enabled collections: ${[...draftCollections].join(', ') || 'none'}`,\n parameters: {\n collection: z\n .string()\n .describe(\n `The collection slug. Must be one of: ${[...draftCollections].join(', ') || 'none'}`,\n ),\n versionId: z\n .string()\n .describe('The version ID returned by listVersions (NOT the document ID)'),\n },\n handler: async (\n args: { collection: string; versionId: string },\n req: PayloadRequest,\n _extra: unknown,\n ) => {\n const { collection, versionId } = args\n\n const guard = requireDraftCollection(collection, draftCollections, 'versions')\n if (guard) return guard\n\n stampMcpContext(req)\n\n try {\n const restored = await req.payload.restoreVersion({\n collection: collection as any,\n id: versionId,\n req,\n overrideAccess: false,\n user: req.user,\n })\n\n const restoredId = String((restored as any).id)\n const displayName = getDocDisplayName(restored, restoredId)\n\n return textResponse(\n `Restored ${collection} document \"${displayName}\" (ID: ${restoredId}) ` +\n `from version ${versionId}. The document is now in draft status — ` +\n `use publishDraft to make the restored content live.`,\n )\n } catch (error) {\n return textResponse(\n `Error restoring ${collection} from version ${versionId}: ${errorMessage(error)}`,\n )\n }\n },\n }\n}\n"],"names":["z","errorMessage","getDocDisplayName","jsonResponse","requireDraftCollection","stampMcpContext","textResponse","DEFAULT_LIST_LIMIT","createListVersionsTool","draftCollections","name","description","join","parameters","collection","string","describe","documentId","limit","number","optional","default","handler","args","req","_extra","guard","result","payload","findVersions","where","parent","equals","sort","overrideAccess","user","versions","docs","map","v","snapshot","version","id","updatedAt","createdAt","status","_status","displayName","autosave","totalDocs","returned","length","error","createRestoreVersionTool","versionId","restored","restoreVersion","restoredId","String"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "payload-mcp-toolkit",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "description": "Schema-aware MCP toolkit for Payload CMS — wraps the official @payloadcms/plugin-mcp with introspected prompts, resources, draft workflow, and AI-friendly tools so non-technical editors can manage content via AI chat.",
5
5
  "license": "MIT",
6
6
  "author": "jon8800",
@@ -1,25 +0,0 @@
1
- /**
2
- * Simple in-memory sliding window rate limiter per API key.
3
- * State resets on server restart — not suitable for serverless.
4
- */
5
- interface RateLimitOptions {
6
- /** Window duration in milliseconds (default: 60000 = 1 minute) */
7
- windowMs?: number;
8
- /** Maximum requests per window (default: 60) */
9
- maxRequests?: number;
10
- }
11
- export declare function createRateLimiter(options?: RateLimitOptions): {
12
- /**
13
- * Check if a request is allowed for the given key.
14
- * Returns { allowed: true } or { allowed: false, retryAfterMs }.
15
- */
16
- check(key: string): {
17
- allowed: true;
18
- } | {
19
- allowed: false;
20
- retryAfterMs: number;
21
- };
22
- /** Reset the store (for testing) */
23
- reset(): void;
24
- };
25
- export {};
@@ -1,51 +0,0 @@
1
- /**
2
- * Simple in-memory sliding window rate limiter per API key.
3
- * State resets on server restart — not suitable for serverless.
4
- */ const DEFAULT_WINDOW_MS = 60_000;
5
- const DEFAULT_MAX_REQUESTS = 60;
6
- export function createRateLimiter(options) {
7
- const windowMs = options?.windowMs ?? DEFAULT_WINDOW_MS;
8
- const maxRequests = options?.maxRequests ?? DEFAULT_MAX_REQUESTS;
9
- const store = new Map();
10
- // Periodically clean up expired entries (every 5 minutes)
11
- const cleanupInterval = setInterval(()=>{
12
- const now = Date.now();
13
- for (const [key, entry] of store){
14
- entry.timestamps = entry.timestamps.filter((t)=>now - t < windowMs);
15
- if (entry.timestamps.length === 0) store.delete(key);
16
- }
17
- }, 5 * 60_000);
18
- // Allow garbage collection if the module is unloaded
19
- if (cleanupInterval.unref) cleanupInterval.unref();
20
- return {
21
- /**
22
- * Check if a request is allowed for the given key.
23
- * Returns { allowed: true } or { allowed: false, retryAfterMs }.
24
- */ check (key) {
25
- const now = Date.now();
26
- const entry = store.get(key) ?? {
27
- timestamps: []
28
- };
29
- // Remove timestamps outside the window
30
- entry.timestamps = entry.timestamps.filter((t)=>now - t < windowMs);
31
- if (entry.timestamps.length >= maxRequests) {
32
- const oldest = entry.timestamps[0];
33
- const retryAfterMs = oldest + windowMs - now;
34
- return {
35
- allowed: false,
36
- retryAfterMs: Math.max(retryAfterMs, 1000)
37
- };
38
- }
39
- entry.timestamps.push(now);
40
- store.set(key, entry);
41
- return {
42
- allowed: true
43
- };
44
- },
45
- /** Reset the store (for testing) */ reset () {
46
- store.clear();
47
- }
48
- };
49
- }
50
-
51
- //# sourceMappingURL=rate-limiter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/rate-limiter.ts"],"sourcesContent":["/**\n * Simple in-memory sliding window rate limiter per API key.\n * State resets on server restart — not suitable for serverless.\n */\n\ninterface RateLimitEntry {\n timestamps: number[]\n}\n\ninterface RateLimitOptions {\n /** Window duration in milliseconds (default: 60000 = 1 minute) */\n windowMs?: number\n /** Maximum requests per window (default: 60) */\n maxRequests?: number\n}\n\nconst DEFAULT_WINDOW_MS = 60_000\nconst DEFAULT_MAX_REQUESTS = 60\n\nexport function createRateLimiter(options?: RateLimitOptions) {\n const windowMs = options?.windowMs ?? DEFAULT_WINDOW_MS\n const maxRequests = options?.maxRequests ?? DEFAULT_MAX_REQUESTS\n const store = new Map<string, RateLimitEntry>()\n\n // Periodically clean up expired entries (every 5 minutes)\n const cleanupInterval = setInterval(() => {\n const now = Date.now()\n for (const [key, entry] of store) {\n entry.timestamps = entry.timestamps.filter((t) => now - t < windowMs)\n if (entry.timestamps.length === 0) store.delete(key)\n }\n }, 5 * 60_000)\n\n // Allow garbage collection if the module is unloaded\n if (cleanupInterval.unref) cleanupInterval.unref()\n\n return {\n /**\n * Check if a request is allowed for the given key.\n * Returns { allowed: true } or { allowed: false, retryAfterMs }.\n */\n check(key: string): { allowed: true } | { allowed: false; retryAfterMs: number } {\n const now = Date.now()\n const entry = store.get(key) ?? { timestamps: [] }\n\n // Remove timestamps outside the window\n entry.timestamps = entry.timestamps.filter((t) => now - t < windowMs)\n\n if (entry.timestamps.length >= maxRequests) {\n const oldest = entry.timestamps[0]\n const retryAfterMs = oldest + windowMs - now\n return { allowed: false, retryAfterMs: Math.max(retryAfterMs, 1000) }\n }\n\n entry.timestamps.push(now)\n store.set(key, entry)\n return { allowed: true }\n },\n\n /** Reset the store (for testing) */\n reset() {\n store.clear()\n },\n }\n}\n"],"names":["DEFAULT_WINDOW_MS","DEFAULT_MAX_REQUESTS","createRateLimiter","options","windowMs","maxRequests","store","Map","cleanupInterval","setInterval","now","Date","key","entry","timestamps","filter","t","length","delete","unref","check","get","oldest","retryAfterMs","allowed","Math","max","push","set","reset","clear"],"mappings":"AAAA;;;CAGC,GAaD,MAAMA,oBAAoB;AAC1B,MAAMC,uBAAuB;AAE7B,OAAO,SAASC,kBAAkBC,OAA0B;IAC1D,MAAMC,WAAWD,SAASC,YAAYJ;IACtC,MAAMK,cAAcF,SAASE,eAAeJ;IAC5C,MAAMK,QAAQ,IAAIC;IAElB,0DAA0D;IAC1D,MAAMC,kBAAkBC,YAAY;QAClC,MAAMC,MAAMC,KAAKD,GAAG;QACpB,KAAK,MAAM,CAACE,KAAKC,MAAM,IAAIP,MAAO;YAChCO,MAAMC,UAAU,GAAGD,MAAMC,UAAU,CAACC,MAAM,CAAC,CAACC,IAAMN,MAAMM,IAAIZ;YAC5D,IAAIS,MAAMC,UAAU,CAACG,MAAM,KAAK,GAAGX,MAAMY,MAAM,CAACN;QAClD;IACF,GAAG,IAAI;IAEP,qDAAqD;IACrD,IAAIJ,gBAAgBW,KAAK,EAAEX,gBAAgBW,KAAK;IAEhD,OAAO;QACL;;;KAGC,GACDC,OAAMR,GAAW;YACf,MAAMF,MAAMC,KAAKD,GAAG;YACpB,MAAMG,QAAQP,MAAMe,GAAG,CAACT,QAAQ;gBAAEE,YAAY,EAAE;YAAC;YAEjD,uCAAuC;YACvCD,MAAMC,UAAU,GAAGD,MAAMC,UAAU,CAACC,MAAM,CAAC,CAACC,IAAMN,MAAMM,IAAIZ;YAE5D,IAAIS,MAAMC,UAAU,CAACG,MAAM,IAAIZ,aAAa;gBAC1C,MAAMiB,SAAST,MAAMC,UAAU,CAAC,EAAE;gBAClC,MAAMS,eAAeD,SAASlB,WAAWM;gBACzC,OAAO;oBAAEc,SAAS;oBAAOD,cAAcE,KAAKC,GAAG,CAACH,cAAc;gBAAM;YACtE;YAEAV,MAAMC,UAAU,CAACa,IAAI,CAACjB;YACtBJ,MAAMsB,GAAG,CAAChB,KAAKC;YACf,OAAO;gBAAEW,SAAS;YAAK;QACzB;QAEA,kCAAkC,GAClCK;YACEvB,MAAMwB,KAAK;QACb;IACF;AACF"}