appwrite-utils-cli 1.0.6 → 1.0.8

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.
@@ -0,0 +1,366 @@
1
+ import { converterFunctions, tryAwaitWithRetry } from "appwrite-utils";
2
+ import { Client, Databases, Storage, Users, Functions, Query, } from "node-appwrite";
3
+ import { InputFile } from "node-appwrite/file";
4
+ import { MessageFormatter } from "../shared/messageFormatter.js";
5
+ import { ProgressManager } from "../shared/progressManager.js";
6
+ import { getClient } from "../utils/getClientFromConfig.js";
7
+ import { transferDatabaseLocalToLocal, transferDatabaseLocalToRemote, transferStorageLocalToLocal, transferStorageLocalToRemote, transferUsersLocalToRemote } from "./transfer.js";
8
+ import { deployLocalFunction } from "../functions/deployments.js";
9
+ import { listFunctions, downloadLatestFunctionDeployment } from "../functions/methods.js";
10
+ import pLimit from "p-limit";
11
+ import chalk from "chalk";
12
+ import { join } from "node:path";
13
+ import fs from "node:fs";
14
+ export class ComprehensiveTransfer {
15
+ options;
16
+ sourceClient;
17
+ targetClient;
18
+ sourceUsers;
19
+ targetUsers;
20
+ sourceDatabases;
21
+ targetDatabases;
22
+ sourceStorage;
23
+ targetStorage;
24
+ sourceFunctions;
25
+ targetFunctions;
26
+ limit;
27
+ userLimit;
28
+ fileLimit;
29
+ results;
30
+ startTime;
31
+ tempDir;
32
+ constructor(options) {
33
+ this.options = options;
34
+ this.sourceClient = getClient(options.sourceEndpoint, options.sourceProject, options.sourceKey);
35
+ this.targetClient = getClient(options.targetEndpoint, options.targetProject, options.targetKey);
36
+ this.sourceUsers = new Users(this.sourceClient);
37
+ this.targetUsers = new Users(this.targetClient);
38
+ this.sourceDatabases = new Databases(this.sourceClient);
39
+ this.targetDatabases = new Databases(this.targetClient);
40
+ this.sourceStorage = new Storage(this.sourceClient);
41
+ this.targetStorage = new Storage(this.targetClient);
42
+ this.sourceFunctions = new Functions(this.sourceClient);
43
+ this.targetFunctions = new Functions(this.targetClient);
44
+ const baseLimit = options.concurrencyLimit || 10;
45
+ this.limit = pLimit(baseLimit);
46
+ // Different rate limits for different operations to prevent API throttling
47
+ // Users: Half speed (more sensitive operations)
48
+ // Files: Quarter speed (most bandwidth intensive)
49
+ this.userLimit = pLimit(Math.max(1, Math.floor(baseLimit / 2)));
50
+ this.fileLimit = pLimit(Math.max(1, Math.floor(baseLimit / 4)));
51
+ this.results = {
52
+ users: { transferred: 0, skipped: 0, failed: 0 },
53
+ databases: { transferred: 0, skipped: 0, failed: 0 },
54
+ buckets: { transferred: 0, skipped: 0, failed: 0 },
55
+ functions: { transferred: 0, skipped: 0, failed: 0 },
56
+ totalTime: 0,
57
+ };
58
+ this.startTime = Date.now();
59
+ this.tempDir = join(process.cwd(), ".appwrite-transfer-temp");
60
+ }
61
+ async execute() {
62
+ try {
63
+ MessageFormatter.info("Starting comprehensive transfer", { prefix: "Transfer" });
64
+ if (this.options.dryRun) {
65
+ MessageFormatter.info("DRY RUN MODE - No actual changes will be made", { prefix: "Transfer" });
66
+ }
67
+ // Show rate limiting configuration
68
+ const baseLimit = this.options.concurrencyLimit || 10;
69
+ const userLimit = Math.max(1, Math.floor(baseLimit / 2));
70
+ const fileLimit = Math.max(1, Math.floor(baseLimit / 4));
71
+ MessageFormatter.info(`Rate limits: General=${baseLimit}, Users=${userLimit}, Files=${fileLimit}`, { prefix: "Transfer" });
72
+ // Ensure temp directory exists
73
+ if (!fs.existsSync(this.tempDir)) {
74
+ fs.mkdirSync(this.tempDir, { recursive: true });
75
+ }
76
+ // Execute transfers in the correct order
77
+ if (this.options.transferUsers !== false) {
78
+ await this.transferAllUsers();
79
+ }
80
+ if (this.options.transferDatabases !== false) {
81
+ await this.transferAllDatabases();
82
+ }
83
+ if (this.options.transferBuckets !== false) {
84
+ await this.transferAllBuckets();
85
+ }
86
+ if (this.options.transferFunctions !== false) {
87
+ await this.transferAllFunctions();
88
+ }
89
+ this.results.totalTime = Date.now() - this.startTime;
90
+ this.printSummary();
91
+ return this.results;
92
+ }
93
+ catch (error) {
94
+ MessageFormatter.error("Comprehensive transfer failed", error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
95
+ throw error;
96
+ }
97
+ finally {
98
+ // Clean up temp directory
99
+ if (fs.existsSync(this.tempDir)) {
100
+ fs.rmSync(this.tempDir, { recursive: true, force: true });
101
+ }
102
+ }
103
+ }
104
+ async transferAllUsers() {
105
+ MessageFormatter.info("Starting user transfer phase", { prefix: "Transfer" });
106
+ if (this.options.dryRun) {
107
+ const usersList = await this.sourceUsers.list([Query.limit(1)]);
108
+ MessageFormatter.info(`DRY RUN: Would transfer ${usersList.total} users`, { prefix: "Transfer" });
109
+ return;
110
+ }
111
+ try {
112
+ // Use the existing user transfer function
113
+ // Note: The rate limiting is handled at the API level, not per-user
114
+ // since user operations are already sequential in the existing implementation
115
+ await transferUsersLocalToRemote(this.sourceUsers, this.options.targetEndpoint, this.options.targetProject, this.options.targetKey);
116
+ // Get actual count for results
117
+ const usersList = await this.sourceUsers.list([Query.limit(1)]);
118
+ this.results.users.transferred = usersList.total;
119
+ MessageFormatter.success(`User transfer completed`, { prefix: "Transfer" });
120
+ }
121
+ catch (error) {
122
+ MessageFormatter.error("User transfer failed", error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
123
+ this.results.users.failed = 1;
124
+ }
125
+ }
126
+ async transferAllDatabases() {
127
+ MessageFormatter.info("Starting database transfer phase", { prefix: "Transfer" });
128
+ try {
129
+ const sourceDatabases = await this.sourceDatabases.list();
130
+ const targetDatabases = await this.targetDatabases.list();
131
+ if (this.options.dryRun) {
132
+ MessageFormatter.info(`DRY RUN: Would transfer ${sourceDatabases.databases.length} databases`, { prefix: "Transfer" });
133
+ return;
134
+ }
135
+ const transferTasks = sourceDatabases.databases.map(db => this.limit(async () => {
136
+ try {
137
+ // Check if database exists in target
138
+ const existingDb = targetDatabases.databases.find(tdb => tdb.$id === db.$id);
139
+ if (!existingDb) {
140
+ // Create database in target
141
+ await this.targetDatabases.create(db.$id, db.name, db.enabled);
142
+ MessageFormatter.success(`Created database: ${db.name}`, { prefix: "Transfer" });
143
+ }
144
+ // Transfer database content
145
+ await transferDatabaseLocalToRemote(this.sourceDatabases, this.options.targetEndpoint, this.options.targetProject, this.options.targetKey, db.$id, db.$id);
146
+ this.results.databases.transferred++;
147
+ MessageFormatter.success(`Database ${db.name} transferred successfully`, { prefix: "Transfer" });
148
+ }
149
+ catch (error) {
150
+ MessageFormatter.error(`Database ${db.name} transfer failed`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
151
+ this.results.databases.failed++;
152
+ }
153
+ }));
154
+ await Promise.all(transferTasks);
155
+ MessageFormatter.success("Database transfer phase completed", { prefix: "Transfer" });
156
+ }
157
+ catch (error) {
158
+ MessageFormatter.error("Database transfer phase failed", error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
159
+ }
160
+ }
161
+ async transferAllBuckets() {
162
+ MessageFormatter.info("Starting bucket transfer phase", { prefix: "Transfer" });
163
+ try {
164
+ const sourceBuckets = await this.sourceStorage.listBuckets();
165
+ const targetBuckets = await this.targetStorage.listBuckets();
166
+ if (this.options.dryRun) {
167
+ let totalFiles = 0;
168
+ for (const bucket of sourceBuckets.buckets) {
169
+ const files = await this.sourceStorage.listFiles(bucket.$id, [Query.limit(1)]);
170
+ totalFiles += files.total;
171
+ }
172
+ MessageFormatter.info(`DRY RUN: Would transfer ${sourceBuckets.buckets.length} buckets with ${totalFiles} files`, { prefix: "Transfer" });
173
+ return;
174
+ }
175
+ const transferTasks = sourceBuckets.buckets.map(bucket => this.limit(async () => {
176
+ try {
177
+ // Check if bucket exists in target
178
+ const existingBucket = targetBuckets.buckets.find(tb => tb.$id === bucket.$id);
179
+ if (!existingBucket) {
180
+ // Create bucket in target
181
+ await this.targetStorage.createBucket(bucket.$id, bucket.name, bucket.$permissions, bucket.fileSecurity, bucket.enabled, bucket.maximumFileSize, bucket.allowedFileExtensions, bucket.compression, bucket.encryption, bucket.antivirus);
182
+ MessageFormatter.success(`Created bucket: ${bucket.name}`, { prefix: "Transfer" });
183
+ }
184
+ // Transfer bucket files with enhanced validation
185
+ await this.transferBucketFiles(bucket.$id, bucket.$id);
186
+ this.results.buckets.transferred++;
187
+ MessageFormatter.success(`Bucket ${bucket.name} transferred successfully`, { prefix: "Transfer" });
188
+ }
189
+ catch (error) {
190
+ MessageFormatter.error(`Bucket ${bucket.name} transfer failed`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
191
+ this.results.buckets.failed++;
192
+ }
193
+ }));
194
+ await Promise.all(transferTasks);
195
+ MessageFormatter.success("Bucket transfer phase completed", { prefix: "Transfer" });
196
+ }
197
+ catch (error) {
198
+ MessageFormatter.error("Bucket transfer phase failed", error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
199
+ }
200
+ }
201
+ async transferBucketFiles(sourceBucketId, targetBucketId) {
202
+ let lastFileId;
203
+ let transferredFiles = 0;
204
+ while (true) {
205
+ const queries = [Query.limit(50)]; // Smaller batch size for better rate limiting
206
+ if (lastFileId) {
207
+ queries.push(Query.cursorAfter(lastFileId));
208
+ }
209
+ const files = await this.sourceStorage.listFiles(sourceBucketId, queries);
210
+ if (files.files.length === 0)
211
+ break;
212
+ // Process files with rate limiting
213
+ const fileTasks = files.files.map(file => this.fileLimit(async () => {
214
+ try {
215
+ // Check if file already exists
216
+ try {
217
+ await this.targetStorage.getFile(targetBucketId, file.$id);
218
+ MessageFormatter.info(`File ${file.name} already exists, skipping`, { prefix: "Transfer" });
219
+ return;
220
+ }
221
+ catch (error) {
222
+ // File doesn't exist, proceed with transfer
223
+ }
224
+ // Download file with validation
225
+ const fileData = await this.validateAndDownloadFile(sourceBucketId, file.$id);
226
+ if (!fileData) {
227
+ MessageFormatter.warning(`File ${file.name} failed validation, skipping`, { prefix: "Transfer" });
228
+ return;
229
+ }
230
+ // Upload file to target
231
+ const fileToCreate = InputFile.fromBuffer(new Uint8Array(fileData), file.name);
232
+ await this.targetStorage.createFile(targetBucketId, file.$id, fileToCreate, file.$permissions);
233
+ transferredFiles++;
234
+ MessageFormatter.success(`Transferred file: ${file.name}`, { prefix: "Transfer" });
235
+ }
236
+ catch (error) {
237
+ MessageFormatter.error(`Failed to transfer file ${file.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
238
+ }
239
+ }));
240
+ await Promise.all(fileTasks);
241
+ if (files.files.length < 50)
242
+ break;
243
+ lastFileId = files.files[files.files.length - 1].$id;
244
+ }
245
+ MessageFormatter.info(`Transferred ${transferredFiles} files from bucket ${sourceBucketId}`, { prefix: "Transfer" });
246
+ }
247
+ async validateAndDownloadFile(bucketId, fileId) {
248
+ let attempts = 3;
249
+ while (attempts > 0) {
250
+ try {
251
+ const fileData = await this.sourceStorage.getFileDownload(bucketId, fileId);
252
+ // Basic validation - ensure file is not empty and not too large
253
+ if (fileData.byteLength === 0) {
254
+ MessageFormatter.warning(`File ${fileId} is empty`, { prefix: "Transfer" });
255
+ return null;
256
+ }
257
+ if (fileData.byteLength > 50 * 1024 * 1024) { // 50MB limit
258
+ MessageFormatter.warning(`File ${fileId} is too large (${fileData.byteLength} bytes)`, { prefix: "Transfer" });
259
+ return null;
260
+ }
261
+ return fileData;
262
+ }
263
+ catch (error) {
264
+ attempts--;
265
+ MessageFormatter.warning(`Error downloading file ${fileId}, attempts left: ${attempts}`, { prefix: "Transfer" });
266
+ if (attempts === 0) {
267
+ MessageFormatter.error(`Failed to download file ${fileId} after all attempts`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
268
+ return null;
269
+ }
270
+ // Wait before retry
271
+ await new Promise(resolve => setTimeout(resolve, 1000 * (4 - attempts)));
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ async transferAllFunctions() {
277
+ MessageFormatter.info("Starting function transfer phase", { prefix: "Transfer" });
278
+ try {
279
+ const sourceFunctions = await listFunctions(this.sourceClient, [Query.limit(1000)]);
280
+ const targetFunctions = await listFunctions(this.targetClient, [Query.limit(1000)]);
281
+ if (this.options.dryRun) {
282
+ MessageFormatter.info(`DRY RUN: Would transfer ${sourceFunctions.functions.length} functions`, { prefix: "Transfer" });
283
+ return;
284
+ }
285
+ const transferTasks = sourceFunctions.functions.map(func => this.limit(async () => {
286
+ try {
287
+ // Check if function exists in target
288
+ const existingFunc = targetFunctions.functions.find(tf => tf.$id === func.$id);
289
+ if (existingFunc) {
290
+ MessageFormatter.info(`Function ${func.name} already exists, skipping creation`, { prefix: "Transfer" });
291
+ this.results.functions.skipped++;
292
+ return;
293
+ }
294
+ // Download function from source
295
+ const functionPath = await this.downloadFunction(func);
296
+ if (!functionPath) {
297
+ MessageFormatter.error(`Failed to download function ${func.name}`, undefined, { prefix: "Transfer" });
298
+ this.results.functions.failed++;
299
+ return;
300
+ }
301
+ // Deploy function to target
302
+ const functionConfig = {
303
+ $id: func.$id,
304
+ name: func.name,
305
+ runtime: func.runtime,
306
+ execute: func.execute,
307
+ events: func.events,
308
+ enabled: func.enabled,
309
+ logging: func.logging,
310
+ entrypoint: func.entrypoint,
311
+ commands: func.commands,
312
+ scopes: func.scopes,
313
+ timeout: func.timeout,
314
+ schedule: func.schedule,
315
+ installationId: func.installationId,
316
+ providerRepositoryId: func.providerRepositoryId,
317
+ providerBranch: func.providerBranch,
318
+ providerSilentMode: func.providerSilentMode,
319
+ providerRootDirectory: func.providerRootDirectory,
320
+ specification: func.specification,
321
+ dirPath: functionPath,
322
+ };
323
+ await deployLocalFunction(this.targetClient, func.name, functionConfig);
324
+ this.results.functions.transferred++;
325
+ MessageFormatter.success(`Function ${func.name} transferred successfully`, { prefix: "Transfer" });
326
+ }
327
+ catch (error) {
328
+ MessageFormatter.error(`Function ${func.name} transfer failed`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
329
+ this.results.functions.failed++;
330
+ }
331
+ }));
332
+ await Promise.all(transferTasks);
333
+ MessageFormatter.success("Function transfer phase completed", { prefix: "Transfer" });
334
+ }
335
+ catch (error) {
336
+ MessageFormatter.error("Function transfer phase failed", error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
337
+ }
338
+ }
339
+ async downloadFunction(func) {
340
+ try {
341
+ const { path } = await downloadLatestFunctionDeployment(this.sourceClient, func.$id, this.tempDir);
342
+ return path;
343
+ }
344
+ catch (error) {
345
+ MessageFormatter.error(`Failed to download function ${func.name}`, error instanceof Error ? error : new Error(String(error)), { prefix: "Transfer" });
346
+ return null;
347
+ }
348
+ }
349
+ printSummary() {
350
+ const duration = Math.round((Date.now() - this.startTime) / 1000);
351
+ MessageFormatter.info("=== COMPREHENSIVE TRANSFER SUMMARY ===", { prefix: "Transfer" });
352
+ MessageFormatter.info(`Total Time: ${duration}s`, { prefix: "Transfer" });
353
+ MessageFormatter.info(`Users: ${this.results.users.transferred} transferred, ${this.results.users.skipped} skipped, ${this.results.users.failed} failed`, { prefix: "Transfer" });
354
+ MessageFormatter.info(`Databases: ${this.results.databases.transferred} transferred, ${this.results.databases.skipped} skipped, ${this.results.databases.failed} failed`, { prefix: "Transfer" });
355
+ MessageFormatter.info(`Buckets: ${this.results.buckets.transferred} transferred, ${this.results.buckets.skipped} skipped, ${this.results.buckets.failed} failed`, { prefix: "Transfer" });
356
+ MessageFormatter.info(`Functions: ${this.results.functions.transferred} transferred, ${this.results.functions.skipped} skipped, ${this.results.functions.failed} failed`, { prefix: "Transfer" });
357
+ const totalTransferred = this.results.users.transferred + this.results.databases.transferred + this.results.buckets.transferred + this.results.functions.transferred;
358
+ const totalFailed = this.results.users.failed + this.results.databases.failed + this.results.buckets.failed + this.results.functions.failed;
359
+ if (totalFailed === 0) {
360
+ MessageFormatter.success(`All ${totalTransferred} items transferred successfully!`, { prefix: "Transfer" });
361
+ }
362
+ else {
363
+ MessageFormatter.warning(`${totalTransferred} items transferred, ${totalFailed} failed`, { prefix: "Transfer" });
364
+ }
365
+ }
366
+ }
@@ -195,8 +195,8 @@ export declare const YamlImportConfigSchema: z.ZodObject<{
195
195
  }>>;
196
196
  }, "strip", z.ZodTypeAny, {
197
197
  batchSize: number;
198
- skipValidation: boolean;
199
198
  dryRun: boolean;
199
+ skipValidation: boolean;
200
200
  continueOnError: boolean;
201
201
  updateMapping?: {
202
202
  targetField: string;
@@ -204,8 +204,8 @@ export declare const YamlImportConfigSchema: z.ZodObject<{
204
204
  } | undefined;
205
205
  }, {
206
206
  batchSize?: number | undefined;
207
- skipValidation?: boolean | undefined;
208
207
  dryRun?: boolean | undefined;
208
+ skipValidation?: boolean | undefined;
209
209
  continueOnError?: boolean | undefined;
210
210
  updateMapping?: {
211
211
  targetField: string;
@@ -215,8 +215,8 @@ export declare const YamlImportConfigSchema: z.ZodObject<{
215
215
  }, "strip", z.ZodTypeAny, {
216
216
  options: {
217
217
  batchSize: number;
218
- skipValidation: boolean;
219
218
  dryRun: boolean;
219
+ skipValidation: boolean;
220
220
  continueOnError: boolean;
221
221
  updateMapping?: {
222
222
  targetField: string;
@@ -304,8 +304,8 @@ export declare const YamlImportConfigSchema: z.ZodObject<{
304
304
  };
305
305
  options?: {
306
306
  batchSize?: number | undefined;
307
- skipValidation?: boolean | undefined;
308
307
  dryRun?: boolean | undefined;
308
+ skipValidation?: boolean | undefined;
309
309
  continueOnError?: boolean | undefined;
310
310
  updateMapping?: {
311
311
  targetField: string;
@@ -7,6 +7,7 @@ import chalk from "chalk";
7
7
  import { findYamlConfig, loadYamlConfig } from "../config/yamlConfig.js";
8
8
  import yaml from "js-yaml";
9
9
  import { z } from "zod";
10
+ import { MessageFormatter } from "../shared/messageFormatter.js";
10
11
  /**
11
12
  * Recursively searches for configuration files starting from the given directory.
12
13
  * Priority: 1) YAML configs in .appwrite directories, 2) appwriteConfig.ts files in subdirectories
@@ -79,7 +80,6 @@ const findAppwriteConfigTS = (dir, depth = 0) => {
79
80
  // First check current directory for appwriteConfig.ts
80
81
  for (const entry of entries) {
81
82
  if (entry.isFile() && entry.name === "appwriteConfig.ts") {
82
- console.log(`Found appwriteConfig.ts at: ${path.join(dir, entry.name)}`);
83
83
  return path.join(dir, entry.name);
84
84
  }
85
85
  }
@@ -94,7 +94,6 @@ const findAppwriteConfigTS = (dir, depth = 0) => {
94
94
  }
95
95
  catch (error) {
96
96
  // Ignore directory access errors
97
- console.log(`Error accessing directory ${dir}:`, error);
98
97
  }
99
98
  return null;
100
99
  };
@@ -134,7 +133,6 @@ export const loadConfigWithPath = async (configDir) => {
134
133
  if (fs.existsSync(configPath)) {
135
134
  const unregister = register(); // Register tsx enhancement
136
135
  try {
137
- console.log(`Loading TypeScript config from: ${configPath}`);
138
136
  const configUrl = pathToFileURL(configPath).href;
139
137
  const configModule = (await import(configUrl));
140
138
  config = configModule.default?.default || configModule.default || configModule;
@@ -214,7 +212,6 @@ export const loadConfig = async (configDir) => {
214
212
  // First try to find and load YAML config
215
213
  const yamlConfigPath = findYamlConfig(configDir);
216
214
  if (yamlConfigPath) {
217
- console.log(`Loading YAML config from: ${yamlConfigPath}`);
218
215
  config = await loadYamlConfig(yamlConfigPath);
219
216
  actualConfigPath = yamlConfigPath;
220
217
  }
@@ -225,7 +222,6 @@ export const loadConfig = async (configDir) => {
225
222
  if (fs.existsSync(configPath)) {
226
223
  const unregister = register(); // Register tsx enhancement
227
224
  try {
228
- console.log(`Loading TypeScript config from: ${configPath}`);
229
225
  const configUrl = pathToFileURL(configPath).href;
230
226
  const configModule = (await import(configUrl));
231
227
  config = configModule.default?.default || configModule.default || configModule;
@@ -300,6 +296,10 @@ export const loadConfig = async (configDir) => {
300
296
  else {
301
297
  config.collections = config.collections || [];
302
298
  }
299
+ // Log successful config loading
300
+ if (actualConfigPath) {
301
+ MessageFormatter.success(`Loaded config from: ${actualConfigPath}`, { prefix: "Config" });
302
+ }
303
303
  return config;
304
304
  };
305
305
  export const findFunctionsDir = (dir, depth = 0) => {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "appwrite-utils-cli",
3
3
  "description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
4
- "version": "1.0.6",
4
+ "version": "1.0.8",
5
5
  "main": "src/main.ts",
6
6
  "type": "module",
7
7
  "repository": {
@@ -256,18 +256,14 @@ export const findYamlConfig = (startDir: string): string | null => {
256
256
  path.join(startDir, "appwrite.yml"),
257
257
  ];
258
258
 
259
- console.log(`DEBUG: Checking YAML paths in ${startDir}:`);
260
259
  for (const configPath of possiblePaths) {
261
- console.log(` - ${configPath}: ${fs.existsSync(configPath)}`);
262
260
  if (fs.existsSync(configPath)) {
263
261
  return configPath;
264
262
  }
265
263
  }
266
264
 
267
265
  // Recursively search subdirectories for .appwrite folders
268
- console.log(`DEBUG: Starting recursive search from ${startDir}`);
269
266
  const yamlConfigInSubdirs = findYamlConfigRecursive(startDir);
270
- console.log(`DEBUG: Recursive search result: ${yamlConfigInSubdirs}`);
271
267
  if (yamlConfigInSubdirs) {
272
268
  return yamlConfigInSubdirs;
273
269
  }
@@ -336,27 +332,22 @@ const shouldIgnoreDirectory = (dirName: string): boolean => {
336
332
  const findYamlConfigRecursive = (dir: string, depth: number = 0): string | null => {
337
333
  // Limit search depth to prevent infinite recursion
338
334
  if (depth > 5) {
339
- console.log(`DEBUG: Stopping search at depth ${depth} in ${dir}`);
340
335
  return null;
341
336
  }
342
337
 
343
338
  if (shouldIgnoreDirectory(path.basename(dir))) {
344
- console.log(`DEBUG: Ignoring directory ${dir}`);
345
339
  return null;
346
340
  }
347
341
 
348
342
  try {
349
343
  const entries = fs.readdirSync(dir, { withFileTypes: true });
350
- console.log(`DEBUG: Searching directory ${dir} at depth ${depth}, found ${entries.length} entries`);
351
344
 
352
345
  for (const entry of entries) {
353
346
  if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
354
347
  const fullPath = path.join(dir, entry.name);
355
- console.log(`DEBUG: Checking subdirectory: ${fullPath}`);
356
348
 
357
349
  // Check if this is an .appwrite directory
358
350
  if (entry.name === ".appwrite") {
359
- console.log(`DEBUG: Found .appwrite directory at ${fullPath}`);
360
351
  const configPaths = [
361
352
  path.join(fullPath, "appwriteConfig.yaml"),
362
353
  path.join(fullPath, "appwriteConfig.yml"),