fixes
This commit is contained in:
86
src/index.ts
86
src/index.ts
@@ -401,6 +401,7 @@ class AppwriteMCPServer {
|
||||
properties: {
|
||||
userId: { type: "string", description: "Unique user ID (optional)" },
|
||||
email: { type: "string", description: "User email" },
|
||||
phone: { type: "string", description: "User phone number in international format (optional, e.g., '+1234567890')" },
|
||||
password: { type: "string", description: "User password" },
|
||||
name: { type: "string", description: "User name (optional)" }
|
||||
},
|
||||
@@ -891,6 +892,7 @@ class AppwriteMCPServer {
|
||||
properties: {
|
||||
userId: { type: "string", description: "User ID (optional)" },
|
||||
email: { type: "string", description: "User email" },
|
||||
phone: { type: "string", description: "User phone number (optional)" },
|
||||
password: { type: "string", description: "User password" },
|
||||
name: { type: "string", description: "User name (optional)" }
|
||||
},
|
||||
@@ -1533,6 +1535,17 @@ class AppwriteMCPServer {
|
||||
const { databaseId, collectionId, documentId, data, permissions } = args;
|
||||
const docId = documentId || ID.unique();
|
||||
|
||||
// Validate document against collection schema
|
||||
try {
|
||||
const validation = await this.validateDocumentData(databaseId, collectionId, data);
|
||||
if (!validation.isValid) {
|
||||
throw new Error(`Document validation failed: ${validation.errors.join(', ')}`);
|
||||
}
|
||||
} catch (validationError) {
|
||||
// If validation fails, provide helpful error message
|
||||
throw new Error(`Schema validation error: ${validationError}. Use list_attributes to check collection schema.`);
|
||||
}
|
||||
|
||||
const document = await this.databases.createDocument(
|
||||
databaseId,
|
||||
collectionId,
|
||||
@@ -1629,10 +1642,10 @@ class AppwriteMCPServer {
|
||||
private async createUser(args: any) {
|
||||
if (!this.users) throw new Error("Users service not initialized");
|
||||
|
||||
const { userId, email, password, name } = args;
|
||||
const { userId, email, phone, password, name } = args;
|
||||
const uid = userId || ID.unique();
|
||||
|
||||
const user = await this.users.create(uid, email, password, name);
|
||||
const user = await this.users.create(uid, email, phone, password, name);
|
||||
|
||||
return {
|
||||
content: [
|
||||
@@ -2371,6 +2384,71 @@ ${attributes.attributes.map((attr: any) =>
|
||||
};
|
||||
}
|
||||
|
||||
// Helper method for createDocument validation
|
||||
private async validateDocumentData(databaseId: string, collectionId: string, documentData: any) {
|
||||
if (!this.databases) throw new Error("Databases not initialized");
|
||||
|
||||
// Get collection schema
|
||||
const attributes = await this.databases.listAttributes(databaseId, collectionId);
|
||||
const attributeMap = new Map(attributes.attributes.map((attr: any) => [attr.key, attr]));
|
||||
|
||||
const errors: string[] = [];
|
||||
|
||||
// Check required fields
|
||||
attributes.attributes.forEach((attr: any) => {
|
||||
if (attr.required && !(attr.key in documentData)) {
|
||||
errors.push(`Missing required field: ${attr.key} (${attr.type})`);
|
||||
}
|
||||
});
|
||||
|
||||
// Check field types and constraints
|
||||
Object.keys(documentData).forEach(key => {
|
||||
const attr = attributeMap.get(key);
|
||||
const value = documentData[key];
|
||||
|
||||
if (!attr) {
|
||||
errors.push(`Unknown field: ${key} (not in collection schema)`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Type validation
|
||||
switch (attr.type) {
|
||||
case 'string':
|
||||
if (typeof value !== 'string') {
|
||||
errors.push(`Field ${key}: expected string, got ${typeof value}`);
|
||||
} else if (attr.size && value.length > attr.size) {
|
||||
errors.push(`Field ${key}: string too long (${value.length} > ${attr.size})`);
|
||||
}
|
||||
break;
|
||||
case 'integer':
|
||||
if (!Number.isInteger(value)) {
|
||||
errors.push(`Field ${key}: expected integer, got ${typeof value}`);
|
||||
}
|
||||
break;
|
||||
case 'boolean':
|
||||
if (typeof value !== 'boolean') {
|
||||
errors.push(`Field ${key}: expected boolean, got ${typeof value}`);
|
||||
}
|
||||
break;
|
||||
case 'email':
|
||||
if (typeof value !== 'string' || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
|
||||
errors.push(`Field ${key}: invalid email format`);
|
||||
}
|
||||
break;
|
||||
case 'datetime':
|
||||
if (isNaN(Date.parse(value))) {
|
||||
errors.push(`Field ${key}: invalid datetime format`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
isValid: errors.length === 0,
|
||||
errors: errors
|
||||
};
|
||||
}
|
||||
|
||||
private async schemaMigration(args: any) {
|
||||
if (!this.databases) throw new Error("Databases not initialized");
|
||||
|
||||
@@ -3608,9 +3686,9 @@ For accurate usage tracking, consider:
|
||||
|
||||
for (const user of users) {
|
||||
try {
|
||||
const { userId, email, password, name } = user;
|
||||
const { userId, email, phone, password, name } = user;
|
||||
const uid = userId || ID.unique();
|
||||
const createdUser = await this.users.create(uid, email, password, name);
|
||||
const createdUser = await this.users.create(uid, email, phone, password, name);
|
||||
results.push(`✅ ${createdUser.email} (${createdUser.$id})`);
|
||||
} catch (error) {
|
||||
errors.push(`❌ ${user.email}: ${error}`);
|
||||
|
||||
Reference in New Issue
Block a user