@fadlee/pocketbase-mcp 1.0.0
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/LICENSE +21 -0
- package/README.md +123 -0
- package/build/src/config/cli.d.ts +9 -0
- package/build/src/config/cli.js +31 -0
- package/build/src/config/environment.d.ts +9 -0
- package/build/src/config/environment.js +13 -0
- package/build/src/config/index.d.ts +13 -0
- package/build/src/config/index.js +20 -0
- package/build/src/index.d.ts +2 -0
- package/build/src/index.js +21 -0
- package/build/src/server.d.ts +10 -0
- package/build/src/server.js +211 -0
- package/build/src/tools/handlers/analysis.d.ts +10 -0
- package/build/src/tools/handlers/analysis.js +127 -0
- package/build/src/tools/handlers/auth.d.ts +10 -0
- package/build/src/tools/handlers/auth.js +51 -0
- package/build/src/tools/handlers/collection.d.ts +22 -0
- package/build/src/tools/handlers/collection.js +82 -0
- package/build/src/tools/handlers/file.d.ts +5 -0
- package/build/src/tools/handlers/file.js +124 -0
- package/build/src/tools/handlers/generation.d.ts +10 -0
- package/build/src/tools/handlers/generation.js +201 -0
- package/build/src/tools/handlers/index.d.ts +10 -0
- package/build/src/tools/handlers/index.js +17 -0
- package/build/src/tools/handlers/migration.d.ts +18 -0
- package/build/src/tools/handlers/migration.js +219 -0
- package/build/src/tools/handlers/record.d.ts +18 -0
- package/build/src/tools/handlers/record.js +94 -0
- package/build/src/tools/index.d.ts +5 -0
- package/build/src/tools/index.js +7 -0
- package/build/src/tools/schemas/analysis.d.ts +56 -0
- package/build/src/tools/schemas/analysis.js +54 -0
- package/build/src/tools/schemas/auth.d.ts +59 -0
- package/build/src/tools/schemas/auth.js +59 -0
- package/build/src/tools/schemas/collection.d.ts +192 -0
- package/build/src/tools/schemas/collection.js +194 -0
- package/build/src/tools/schemas/file.d.ts +70 -0
- package/build/src/tools/schemas/file.js +70 -0
- package/build/src/tools/schemas/generation.d.ts +49 -0
- package/build/src/tools/schemas/generation.js +49 -0
- package/build/src/tools/schemas/index.d.ts +10 -0
- package/build/src/tools/schemas/index.js +17 -0
- package/build/src/tools/schemas/migration.d.ts +133 -0
- package/build/src/tools/schemas/migration.js +146 -0
- package/build/src/tools/schemas/record.d.ts +103 -0
- package/build/src/tools/schemas/record.js +103 -0
- package/build/src/types/index.d.ts +188 -0
- package/build/src/types/index.js +1 -0
- package/build/src/utils/errors.d.ts +17 -0
- package/build/src/utils/errors.js +35 -0
- package/build/src/utils/response.d.ts +23 -0
- package/build/src/utils/response.js +62 -0
- package/build/src/utils/typescript.d.ts +24 -0
- package/build/src/utils/typescript.js +130 -0
- package/package.json +57 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { handlePocketBaseError } from "../../utils/errors.js";
|
|
2
|
+
import { createJsonResponse } from "../../utils/response.js";
|
|
3
|
+
/**
|
|
4
|
+
* Authenticate a user and get auth token
|
|
5
|
+
*/
|
|
6
|
+
export function createAuthenticateUserHandler(pb) {
|
|
7
|
+
return async (args) => {
|
|
8
|
+
try {
|
|
9
|
+
const collection = args.collection || "users";
|
|
10
|
+
const autoRefreshThreshold = args.autoRefreshThreshold || 1800; // 30 minutes
|
|
11
|
+
const result = await pb
|
|
12
|
+
.collection(collection)
|
|
13
|
+
.authWithPassword(args.email, args.password, {
|
|
14
|
+
autoRefreshThreshold,
|
|
15
|
+
});
|
|
16
|
+
return createJsonResponse(result);
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw handlePocketBaseError("authenticate user", error);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Create a new user account
|
|
25
|
+
*/
|
|
26
|
+
export function createCreateUserHandler(pb) {
|
|
27
|
+
return async (args) => {
|
|
28
|
+
try {
|
|
29
|
+
const collection = args.collection || "users";
|
|
30
|
+
const userData = {
|
|
31
|
+
email: args.email,
|
|
32
|
+
password: args.password,
|
|
33
|
+
passwordConfirm: args.passwordConfirm,
|
|
34
|
+
};
|
|
35
|
+
// Add optional fields
|
|
36
|
+
if (args.verified !== undefined)
|
|
37
|
+
userData.verified = args.verified;
|
|
38
|
+
if (args.emailVisibility !== undefined)
|
|
39
|
+
userData.emailVisibility = args.emailVisibility;
|
|
40
|
+
// Add any additional data fields
|
|
41
|
+
if (args.additionalData) {
|
|
42
|
+
Object.assign(userData, args.additionalData);
|
|
43
|
+
}
|
|
44
|
+
const result = await pb.collection(collection).create(userData);
|
|
45
|
+
return createJsonResponse(result);
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw handlePocketBaseError("create user", error);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type PocketBase from "pocketbase";
|
|
2
|
+
import type { ToolHandler } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a new collection in PocketBase
|
|
5
|
+
*/
|
|
6
|
+
export declare function createCreateCollectionHandler(pb: PocketBase): ToolHandler;
|
|
7
|
+
/**
|
|
8
|
+
* Delete a collection from PocketBase
|
|
9
|
+
*/
|
|
10
|
+
export declare function createDeleteCollectionHandler(pb: PocketBase): ToolHandler;
|
|
11
|
+
/**
|
|
12
|
+
* Get schema details for a collection
|
|
13
|
+
*/
|
|
14
|
+
export declare function createGetCollectionSchemaHandler(pb: PocketBase): ToolHandler;
|
|
15
|
+
/**
|
|
16
|
+
* List all collections
|
|
17
|
+
*/
|
|
18
|
+
export declare function createListCollectionsHandler(pb: PocketBase): ToolHandler;
|
|
19
|
+
/**
|
|
20
|
+
* Truncate all records from a collection
|
|
21
|
+
*/
|
|
22
|
+
export declare function createTruncateCollectionHandler(pb: PocketBase): ToolHandler;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { handlePocketBaseError } from "../../utils/errors.js";
|
|
2
|
+
import { createJsonResponse } from "../../utils/response.js";
|
|
3
|
+
/**
|
|
4
|
+
* Create a new collection in PocketBase
|
|
5
|
+
*/
|
|
6
|
+
export function createCreateCollectionHandler(pb) {
|
|
7
|
+
return async (args) => {
|
|
8
|
+
try {
|
|
9
|
+
const result = await pb.collections.create({
|
|
10
|
+
...args,
|
|
11
|
+
});
|
|
12
|
+
return createJsonResponse(result);
|
|
13
|
+
}
|
|
14
|
+
catch (error) {
|
|
15
|
+
throw handlePocketBaseError("create collection", error);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Delete a collection from PocketBase
|
|
21
|
+
*/
|
|
22
|
+
export function createDeleteCollectionHandler(pb) {
|
|
23
|
+
return async (args) => {
|
|
24
|
+
try {
|
|
25
|
+
await pb.collections.delete(args.collection);
|
|
26
|
+
return createJsonResponse({
|
|
27
|
+
success: true,
|
|
28
|
+
message: `Collection '${args.collection}' deleted successfully`
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
throw handlePocketBaseError("delete collection", error);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Get schema details for a collection
|
|
38
|
+
*/
|
|
39
|
+
export function createGetCollectionSchemaHandler(pb) {
|
|
40
|
+
return async (args) => {
|
|
41
|
+
try {
|
|
42
|
+
const result = await pb.collections.getOne(args.collection);
|
|
43
|
+
return createJsonResponse(result);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw handlePocketBaseError("get collection schema", error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* List all collections
|
|
52
|
+
*/
|
|
53
|
+
export function createListCollectionsHandler(pb) {
|
|
54
|
+
return async (args) => {
|
|
55
|
+
try {
|
|
56
|
+
const result = await pb.collections.getFullList({
|
|
57
|
+
sort: args.sort || "-created"
|
|
58
|
+
});
|
|
59
|
+
return createJsonResponse(result);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw handlePocketBaseError("list collections", error);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Truncate all records from a collection
|
|
68
|
+
*/
|
|
69
|
+
export function createTruncateCollectionHandler(pb) {
|
|
70
|
+
return async (args) => {
|
|
71
|
+
try {
|
|
72
|
+
await pb.collections.truncate(args.collection);
|
|
73
|
+
return createJsonResponse({
|
|
74
|
+
success: true,
|
|
75
|
+
message: `All records in collection '${args.collection}' have been deleted`
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw handlePocketBaseError("truncate collection", error);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type PocketBase from 'pocketbase';
|
|
2
|
+
import type { ToolHandler } from '../../types/index.js';
|
|
3
|
+
export declare function createUploadFileHandler(pb: PocketBase): ToolHandler;
|
|
4
|
+
export declare function createDownloadFileHandler(pb: PocketBase): ToolHandler;
|
|
5
|
+
export declare function createUploadFileFromUrlHandler(pb: PocketBase): ToolHandler;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { createJsonResponse } from '../../utils/response.js';
|
|
2
|
+
import { handlePocketBaseError } from '../../utils/errors.js';
|
|
3
|
+
export function createUploadFileHandler(pb) {
|
|
4
|
+
return async (args) => {
|
|
5
|
+
try {
|
|
6
|
+
const { collection, recordId, fileField, fileContent, fileName } = args;
|
|
7
|
+
// Create a Blob from the file content string
|
|
8
|
+
const blob = new Blob([fileContent]);
|
|
9
|
+
// Create a FormData object and append the file
|
|
10
|
+
const formData = new FormData();
|
|
11
|
+
formData.append(fileField, blob, fileName);
|
|
12
|
+
// Update the record with the file
|
|
13
|
+
const record = await pb.collection(collection).update(recordId, formData);
|
|
14
|
+
return createJsonResponse({
|
|
15
|
+
success: true,
|
|
16
|
+
message: `File '${fileName}' uploaded successfully to record ${recordId}`,
|
|
17
|
+
record
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
throw handlePocketBaseError("upload file", error);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function createDownloadFileHandler(pb) {
|
|
26
|
+
return async (args) => {
|
|
27
|
+
try {
|
|
28
|
+
const { collection, recordId, fileField } = args;
|
|
29
|
+
// Fetch the record to get the filename associated with the file field
|
|
30
|
+
const record = await pb.collection(collection).getOne(recordId);
|
|
31
|
+
// Ensure the file field exists and has a value
|
|
32
|
+
const fileName = record[fileField];
|
|
33
|
+
if (!fileName || typeof fileName !== 'string') {
|
|
34
|
+
throw new Error(`File field '${fileField}' not found or empty on record ${recordId}`);
|
|
35
|
+
}
|
|
36
|
+
// Get the file URL using the filename from the record
|
|
37
|
+
const fileUrl = pb.files.getUrl(record, fileName);
|
|
38
|
+
return createJsonResponse({
|
|
39
|
+
success: true,
|
|
40
|
+
fileName,
|
|
41
|
+
fileUrl,
|
|
42
|
+
message: `Download URL for ${fileName}: ${fileUrl}`
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
throw handlePocketBaseError("get download URL", error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export function createUploadFileFromUrlHandler(pb) {
|
|
51
|
+
return async (args) => {
|
|
52
|
+
try {
|
|
53
|
+
const { collection, recordId, fileField, url, fileName } = args;
|
|
54
|
+
// Download the file from the URL
|
|
55
|
+
const response = await fetch(url);
|
|
56
|
+
if (!response.ok) {
|
|
57
|
+
throw new Error(`Failed to download file from URL: ${response.status} ${response.statusText}`);
|
|
58
|
+
}
|
|
59
|
+
// Get the file content as ArrayBuffer
|
|
60
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
61
|
+
// Determine the filename
|
|
62
|
+
let finalFileName = fileName;
|
|
63
|
+
if (!finalFileName) {
|
|
64
|
+
// Extract filename from URL
|
|
65
|
+
const urlPath = new URL(url).pathname;
|
|
66
|
+
finalFileName = urlPath.split('/').pop() || 'downloaded-file';
|
|
67
|
+
// If no extension, try to get from Content-Type header
|
|
68
|
+
if (!finalFileName.includes('.')) {
|
|
69
|
+
const contentType = response.headers.get('content-type');
|
|
70
|
+
if (contentType) {
|
|
71
|
+
const extension = getExtensionFromMimeType(contentType);
|
|
72
|
+
if (extension) {
|
|
73
|
+
finalFileName += `.${extension}`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Create a Blob from the downloaded content
|
|
79
|
+
const blob = new Blob([arrayBuffer]);
|
|
80
|
+
// Create a FormData object and append the file
|
|
81
|
+
const formData = new FormData();
|
|
82
|
+
formData.append(fileField, blob, finalFileName);
|
|
83
|
+
// Update the record with the file
|
|
84
|
+
const record = await pb.collection(collection).update(recordId, formData);
|
|
85
|
+
return createJsonResponse({
|
|
86
|
+
success: true,
|
|
87
|
+
message: `File '${finalFileName}' uploaded successfully from URL to record ${recordId}`,
|
|
88
|
+
fileName: finalFileName,
|
|
89
|
+
sourceUrl: url,
|
|
90
|
+
record
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
throw handlePocketBaseError("upload file from URL", error);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Helper function to get file extension from MIME type
|
|
99
|
+
function getExtensionFromMimeType(mimeType) {
|
|
100
|
+
const mimeToExt = {
|
|
101
|
+
'image/jpeg': 'jpg',
|
|
102
|
+
'image/png': 'png',
|
|
103
|
+
'image/gif': 'gif',
|
|
104
|
+
'image/webp': 'webp',
|
|
105
|
+
'image/svg+xml': 'svg',
|
|
106
|
+
'text/plain': 'txt',
|
|
107
|
+
'text/html': 'html',
|
|
108
|
+
'text/css': 'css',
|
|
109
|
+
'text/javascript': 'js',
|
|
110
|
+
'application/json': 'json',
|
|
111
|
+
'application/pdf': 'pdf',
|
|
112
|
+
'application/zip': 'zip',
|
|
113
|
+
'application/x-zip-compressed': 'zip',
|
|
114
|
+
'application/msword': 'doc',
|
|
115
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
|
|
116
|
+
'application/vnd.ms-excel': 'xls',
|
|
117
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
|
|
118
|
+
'video/mp4': 'mp4',
|
|
119
|
+
'video/webm': 'webm',
|
|
120
|
+
'audio/mpeg': 'mp3',
|
|
121
|
+
'audio/wav': 'wav'
|
|
122
|
+
};
|
|
123
|
+
return mimeToExt[mimeType.toLowerCase()] || null;
|
|
124
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type PocketBase from "pocketbase";
|
|
2
|
+
import type { ToolHandler } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generate a PocketBase schema based on TypeScript interfaces or database diagram
|
|
5
|
+
*/
|
|
6
|
+
export declare function createGeneratePbSchemaHandler(pb: PocketBase): ToolHandler;
|
|
7
|
+
/**
|
|
8
|
+
* Generate TypeScript interfaces from PocketBase collections
|
|
9
|
+
*/
|
|
10
|
+
export declare function createGenerateTypescriptInterfacesHandler(pb: PocketBase): ToolHandler;
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { handlePocketBaseError } from "../../utils/errors.js";
|
|
2
|
+
import { createTextResponse, createJsonResponse } from "../../utils/response.js";
|
|
3
|
+
import { analyzeTypeScriptForSchema, toPascalCase, mapPocketBaseTypeToTypeScript } from "../../utils/typescript.js";
|
|
4
|
+
/**
|
|
5
|
+
* Generate a PocketBase schema based on TypeScript interfaces or database diagram
|
|
6
|
+
*/
|
|
7
|
+
export function createGeneratePbSchemaHandler(pb) {
|
|
8
|
+
return async (args) => {
|
|
9
|
+
try {
|
|
10
|
+
const { sourceCode, options = {} } = args;
|
|
11
|
+
const includeAuth = options.includeAuthentication ?? true;
|
|
12
|
+
const includeTimestamps = options.includeTimestamps ?? true;
|
|
13
|
+
// Analyze TypeScript source code
|
|
14
|
+
const interfaces = analyzeTypeScriptForSchema(sourceCode, options);
|
|
15
|
+
if (interfaces.length === 0) {
|
|
16
|
+
return createTextResponse("No TypeScript interfaces found in the provided source code.");
|
|
17
|
+
}
|
|
18
|
+
const collections = [];
|
|
19
|
+
// Generate collections from interfaces
|
|
20
|
+
for (const iface of interfaces) {
|
|
21
|
+
const fields = [];
|
|
22
|
+
// Add standard fields if requested
|
|
23
|
+
if (includeTimestamps) {
|
|
24
|
+
fields.push({
|
|
25
|
+
name: "created",
|
|
26
|
+
type: "autodate",
|
|
27
|
+
required: false,
|
|
28
|
+
system: true,
|
|
29
|
+
onCreate: true,
|
|
30
|
+
onUpdate: false,
|
|
31
|
+
}, {
|
|
32
|
+
name: "updated",
|
|
33
|
+
type: "autodate",
|
|
34
|
+
required: false,
|
|
35
|
+
system: true,
|
|
36
|
+
onCreate: true,
|
|
37
|
+
onUpdate: true,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// Convert interface properties to PocketBase fields
|
|
41
|
+
for (const prop of iface.properties) {
|
|
42
|
+
const field = {
|
|
43
|
+
name: prop.name,
|
|
44
|
+
type: mapTypeScriptToPocketBase(prop.type),
|
|
45
|
+
required: !prop.optional,
|
|
46
|
+
};
|
|
47
|
+
// Add type-specific options
|
|
48
|
+
if (field.type === "text" && prop.type.includes("email")) {
|
|
49
|
+
field.type = "email";
|
|
50
|
+
}
|
|
51
|
+
else if (field.type === "text" && prop.type.includes("url")) {
|
|
52
|
+
field.type = "url";
|
|
53
|
+
}
|
|
54
|
+
else if (field.type === "text" && prop.type.includes("Date")) {
|
|
55
|
+
field.type = "date";
|
|
56
|
+
}
|
|
57
|
+
fields.push(field);
|
|
58
|
+
}
|
|
59
|
+
const collection = {
|
|
60
|
+
name: iface.name.toLowerCase(),
|
|
61
|
+
type: "base",
|
|
62
|
+
fields,
|
|
63
|
+
listRule: "",
|
|
64
|
+
viewRule: "",
|
|
65
|
+
createRule: "",
|
|
66
|
+
updateRule: "",
|
|
67
|
+
deleteRule: "",
|
|
68
|
+
};
|
|
69
|
+
collections.push(collection);
|
|
70
|
+
}
|
|
71
|
+
// Add authentication collection if requested
|
|
72
|
+
if (includeAuth) {
|
|
73
|
+
const authCollection = {
|
|
74
|
+
name: "users",
|
|
75
|
+
type: "auth",
|
|
76
|
+
fields: [
|
|
77
|
+
{
|
|
78
|
+
name: "name",
|
|
79
|
+
type: "text",
|
|
80
|
+
required: false,
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "avatar",
|
|
84
|
+
type: "file",
|
|
85
|
+
required: false,
|
|
86
|
+
options: {
|
|
87
|
+
maxSelect: 1,
|
|
88
|
+
maxSize: 5242880,
|
|
89
|
+
mimeTypes: ["image/jpeg", "image/png", "image/svg+xml", "image/gif"],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
listRule: "id = @request.auth.id",
|
|
94
|
+
viewRule: "id = @request.auth.id",
|
|
95
|
+
createRule: "",
|
|
96
|
+
updateRule: "id = @request.auth.id",
|
|
97
|
+
deleteRule: "id = @request.auth.id",
|
|
98
|
+
};
|
|
99
|
+
collections.unshift(authCollection);
|
|
100
|
+
}
|
|
101
|
+
const schema = {
|
|
102
|
+
collections,
|
|
103
|
+
generatedAt: new Date().toISOString(),
|
|
104
|
+
source: "TypeScript interfaces",
|
|
105
|
+
};
|
|
106
|
+
return createJsonResponse(schema);
|
|
107
|
+
}
|
|
108
|
+
catch (error) {
|
|
109
|
+
throw handlePocketBaseError("generate PocketBase schema", error);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Generate TypeScript interfaces from PocketBase collections
|
|
115
|
+
*/
|
|
116
|
+
export function createGenerateTypescriptInterfacesHandler(pb) {
|
|
117
|
+
return async (args = {}) => {
|
|
118
|
+
try {
|
|
119
|
+
const { collections: targetCollections = [], options = {} } = args;
|
|
120
|
+
const includeRelations = options.includeRelations ?? true;
|
|
121
|
+
// Get all collections or specific ones
|
|
122
|
+
const allCollections = await pb.collections.getFullList();
|
|
123
|
+
const collectionsToProcess = targetCollections.length > 0
|
|
124
|
+
? allCollections.filter(c => targetCollections.includes(c.name))
|
|
125
|
+
: allCollections;
|
|
126
|
+
const interfaces = [];
|
|
127
|
+
// Generate base record interface
|
|
128
|
+
interfaces.push("// Base record interface");
|
|
129
|
+
interfaces.push("export interface BaseRecord {");
|
|
130
|
+
interfaces.push(" id: string;");
|
|
131
|
+
interfaces.push(" created: string;");
|
|
132
|
+
interfaces.push(" updated: string;");
|
|
133
|
+
interfaces.push("}");
|
|
134
|
+
interfaces.push("");
|
|
135
|
+
// Generate interfaces for each collection
|
|
136
|
+
for (const collection of collectionsToProcess) {
|
|
137
|
+
const interfaceName = toPascalCase(collection.name);
|
|
138
|
+
const fields = collection.fields || [];
|
|
139
|
+
interfaces.push(`// ${collection.name} collection`);
|
|
140
|
+
interfaces.push(`export interface ${interfaceName} extends BaseRecord {`);
|
|
141
|
+
for (const field of fields) {
|
|
142
|
+
if (field.system)
|
|
143
|
+
continue; // Skip system fields
|
|
144
|
+
const fieldType = mapPocketBaseTypeToTypeScript(field.type, field);
|
|
145
|
+
const optional = !field.required ? "?" : "";
|
|
146
|
+
if (includeRelations && field.type === "relation") {
|
|
147
|
+
const relatedCollection = field.options?.collectionId;
|
|
148
|
+
if (relatedCollection) {
|
|
149
|
+
const relatedCollectionName = allCollections.find(c => c.id === relatedCollection)?.name;
|
|
150
|
+
if (relatedCollectionName) {
|
|
151
|
+
const relatedInterface = toPascalCase(relatedCollectionName);
|
|
152
|
+
const isMultiple = field.options?.maxSelect !== 1;
|
|
153
|
+
interfaces.push(` ${field.name}${optional}: ${isMultiple ? `${relatedInterface}[]` : relatedInterface};`);
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
interfaces.push(` ${field.name}${optional}: ${fieldType};`);
|
|
159
|
+
}
|
|
160
|
+
interfaces.push("}");
|
|
161
|
+
interfaces.push("");
|
|
162
|
+
}
|
|
163
|
+
// Add utility types
|
|
164
|
+
interfaces.push("// Utility types");
|
|
165
|
+
interfaces.push("export type RecordId = string;");
|
|
166
|
+
interfaces.push("export type RecordTimestamp = string;");
|
|
167
|
+
interfaces.push("");
|
|
168
|
+
// Add collection names type
|
|
169
|
+
const collectionNames = collectionsToProcess.map(c => `"${c.name}"`).join(" | ");
|
|
170
|
+
interfaces.push(`export type CollectionName = ${collectionNames};`);
|
|
171
|
+
const result = interfaces.join("\n");
|
|
172
|
+
return createTextResponse(result);
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
throw handlePocketBaseError("generate TypeScript interfaces", error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Helper function to map TypeScript types to PocketBase field types
|
|
181
|
+
*/
|
|
182
|
+
function mapTypeScriptToPocketBase(tsType) {
|
|
183
|
+
const type = tsType.toLowerCase();
|
|
184
|
+
if (type.includes("string"))
|
|
185
|
+
return "text";
|
|
186
|
+
if (type.includes("number"))
|
|
187
|
+
return "number";
|
|
188
|
+
if (type.includes("boolean"))
|
|
189
|
+
return "bool";
|
|
190
|
+
if (type.includes("date"))
|
|
191
|
+
return "date";
|
|
192
|
+
if (type.includes("email"))
|
|
193
|
+
return "email";
|
|
194
|
+
if (type.includes("url"))
|
|
195
|
+
return "url";
|
|
196
|
+
if (type.includes("[]"))
|
|
197
|
+
return "json";
|
|
198
|
+
if (type.includes("object") || type.includes("{"))
|
|
199
|
+
return "json";
|
|
200
|
+
return "text"; // Default fallback
|
|
201
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool handlers registry - exports all handler creation functions
|
|
3
|
+
*/
|
|
4
|
+
export { createCreateCollectionHandler, createDeleteCollectionHandler, createGetCollectionSchemaHandler, createListCollectionsHandler, createTruncateCollectionHandler, } from "./collection.js";
|
|
5
|
+
export { createCreateRecordHandler, createListRecordsHandler, createUpdateRecordHandler, createDeleteRecordHandler, } from "./record.js";
|
|
6
|
+
export { createAuthenticateUserHandler, createCreateUserHandler, } from "./auth.js";
|
|
7
|
+
export { createAnalyzeCollectionDataHandler, createQueryCollectionHandler, } from "./analysis.js";
|
|
8
|
+
export { createMigrateCollectionHandler, createBackupDatabaseHandler, createImportDataHandler, createManageIndexesHandler, } from "./migration.js";
|
|
9
|
+
export { createGeneratePbSchemaHandler, createGenerateTypescriptInterfacesHandler, } from "./generation.js";
|
|
10
|
+
export { createUploadFileHandler, createDownloadFileHandler, createUploadFileFromUrlHandler } from './file.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tool handlers registry - exports all handler creation functions
|
|
3
|
+
*/
|
|
4
|
+
// Collection handlers
|
|
5
|
+
export { createCreateCollectionHandler, createDeleteCollectionHandler, createGetCollectionSchemaHandler, createListCollectionsHandler, createTruncateCollectionHandler, } from "./collection.js";
|
|
6
|
+
// Record handlers
|
|
7
|
+
export { createCreateRecordHandler, createListRecordsHandler, createUpdateRecordHandler, createDeleteRecordHandler, } from "./record.js";
|
|
8
|
+
// Auth handlers
|
|
9
|
+
export { createAuthenticateUserHandler, createCreateUserHandler, } from "./auth.js";
|
|
10
|
+
// Analysis handlers
|
|
11
|
+
export { createAnalyzeCollectionDataHandler, createQueryCollectionHandler, } from "./analysis.js";
|
|
12
|
+
// Migration handlers
|
|
13
|
+
export { createMigrateCollectionHandler, createBackupDatabaseHandler, createImportDataHandler, createManageIndexesHandler, } from "./migration.js";
|
|
14
|
+
// Generation handlers
|
|
15
|
+
export { createGeneratePbSchemaHandler, createGenerateTypescriptInterfacesHandler, } from "./generation.js";
|
|
16
|
+
// File handlers
|
|
17
|
+
export { createUploadFileHandler, createDownloadFileHandler, createUploadFileFromUrlHandler } from './file.js';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type PocketBase from "pocketbase";
|
|
2
|
+
import type { ToolHandler } from "../../types/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Migrate collection schema with data preservation
|
|
5
|
+
*/
|
|
6
|
+
export declare function createMigrateCollectionHandler(pb: PocketBase): ToolHandler;
|
|
7
|
+
/**
|
|
8
|
+
* Create a backup of the PocketBase database
|
|
9
|
+
*/
|
|
10
|
+
export declare function createBackupDatabaseHandler(pb: PocketBase): ToolHandler;
|
|
11
|
+
/**
|
|
12
|
+
* Import data into a collection
|
|
13
|
+
*/
|
|
14
|
+
export declare function createImportDataHandler(pb: PocketBase): ToolHandler;
|
|
15
|
+
/**
|
|
16
|
+
* Manage collection indexes
|
|
17
|
+
*/
|
|
18
|
+
export declare function createManageIndexesHandler(pb: PocketBase): ToolHandler;
|