@njdamstra/appwrite-utils-cli 1.8.9 → 1.10.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.
- package/CHANGELOG.md +16 -0
- package/CONFIG_TODO.md +1189 -0
- package/SELECTION_DIALOGS.md +146 -0
- package/SERVICE_IMPLEMENTATION_REPORT.md +462 -0
- package/dist/adapters/index.d.ts +7 -8
- package/dist/adapters/index.js +7 -9
- package/dist/backups/operations/bucketBackup.js +2 -2
- package/dist/backups/operations/collectionBackup.d.ts +1 -1
- package/dist/backups/operations/collectionBackup.js +3 -3
- package/dist/backups/operations/comprehensiveBackup.d.ts +1 -1
- package/dist/backups/operations/comprehensiveBackup.js +2 -2
- package/dist/backups/tracking/centralizedTracking.d.ts +1 -1
- package/dist/backups/tracking/centralizedTracking.js +2 -2
- package/dist/cli/commands/configCommands.js +51 -7
- package/dist/cli/commands/databaseCommands.d.ts +1 -0
- package/dist/cli/commands/databaseCommands.js +119 -9
- package/dist/cli/commands/functionCommands.js +3 -3
- package/dist/cli/commands/importFileCommands.d.ts +7 -0
- package/dist/cli/commands/importFileCommands.js +674 -0
- package/dist/cli/commands/schemaCommands.js +3 -3
- package/dist/cli/commands/storageCommands.js +2 -3
- package/dist/cli/commands/transferCommands.js +3 -5
- package/dist/collections/attributes.d.ts +1 -1
- package/dist/collections/attributes.js +85 -35
- package/dist/collections/indexes.js +2 -4
- package/dist/collections/methods.d.ts +1 -1
- package/dist/collections/methods.js +111 -192
- package/dist/collections/tableOperations.d.ts +1 -0
- package/dist/collections/tableOperations.js +90 -23
- package/dist/collections/transferOperations.d.ts +1 -1
- package/dist/collections/transferOperations.js +3 -4
- package/dist/collections/wipeOperations.d.ts +4 -3
- package/dist/collections/wipeOperations.js +112 -39
- package/dist/databases/methods.js +2 -2
- package/dist/databases/setup.js +2 -2
- package/dist/examples/yamlTerminologyExample.js +2 -2
- package/dist/functions/deployments.d.ts +1 -1
- package/dist/functions/deployments.js +5 -5
- package/dist/functions/fnConfigDiscovery.js +2 -2
- package/dist/functions/methods.js +16 -4
- package/dist/init.js +1 -1
- package/dist/interactiveCLI.d.ts +6 -1
- package/dist/interactiveCLI.js +64 -10
- package/dist/main.js +130 -177
- package/dist/migrations/afterImportActions.js +2 -3
- package/dist/migrations/appwriteToX.d.ts +97 -1
- package/dist/migrations/appwriteToX.js +9 -7
- package/dist/migrations/comprehensiveTransfer.js +3 -5
- package/dist/migrations/dataLoader.d.ts +194 -2
- package/dist/migrations/dataLoader.js +2 -5
- package/dist/migrations/importController.js +3 -4
- package/dist/migrations/importDataActions.js +3 -3
- package/dist/migrations/relationships.js +1 -2
- package/dist/migrations/services/DataTransformationService.js +2 -2
- package/dist/migrations/services/FileHandlerService.js +1 -1
- package/dist/migrations/services/ImportOrchestrator.js +4 -4
- package/dist/migrations/services/RateLimitManager.js +1 -1
- package/dist/migrations/services/RelationshipResolver.js +1 -1
- package/dist/migrations/services/UserMappingService.js +1 -1
- package/dist/migrations/services/ValidationService.js +1 -1
- package/dist/migrations/transfer.d.ts +8 -4
- package/dist/migrations/transfer.js +106 -55
- package/dist/migrations/yaml/YamlImportConfigLoader.js +1 -1
- package/dist/migrations/yaml/YamlImportIntegration.js +2 -2
- package/dist/migrations/yaml/generateImportSchemas.js +1 -1
- package/dist/setupCommands.d.ts +1 -1
- package/dist/setupCommands.js +5 -6
- package/dist/setupController.js +1 -1
- package/dist/shared/backupTracking.d.ts +1 -1
- package/dist/shared/backupTracking.js +2 -2
- package/dist/shared/confirmationDialogs.js +1 -1
- package/dist/shared/migrationHelpers.d.ts +1 -1
- package/dist/shared/migrationHelpers.js +3 -3
- package/dist/shared/operationQueue.d.ts +1 -1
- package/dist/shared/operationQueue.js +2 -3
- package/dist/shared/operationsTable.d.ts +1 -1
- package/dist/shared/operationsTable.js +2 -2
- package/dist/shared/progressManager.js +1 -1
- package/dist/shared/selectionDialogs.js +9 -8
- package/dist/storage/methods.js +4 -4
- package/dist/storage/schemas.d.ts +386 -2
- package/dist/tables/indexManager.d.ts +65 -0
- package/dist/tables/indexManager.js +294 -0
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/dist/users/methods.js +2 -3
- package/dist/utils/configMigration.js +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +1 -1
- package/dist/utils/loadConfigs.d.ts +2 -2
- package/dist/utils/loadConfigs.js +6 -7
- package/dist/utils/setupFiles.js +5 -7
- package/dist/utilsController.d.ts +15 -8
- package/dist/utilsController.js +57 -28
- package/package.json +8 -4
- package/src/adapters/index.ts +8 -34
- package/src/backups/operations/bucketBackup.ts +2 -2
- package/src/backups/operations/collectionBackup.ts +4 -4
- package/src/backups/operations/comprehensiveBackup.ts +3 -3
- package/src/backups/tracking/centralizedTracking.ts +3 -3
- package/src/cli/commands/configCommands.ts +72 -8
- package/src/cli/commands/databaseCommands.ts +161 -9
- package/src/cli/commands/functionCommands.ts +4 -3
- package/src/cli/commands/importFileCommands.ts +815 -0
- package/src/cli/commands/schemaCommands.ts +3 -3
- package/src/cli/commands/storageCommands.ts +2 -3
- package/src/cli/commands/transferCommands.ts +3 -6
- package/src/collections/attributes.ts +155 -39
- package/src/collections/indexes.ts +5 -7
- package/src/collections/methods.ts +115 -150
- package/src/collections/tableOperations.ts +92 -21
- package/src/collections/transferOperations.ts +4 -5
- package/src/collections/wipeOperations.ts +154 -51
- package/src/databases/methods.ts +2 -2
- package/src/databases/setup.ts +2 -2
- package/src/examples/yamlTerminologyExample.ts +2 -2
- package/src/functions/deployments.ts +6 -5
- package/src/functions/fnConfigDiscovery.ts +2 -2
- package/src/functions/methods.ts +19 -6
- package/src/init.ts +1 -1
- package/src/interactiveCLI.ts +78 -13
- package/src/main.ts +143 -287
- package/src/migrations/afterImportActions.ts +2 -3
- package/src/migrations/appwriteToX.ts +12 -8
- package/src/migrations/comprehensiveTransfer.ts +6 -6
- package/src/migrations/dataLoader.ts +2 -5
- package/src/migrations/importController.ts +3 -4
- package/src/migrations/importDataActions.ts +3 -3
- package/src/migrations/relationships.ts +1 -2
- package/src/migrations/services/DataTransformationService.ts +2 -2
- package/src/migrations/services/FileHandlerService.ts +1 -1
- package/src/migrations/services/ImportOrchestrator.ts +4 -4
- package/src/migrations/services/RateLimitManager.ts +1 -1
- package/src/migrations/services/RelationshipResolver.ts +1 -1
- package/src/migrations/services/UserMappingService.ts +1 -1
- package/src/migrations/services/ValidationService.ts +1 -1
- package/src/migrations/transfer.ts +126 -83
- package/src/migrations/yaml/YamlImportConfigLoader.ts +1 -1
- package/src/migrations/yaml/YamlImportIntegration.ts +2 -2
- package/src/migrations/yaml/generateImportSchemas.ts +1 -1
- package/src/setupCommands.ts +5 -6
- package/src/setupController.ts +1 -1
- package/src/shared/backupTracking.ts +3 -3
- package/src/shared/confirmationDialogs.ts +1 -1
- package/src/shared/migrationHelpers.ts +4 -4
- package/src/shared/operationQueue.ts +3 -4
- package/src/shared/operationsTable.ts +3 -3
- package/src/shared/progressManager.ts +1 -1
- package/src/shared/selectionDialogs.ts +9 -8
- package/src/storage/methods.ts +4 -4
- package/src/tables/indexManager.ts +409 -0
- package/src/types.ts +2 -2
- package/src/users/methods.ts +2 -3
- package/src/utils/configMigration.ts +1 -1
- package/src/utils/index.ts +1 -1
- package/src/utils/loadConfigs.ts +15 -7
- package/src/utils/setupFiles.ts +5 -7
- package/src/utilsController.ts +86 -32
- package/dist/adapters/AdapterFactory.d.ts +0 -94
- package/dist/adapters/AdapterFactory.js +0 -405
- package/dist/adapters/DatabaseAdapter.d.ts +0 -233
- package/dist/adapters/DatabaseAdapter.js +0 -50
- package/dist/adapters/LegacyAdapter.d.ts +0 -50
- package/dist/adapters/LegacyAdapter.js +0 -612
- package/dist/adapters/TablesDBAdapter.d.ts +0 -45
- package/dist/adapters/TablesDBAdapter.js +0 -571
- package/dist/config/ConfigManager.d.ts +0 -445
- package/dist/config/ConfigManager.js +0 -625
- package/dist/config/configMigration.d.ts +0 -87
- package/dist/config/configMigration.js +0 -390
- package/dist/config/configValidation.d.ts +0 -66
- package/dist/config/configValidation.js +0 -358
- package/dist/config/index.d.ts +0 -8
- package/dist/config/index.js +0 -7
- package/dist/config/services/ConfigDiscoveryService.d.ts +0 -126
- package/dist/config/services/ConfigDiscoveryService.js +0 -374
- package/dist/config/services/ConfigLoaderService.d.ts +0 -129
- package/dist/config/services/ConfigLoaderService.js +0 -540
- package/dist/config/services/ConfigMergeService.d.ts +0 -208
- package/dist/config/services/ConfigMergeService.js +0 -308
- package/dist/config/services/ConfigValidationService.d.ts +0 -214
- package/dist/config/services/ConfigValidationService.js +0 -310
- package/dist/config/services/SessionAuthService.d.ts +0 -225
- package/dist/config/services/SessionAuthService.js +0 -456
- package/dist/config/services/__tests__/ConfigMergeService.test.d.ts +0 -1
- package/dist/config/services/__tests__/ConfigMergeService.test.js +0 -271
- package/dist/config/services/index.d.ts +0 -13
- package/dist/config/services/index.js +0 -10
- package/dist/config/yamlConfig.d.ts +0 -722
- package/dist/config/yamlConfig.js +0 -702
- package/dist/functions/pathResolution.d.ts +0 -37
- package/dist/functions/pathResolution.js +0 -185
- package/dist/shared/attributeMapper.d.ts +0 -20
- package/dist/shared/attributeMapper.js +0 -203
- package/dist/shared/errorUtils.d.ts +0 -54
- package/dist/shared/errorUtils.js +0 -95
- package/dist/shared/functionManager.d.ts +0 -48
- package/dist/shared/functionManager.js +0 -336
- package/dist/shared/indexManager.d.ts +0 -24
- package/dist/shared/indexManager.js +0 -151
- package/dist/shared/jsonSchemaGenerator.d.ts +0 -50
- package/dist/shared/jsonSchemaGenerator.js +0 -290
- package/dist/shared/logging.d.ts +0 -61
- package/dist/shared/logging.js +0 -116
- package/dist/shared/messageFormatter.d.ts +0 -39
- package/dist/shared/messageFormatter.js +0 -162
- package/dist/shared/pydanticModelGenerator.d.ts +0 -17
- package/dist/shared/pydanticModelGenerator.js +0 -615
- package/dist/shared/schemaGenerator.d.ts +0 -40
- package/dist/shared/schemaGenerator.js +0 -556
- package/dist/utils/ClientFactory.d.ts +0 -87
- package/dist/utils/ClientFactory.js +0 -212
- package/dist/utils/configDiscovery.d.ts +0 -78
- package/dist/utils/configDiscovery.js +0 -472
- package/dist/utils/constantsGenerator.d.ts +0 -31
- package/dist/utils/constantsGenerator.js +0 -321
- package/dist/utils/dataConverters.d.ts +0 -46
- package/dist/utils/dataConverters.js +0 -139
- package/dist/utils/directoryUtils.d.ts +0 -22
- package/dist/utils/directoryUtils.js +0 -59
- package/dist/utils/getClientFromConfig.d.ts +0 -39
- package/dist/utils/getClientFromConfig.js +0 -199
- package/dist/utils/helperFunctions.d.ts +0 -63
- package/dist/utils/helperFunctions.js +0 -156
- package/dist/utils/pathResolvers.d.ts +0 -53
- package/dist/utils/pathResolvers.js +0 -72
- package/dist/utils/projectConfig.d.ts +0 -119
- package/dist/utils/projectConfig.js +0 -171
- package/dist/utils/retryFailedPromises.d.ts +0 -2
- package/dist/utils/retryFailedPromises.js +0 -23
- package/dist/utils/sessionAuth.d.ts +0 -48
- package/dist/utils/sessionAuth.js +0 -164
- package/dist/utils/typeGuards.d.ts +0 -35
- package/dist/utils/typeGuards.js +0 -57
- package/dist/utils/validationRules.d.ts +0 -43
- package/dist/utils/validationRules.js +0 -42
- package/dist/utils/versionDetection.d.ts +0 -58
- package/dist/utils/versionDetection.js +0 -251
- package/dist/utils/yamlConverter.d.ts +0 -100
- package/dist/utils/yamlConverter.js +0 -428
- package/dist/utils/yamlLoader.d.ts +0 -70
- package/dist/utils/yamlLoader.js +0 -267
- package/src/adapters/AdapterFactory.ts +0 -510
- package/src/adapters/DatabaseAdapter.ts +0 -306
- package/src/adapters/LegacyAdapter.ts +0 -841
- package/src/adapters/TablesDBAdapter.ts +0 -773
- package/src/config/ConfigManager.ts +0 -808
- package/src/config/README.md +0 -274
- package/src/config/configMigration.ts +0 -575
- package/src/config/configValidation.ts +0 -445
- package/src/config/index.ts +0 -10
- package/src/config/services/ConfigDiscoveryService.ts +0 -463
- package/src/config/services/ConfigLoaderService.ts +0 -740
- package/src/config/services/ConfigMergeService.ts +0 -388
- package/src/config/services/ConfigValidationService.ts +0 -394
- package/src/config/services/SessionAuthService.ts +0 -565
- package/src/config/services/__tests__/ConfigMergeService.test.ts +0 -351
- package/src/config/services/index.ts +0 -29
- package/src/config/yamlConfig.ts +0 -761
- package/src/functions/pathResolution.ts +0 -227
- package/src/shared/attributeMapper.ts +0 -229
- package/src/shared/errorUtils.ts +0 -110
- package/src/shared/functionManager.ts +0 -525
- package/src/shared/indexManager.ts +0 -254
- package/src/shared/jsonSchemaGenerator.ts +0 -383
- package/src/shared/logging.ts +0 -149
- package/src/shared/messageFormatter.ts +0 -208
- package/src/shared/pydanticModelGenerator.ts +0 -618
- package/src/shared/schemaGenerator.ts +0 -644
- package/src/utils/ClientFactory.ts +0 -240
- package/src/utils/configDiscovery.ts +0 -557
- package/src/utils/constantsGenerator.ts +0 -369
- package/src/utils/dataConverters.ts +0 -159
- package/src/utils/directoryUtils.ts +0 -61
- package/src/utils/getClientFromConfig.ts +0 -257
- package/src/utils/helperFunctions.ts +0 -228
- package/src/utils/pathResolvers.ts +0 -81
- package/src/utils/projectConfig.ts +0 -299
- package/src/utils/retryFailedPromises.ts +0 -29
- package/src/utils/sessionAuth.ts +0 -230
- package/src/utils/typeGuards.ts +0 -65
- package/src/utils/validationRules.ts +0 -88
- package/src/utils/versionDetection.ts +0 -292
- package/src/utils/yamlConverter.ts +0 -542
- package/src/utils/yamlLoader.ts +0 -371
|
@@ -3,12 +3,11 @@ import {
|
|
|
3
3
|
Query,
|
|
4
4
|
type Models,
|
|
5
5
|
} from "node-appwrite";
|
|
6
|
-
import type { DatabaseAdapter } from "
|
|
7
|
-
import { tryAwaitWithRetry } from "
|
|
8
|
-
import { MessageFormatter } from "
|
|
6
|
+
import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
|
|
7
|
+
import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
|
|
8
|
+
import { MessageFormatter, isRetryableError, isCriticalError } from "@njdamstra/appwrite-utils-helpers";
|
|
9
9
|
import { ProgressManager } from "../shared/progressManager.js";
|
|
10
|
-
import {
|
|
11
|
-
import { delay } from "../utils/helperFunctions.js";
|
|
10
|
+
import { delay } from "@njdamstra/appwrite-utils-helpers";
|
|
12
11
|
import { chunk } from "es-toolkit";
|
|
13
12
|
import pLimit from "p-limit";
|
|
14
13
|
import { fetchAllCollections } from "./methods.js";
|
|
@@ -239,8 +238,9 @@ export const wipeAllTables = async (
|
|
|
239
238
|
};
|
|
240
239
|
|
|
241
240
|
/**
|
|
242
|
-
* Optimized deletion of all rows from a table
|
|
243
|
-
* Uses
|
|
241
|
+
* Optimized deletion of all rows from a table.
|
|
242
|
+
* Uses bulk deletion when possible, but falls back to individual row deletion
|
|
243
|
+
* for tables with relationship columns (bulk delete not supported for those).
|
|
244
244
|
*/
|
|
245
245
|
export const wipeTableRows = async (
|
|
246
246
|
adapter: DatabaseAdapter,
|
|
@@ -248,76 +248,179 @@ export const wipeTableRows = async (
|
|
|
248
248
|
tableId: string
|
|
249
249
|
): Promise<void> => {
|
|
250
250
|
try {
|
|
251
|
-
// Check if bulk
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
new Error("bulkDeleteRows not available"),
|
|
256
|
-
{ prefix: "Wipe" }
|
|
257
|
-
);
|
|
258
|
-
throw new Error("Bulk deletion required for wipe operations");
|
|
259
|
-
}
|
|
251
|
+
// Check if the table has relationship columns — bulk delete is not supported for those
|
|
252
|
+
const tableInfo = await adapter.getTable({ databaseId, tableId });
|
|
253
|
+
const columns: any[] = (tableInfo.data as any)?.columns || [];
|
|
254
|
+
const hasRelationships = columns.some((col: any) => col.type === "relationship");
|
|
260
255
|
|
|
261
|
-
const DELETE_BATCH_SIZE = 250;
|
|
256
|
+
const DELETE_BATCH_SIZE = 250;
|
|
262
257
|
let totalDeleted = 0;
|
|
263
258
|
let hasMoreRows = true;
|
|
264
259
|
|
|
265
|
-
MessageFormatter.info("Starting optimized table row deletion...", { prefix: "Wipe" });
|
|
266
|
-
|
|
267
260
|
const progress = ProgressManager.create(
|
|
268
261
|
`delete-${tableId}`,
|
|
269
|
-
1,
|
|
262
|
+
1,
|
|
270
263
|
{ title: "Deleting table rows" }
|
|
271
264
|
);
|
|
272
265
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
266
|
+
if (hasRelationships) {
|
|
267
|
+
// ── Relationship table: fetch rows then delete individually ──
|
|
268
|
+
MessageFormatter.info(
|
|
269
|
+
"Table has relationship columns — using individual row deletion (bulk delete not supported)",
|
|
270
|
+
{ prefix: "Wipe" }
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
const FETCH_BATCH_SIZE = 1000;
|
|
274
|
+
const MAX_CONCURRENT_DELETES = 25;
|
|
275
|
+
const limit = pLimit(MAX_CONCURRENT_DELETES);
|
|
276
|
+
|
|
277
|
+
// Pipeline: prefetch the first batch, then overlap fetch+delete
|
|
278
|
+
let pendingRows: any[] = [];
|
|
279
|
+
let totalDiscovered = 0;
|
|
280
|
+
|
|
281
|
+
// Fetch helper — always fetches from the top since we're deleting everything
|
|
282
|
+
const fetchBatch = async (): Promise<any[]> => {
|
|
283
|
+
const queries: any[] = [Query.limit(FETCH_BATCH_SIZE)];
|
|
284
|
+
const response = await tryAwaitWithRetry(async () =>
|
|
285
|
+
adapter.listRows({ databaseId, tableId, queries })
|
|
283
286
|
);
|
|
287
|
+
return (response as any).rows || (response as any).data || [];
|
|
288
|
+
};
|
|
284
289
|
|
|
285
|
-
|
|
290
|
+
// Kick off the first fetch
|
|
291
|
+
let nextFetchPromise: Promise<any[]> | null = fetchBatch();
|
|
286
292
|
|
|
287
|
-
|
|
293
|
+
while (hasMoreRows) {
|
|
294
|
+
// Await the prefetched batch
|
|
295
|
+
const rows = nextFetchPromise ? await nextFetchPromise : [];
|
|
296
|
+
nextFetchPromise = null;
|
|
297
|
+
|
|
298
|
+
if (rows.length === 0) {
|
|
288
299
|
hasMoreRows = false;
|
|
289
300
|
break;
|
|
290
301
|
}
|
|
291
302
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
303
|
+
totalDiscovered += rows.length;
|
|
304
|
+
const isLastBatch = rows.length < FETCH_BATCH_SIZE;
|
|
305
|
+
|
|
306
|
+
if (!isLastBatch) {
|
|
307
|
+
progress.setTotal(totalDiscovered + 1000);
|
|
308
|
+
} else {
|
|
309
|
+
progress.setTotal(totalDiscovered);
|
|
310
|
+
}
|
|
295
311
|
|
|
296
312
|
MessageFormatter.progress(
|
|
297
|
-
`
|
|
313
|
+
`Fetched ${rows.length} rows (${totalDiscovered} discovered, ${totalDeleted} deleted so far)`,
|
|
298
314
|
{ prefix: "Wipe" }
|
|
299
315
|
);
|
|
300
316
|
|
|
301
|
-
//
|
|
302
|
-
|
|
317
|
+
// Start deleting this batch — and prefetch the next one concurrently
|
|
318
|
+
// (only prefetch if we expect more rows)
|
|
319
|
+
if (!isLastBatch) {
|
|
320
|
+
// Wait a moment before prefetching so the first few deletes free up API capacity
|
|
321
|
+
nextFetchPromise = delay(200).then(() => fetchBatch());
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Delete each row with concurrency limit
|
|
325
|
+
const deletePromises = rows.map((row: any) =>
|
|
326
|
+
limit(async () => {
|
|
327
|
+
try {
|
|
328
|
+
await tryAwaitWithRetry(async () =>
|
|
329
|
+
adapter.deleteRow({ databaseId, tableId, id: row.$id })
|
|
330
|
+
);
|
|
331
|
+
totalDeleted++;
|
|
332
|
+
progress.update(totalDeleted);
|
|
333
|
+
} catch (error: any) {
|
|
334
|
+
const errorMessage = error.message || String(error);
|
|
335
|
+
if (errorMessage.includes("could not be found")) {
|
|
336
|
+
totalDeleted++;
|
|
337
|
+
progress.update(totalDeleted);
|
|
338
|
+
} else if (isCriticalError(errorMessage)) {
|
|
339
|
+
MessageFormatter.error(
|
|
340
|
+
`Critical error deleting row ${row.$id}: ${errorMessage}`,
|
|
341
|
+
error,
|
|
342
|
+
{ prefix: "Wipe" }
|
|
343
|
+
);
|
|
344
|
+
throw error;
|
|
345
|
+
} else {
|
|
346
|
+
MessageFormatter.error(
|
|
347
|
+
`Failed to delete row ${row.$id}: ${errorMessage}`,
|
|
348
|
+
error,
|
|
349
|
+
{ prefix: "Wipe" }
|
|
350
|
+
);
|
|
351
|
+
totalDeleted++;
|
|
352
|
+
progress.update(totalDeleted);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
);
|
|
303
357
|
|
|
304
|
-
|
|
305
|
-
const errorMessage = error.message || String(error);
|
|
358
|
+
await Promise.all(deletePromises);
|
|
306
359
|
|
|
307
|
-
if (
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
360
|
+
if (isLastBatch) {
|
|
361
|
+
hasMoreRows = false;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
await delay(10);
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
// ── No relationships: use fast bulk deletion ──
|
|
368
|
+
if (!adapter.bulkDeleteRows) {
|
|
369
|
+
MessageFormatter.error(
|
|
370
|
+
"Bulk deletion not available for this adapter - wipe operation not supported",
|
|
371
|
+
new Error("bulkDeleteRows not available"),
|
|
372
|
+
{ prefix: "Wipe" }
|
|
373
|
+
);
|
|
374
|
+
throw new Error("Bulk deletion required for wipe operations");
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
MessageFormatter.info("Starting optimized table row deletion...", { prefix: "Wipe" });
|
|
378
|
+
|
|
379
|
+
while (hasMoreRows) {
|
|
380
|
+
try {
|
|
381
|
+
const result = await tryAwaitWithRetry(async () =>
|
|
382
|
+
adapter.bulkDeleteRows!({
|
|
383
|
+
databaseId,
|
|
384
|
+
tableId,
|
|
385
|
+
rowIds: [],
|
|
386
|
+
batchSize: DELETE_BATCH_SIZE
|
|
387
|
+
})
|
|
312
388
|
);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
389
|
+
|
|
390
|
+
const deletedCount = (result as any).total || 0;
|
|
391
|
+
|
|
392
|
+
if (deletedCount === 0) {
|
|
393
|
+
hasMoreRows = false;
|
|
394
|
+
break;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
totalDeleted += deletedCount;
|
|
398
|
+
progress.setTotal(totalDeleted + 100);
|
|
399
|
+
progress.update(totalDeleted);
|
|
400
|
+
|
|
401
|
+
MessageFormatter.progress(
|
|
402
|
+
`Deleted ${deletedCount} rows (${totalDeleted} total so far)`,
|
|
318
403
|
{ prefix: "Wipe" }
|
|
319
404
|
);
|
|
320
|
-
|
|
405
|
+
|
|
406
|
+
await delay(10);
|
|
407
|
+
} catch (error: any) {
|
|
408
|
+
const errorMessage = error.message || String(error);
|
|
409
|
+
|
|
410
|
+
if (isCriticalError(errorMessage)) {
|
|
411
|
+
MessageFormatter.error(
|
|
412
|
+
`Critical error during bulk deletion: ${errorMessage}`,
|
|
413
|
+
error,
|
|
414
|
+
{ prefix: "Wipe" }
|
|
415
|
+
);
|
|
416
|
+
throw error;
|
|
417
|
+
} else {
|
|
418
|
+
MessageFormatter.error(
|
|
419
|
+
`Error during deletion batch: ${errorMessage}`,
|
|
420
|
+
error,
|
|
421
|
+
{ prefix: "Wipe" }
|
|
422
|
+
);
|
|
423
|
+
}
|
|
321
424
|
}
|
|
322
425
|
}
|
|
323
426
|
}
|
package/src/databases/methods.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Databases, Query, type Models } from "node-appwrite";
|
|
2
|
-
import { delay, tryAwaitWithRetry } from "
|
|
2
|
+
import { delay, tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
|
|
3
3
|
import { fetchAllCollections } from "../collections/methods.js";
|
|
4
|
-
import { MessageFormatter } from "
|
|
4
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
5
5
|
|
|
6
6
|
export const fetchAllDatabases = async (
|
|
7
7
|
database: Databases
|
package/src/databases/setup.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Databases, Query, type Models } from "node-appwrite";
|
|
2
|
-
import { tryAwaitWithRetry } from "
|
|
2
|
+
import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
|
|
3
3
|
import { type AppwriteConfig } from "@njdamstra/appwrite-utils";
|
|
4
4
|
import { ulid } from "ulidx";
|
|
5
|
-
import { MessageFormatter } from "
|
|
5
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
6
6
|
|
|
7
7
|
export const ensureDatabasesExist = async (config: AppwriteConfig, databasesToEnsure?: Models.Database[]) => {
|
|
8
8
|
if (!config.appwriteClient) {
|
|
@@ -17,8 +17,8 @@ import {
|
|
|
17
17
|
usesTableTerminology,
|
|
18
18
|
type YamlTerminologyConfig,
|
|
19
19
|
type YamlCollectionData
|
|
20
|
-
} from "
|
|
21
|
-
import { createYamlLoader } from "
|
|
20
|
+
} from "@njdamstra/appwrite-utils-helpers";
|
|
21
|
+
import { createYamlLoader } from "@njdamstra/appwrite-utils-helpers";
|
|
22
22
|
import { YamlImportIntegration } from "../migrations/yaml/YamlImportIntegration.js";
|
|
23
23
|
import { createImportSchemas } from "../migrations/yaml/generateImportSchemas.js";
|
|
24
24
|
import {
|
|
@@ -15,8 +15,8 @@ import {
|
|
|
15
15
|
updateFunctionSpecifications,
|
|
16
16
|
} from "./methods.js";
|
|
17
17
|
import ignore from "ignore";
|
|
18
|
-
import { MessageFormatter } from "
|
|
19
|
-
import { resolveFunctionDirectory, validateFunctionDirectory } from '
|
|
18
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
19
|
+
import { resolveFunctionDirectory, validateFunctionDirectory } from '@njdamstra/appwrite-utils-helpers';
|
|
20
20
|
|
|
21
21
|
export const deployFunction = async (
|
|
22
22
|
client: Client,
|
|
@@ -150,7 +150,8 @@ export const deployLocalFunction = async (
|
|
|
150
150
|
client: Client,
|
|
151
151
|
functionName: string,
|
|
152
152
|
functionConfig: AppwriteFunction,
|
|
153
|
-
functionPath?: string
|
|
153
|
+
functionPath?: string,
|
|
154
|
+
configDirPath?: string
|
|
154
155
|
) => {
|
|
155
156
|
let functionExists = true;
|
|
156
157
|
let functionThatExists: Models.Function;
|
|
@@ -160,10 +161,10 @@ export const deployLocalFunction = async (
|
|
|
160
161
|
functionExists = false;
|
|
161
162
|
}
|
|
162
163
|
|
|
163
|
-
const
|
|
164
|
+
const resolvedConfigDir = configDirPath ?? process.cwd();
|
|
164
165
|
const resolvedPath = resolveFunctionDirectory(
|
|
165
166
|
functionName,
|
|
166
|
-
|
|
167
|
+
resolvedConfigDir,
|
|
167
168
|
functionConfig.dirPath,
|
|
168
169
|
functionPath
|
|
169
170
|
);
|
|
@@ -3,8 +3,8 @@ import path from 'node:path';
|
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
4
|
import { homedir } from 'node:os';
|
|
5
5
|
import { AppwriteFunctionSchema, type AppwriteFunction } from '@njdamstra/appwrite-utils';
|
|
6
|
-
import { shouldIgnoreDirectory } from '
|
|
7
|
-
import { MessageFormatter } from '
|
|
6
|
+
import { shouldIgnoreDirectory } from '@njdamstra/appwrite-utils-helpers';
|
|
7
|
+
import { MessageFormatter } from '@njdamstra/appwrite-utils-helpers';
|
|
8
8
|
|
|
9
9
|
function findGitRoot(startDir: string): string {
|
|
10
10
|
let dir = path.resolve(startDir);
|
package/src/functions/methods.ts
CHANGED
|
@@ -13,23 +13,36 @@ import {
|
|
|
13
13
|
type FunctionScope,
|
|
14
14
|
type Specification,
|
|
15
15
|
type Runtime as AppwriteUtilsRuntime,
|
|
16
|
+
EventTypeSchema,
|
|
16
17
|
} from "@njdamstra/appwrite-utils";
|
|
17
18
|
import chalk from "chalk";
|
|
18
19
|
import { extract as extractTar } from "tar";
|
|
19
|
-
import { MessageFormatter } from "
|
|
20
|
-
import { expandTildePath, normalizeFunctionName } from
|
|
20
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
21
|
+
import { expandTildePath, normalizeFunctionName } from '@njdamstra/appwrite-utils-helpers';
|
|
21
22
|
|
|
22
23
|
/**
|
|
23
24
|
* Validates and filters events array for Appwrite functions
|
|
24
25
|
* - Filters out empty/invalid strings
|
|
26
|
+
* - Validates against EventTypeSchema
|
|
25
27
|
* - Limits to 100 items maximum (Appwrite limit)
|
|
26
28
|
* - Returns empty array if input is invalid
|
|
27
29
|
*/
|
|
28
30
|
const validateEvents = (events?: string[]): string[] => {
|
|
29
31
|
if (!events || !Array.isArray(events)) return [];
|
|
30
|
-
|
|
32
|
+
|
|
31
33
|
return events
|
|
32
|
-
.filter(event =>
|
|
34
|
+
.filter(event => {
|
|
35
|
+
if (!event || typeof event !== 'string' || event.trim().length === 0) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// Validate against EventTypeSchema
|
|
39
|
+
const result = EventTypeSchema.safeParse(event);
|
|
40
|
+
if (!result.success) {
|
|
41
|
+
MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
})
|
|
33
46
|
.slice(0, 100);
|
|
34
47
|
};
|
|
35
48
|
|
|
@@ -124,7 +137,7 @@ export const createFunction = async (
|
|
|
124
137
|
functionConfig.logging,
|
|
125
138
|
functionConfig.entrypoint,
|
|
126
139
|
functionConfig.commands,
|
|
127
|
-
functionConfig.scopes,
|
|
140
|
+
functionConfig.scopes as any[],
|
|
128
141
|
functionConfig.installationId,
|
|
129
142
|
functionConfig.providerRepositoryId,
|
|
130
143
|
functionConfig.providerBranch,
|
|
@@ -204,7 +217,7 @@ export const updateFunction = async (
|
|
|
204
217
|
functionConfig.logging,
|
|
205
218
|
functionConfig.entrypoint,
|
|
206
219
|
functionConfig.commands,
|
|
207
|
-
functionConfig.scopes,
|
|
220
|
+
functionConfig.scopes as any[],
|
|
208
221
|
functionConfig.installationId,
|
|
209
222
|
functionConfig.providerRepositoryId,
|
|
210
223
|
functionConfig.providerBranch,
|
package/src/init.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import inquirer from "inquirer";
|
|
3
3
|
import { createEmptyCollection, setupDirsFiles } from "./utils/setupFiles.js";
|
|
4
|
-
import { MessageFormatter } from "
|
|
4
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
5
5
|
|
|
6
6
|
MessageFormatter.banner("Appwrite Utils CLI Tool", "For more information, visit https://github.com/njdamstra/AppwriteUtils");
|
|
7
7
|
|
package/src/interactiveCLI.ts
CHANGED
|
@@ -35,9 +35,8 @@ import { join } from "node:path";
|
|
|
35
35
|
import path from "path";
|
|
36
36
|
import fs from "node:fs";
|
|
37
37
|
import os from "node:os";
|
|
38
|
-
import { MessageFormatter } from "
|
|
38
|
+
import { MessageFormatter, findYamlConfig } from "@njdamstra/appwrite-utils-helpers";
|
|
39
39
|
import { findAppwriteConfig } from "./utils/loadConfigs.js";
|
|
40
|
-
import { findYamlConfig } from "./config/yamlConfig.js";
|
|
41
40
|
|
|
42
41
|
// Import command modules
|
|
43
42
|
import { configCommands } from "./cli/commands/configCommands.js";
|
|
@@ -46,6 +45,7 @@ import { functionCommands } from "./cli/commands/functionCommands.js";
|
|
|
46
45
|
import { storageCommands } from "./cli/commands/storageCommands.js";
|
|
47
46
|
import { transferCommands } from "./cli/commands/transferCommands.js";
|
|
48
47
|
import { schemaCommands } from "./cli/commands/schemaCommands.js";
|
|
48
|
+
import { importFileCommands } from "./cli/commands/importFileCommands.js";
|
|
49
49
|
|
|
50
50
|
enum CHOICES {
|
|
51
51
|
MIGRATE_CONFIG = "🔄 Migrate TypeScript config to YAML (.appwrite structure)",
|
|
@@ -67,26 +67,35 @@ enum CHOICES {
|
|
|
67
67
|
GENERATE_SCHEMAS = "🏗️ Generate schemas",
|
|
68
68
|
GENERATE_CONSTANTS = "📋 Generate cross-language constants (TypeScript, Python, PHP, Dart, etc.)",
|
|
69
69
|
IMPORT_DATA = "📥 Import data",
|
|
70
|
+
IMPORT_FILE = "📄 Import file (CSV/JSON) directly into a table",
|
|
70
71
|
RELOAD_CONFIG = "🔄 Reload configuration files",
|
|
71
72
|
UPDATE_FUNCTION_SPEC = "⚙️ Update function specifications",
|
|
72
73
|
MANAGE_BUCKETS = "🪣 Manage storage buckets",
|
|
73
74
|
EXIT = "👋 Exit",
|
|
74
75
|
}
|
|
75
76
|
|
|
77
|
+
export interface InteractiveCLIOptions {
|
|
78
|
+
useSession?: boolean;
|
|
79
|
+
sessionCookie?: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
76
82
|
export class InteractiveCLI {
|
|
77
83
|
private controller: UtilsController | undefined;
|
|
78
84
|
private isUsingTypeScriptConfig: boolean = false;
|
|
79
85
|
private lastSelectedCollectionIds: string[] = [];
|
|
86
|
+
private options: InteractiveCLIOptions;
|
|
80
87
|
|
|
81
|
-
constructor(private currentDir: string) {
|
|
88
|
+
constructor(private currentDir: string, options: InteractiveCLIOptions = {}) {
|
|
89
|
+
this.options = options;
|
|
90
|
+
}
|
|
82
91
|
|
|
83
92
|
async run(): Promise<void> {
|
|
84
93
|
MessageFormatter.banner(
|
|
85
94
|
"Appwrite Utils CLI",
|
|
86
|
-
"Welcome to Appwrite Utils CLI Tool
|
|
95
|
+
"Welcome to Appwrite Utils CLI Tool"
|
|
87
96
|
);
|
|
88
97
|
MessageFormatter.info(
|
|
89
|
-
"For more information, visit https://github.com/
|
|
98
|
+
"For more information, visit https://github.com/njdamstra/AppwriteUtils"
|
|
90
99
|
);
|
|
91
100
|
|
|
92
101
|
// Detect configuration type
|
|
@@ -180,6 +189,10 @@ export class InteractiveCLI {
|
|
|
180
189
|
await this.initControllerIfNeeded();
|
|
181
190
|
await schemaCommands.importData(this);
|
|
182
191
|
break;
|
|
192
|
+
case CHOICES.IMPORT_FILE:
|
|
193
|
+
await this.initControllerIfNeeded();
|
|
194
|
+
await importFileCommands.importFile(this);
|
|
195
|
+
break;
|
|
183
196
|
case CHOICES.RELOAD_CONFIG:
|
|
184
197
|
await configCommands.reloadConfigWithSessionPreservation(this);
|
|
185
198
|
break;
|
|
@@ -204,7 +217,10 @@ export class InteractiveCLI {
|
|
|
204
217
|
}): Promise<void> {
|
|
205
218
|
if (!this.controller) {
|
|
206
219
|
this.controller = UtilsController.getInstance(this.currentDir, directConfig);
|
|
207
|
-
await this.controller.init(
|
|
220
|
+
await this.controller.init({
|
|
221
|
+
useSession: this.options.useSession,
|
|
222
|
+
sessionCookie: this.options.sessionCookie
|
|
223
|
+
});
|
|
208
224
|
} else {
|
|
209
225
|
// Extract session info from existing controller before reinitializing
|
|
210
226
|
const sessionInfo = await this.controller.getSessionInfo();
|
|
@@ -219,12 +235,18 @@ export class InteractiveCLI {
|
|
|
219
235
|
// Reinitialize with session preservation
|
|
220
236
|
UtilsController.clearInstance();
|
|
221
237
|
this.controller = UtilsController.getInstance(this.currentDir, enhancedDirectConfig);
|
|
222
|
-
await this.controller.init(
|
|
238
|
+
await this.controller.init({
|
|
239
|
+
useSession: this.options.useSession,
|
|
240
|
+
sessionCookie: this.options.sessionCookie
|
|
241
|
+
});
|
|
223
242
|
} else if (directConfig) {
|
|
224
243
|
// Standard reinitialize without session
|
|
225
244
|
UtilsController.clearInstance();
|
|
226
245
|
this.controller = UtilsController.getInstance(this.currentDir, directConfig);
|
|
227
|
-
await this.controller.init(
|
|
246
|
+
await this.controller.init({
|
|
247
|
+
useSession: this.options.useSession,
|
|
248
|
+
sessionCookie: this.options.sessionCookie
|
|
249
|
+
});
|
|
228
250
|
}
|
|
229
251
|
// If no directConfig provided, keep existing controller
|
|
230
252
|
}
|
|
@@ -308,7 +330,8 @@ export class InteractiveCLI {
|
|
|
308
330
|
},
|
|
309
331
|
]);
|
|
310
332
|
|
|
311
|
-
|
|
333
|
+
// "list" type returns a single value, "checkbox" returns an array — normalize to array
|
|
334
|
+
return Array.isArray(selectedDatabases) ? selectedDatabases : [selectedDatabases];
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
private async selectCollections(
|
|
@@ -383,8 +406,14 @@ export class InteractiveCLI {
|
|
|
383
406
|
(coll) => !configCollections.some((c) => c.name === coll.name || c.$id === coll.$id)
|
|
384
407
|
);
|
|
385
408
|
|
|
409
|
+
const getCollectionId = (collection: Models.Collection) => collection.$id || collection.name;
|
|
410
|
+
const localCollectionIds = new Set(configCollections.map((c) => c.$id || c.name));
|
|
411
|
+
const localCollections = allCollections.filter((collection) =>
|
|
412
|
+
localCollectionIds.has(getCollectionId(collection))
|
|
413
|
+
);
|
|
414
|
+
|
|
386
415
|
// Enhanced choice display with type indicators
|
|
387
|
-
const choices = allCollections
|
|
416
|
+
const choices: { name: string; value: Models.Collection | string }[] = allCollections
|
|
388
417
|
.sort((a, b) => {
|
|
389
418
|
// Sort by type first (collections before tables), then by name
|
|
390
419
|
const aIsTable = (a as any)._isFromTablesDir || false;
|
|
@@ -438,6 +467,20 @@ export class InteractiveCLI {
|
|
|
438
467
|
};
|
|
439
468
|
});
|
|
440
469
|
|
|
470
|
+
if (multiSelect && localCollections.length > 1) {
|
|
471
|
+
choices.unshift({
|
|
472
|
+
name: chalk.green.bold(`📋 Select All Local Items (${localCollections.length})`),
|
|
473
|
+
value: "__SELECT_ALL_LOCAL__"
|
|
474
|
+
});
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
if (multiSelect && allCollections.length > 1) {
|
|
478
|
+
choices.unshift({
|
|
479
|
+
name: chalk.green.bold(`📋 Select All Shown (${allCollections.length})`),
|
|
480
|
+
value: "__SELECT_ALL__"
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
|
|
441
484
|
const { selectedCollections } = await inquirer.prompt([
|
|
442
485
|
{
|
|
443
486
|
type: multiSelect ? "checkbox" : "list",
|
|
@@ -446,9 +489,28 @@ export class InteractiveCLI {
|
|
|
446
489
|
choices,
|
|
447
490
|
loop: true,
|
|
448
491
|
pageSize: 15, // Increased page size to accommodate additional info
|
|
492
|
+
validate: (input: any[]) => {
|
|
493
|
+
if (!multiSelect) return true;
|
|
494
|
+
if (input.includes("__SELECT_ALL__") && input.length > 1) {
|
|
495
|
+
return "Cannot select 'Select All' with individual items.";
|
|
496
|
+
}
|
|
497
|
+
if (input.includes("__SELECT_ALL_LOCAL__") && input.length > 1) {
|
|
498
|
+
return "Cannot select 'Select All Local' with individual items.";
|
|
499
|
+
}
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
449
502
|
},
|
|
450
503
|
]);
|
|
451
504
|
|
|
505
|
+
if (multiSelect && Array.isArray(selectedCollections)) {
|
|
506
|
+
if (selectedCollections.includes("__SELECT_ALL__")) {
|
|
507
|
+
return allCollections;
|
|
508
|
+
}
|
|
509
|
+
if (selectedCollections.includes("__SELECT_ALL_LOCAL__")) {
|
|
510
|
+
return localCollections;
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
|
|
452
514
|
return selectedCollections;
|
|
453
515
|
}
|
|
454
516
|
|
|
@@ -1007,7 +1069,7 @@ export class InteractiveCLI {
|
|
|
1007
1069
|
compression: bucketCompressionType as Compression,
|
|
1008
1070
|
encryption: bucketEncryption,
|
|
1009
1071
|
antivirus: bucketAntivirus,
|
|
1010
|
-
},
|
|
1072
|
+
} as any,
|
|
1011
1073
|
bucketId.length > 0 ? bucketId : ulid()
|
|
1012
1074
|
);
|
|
1013
1075
|
}
|
|
@@ -1019,7 +1081,10 @@ export class InteractiveCLI {
|
|
|
1019
1081
|
_sourceFolder?: string;
|
|
1020
1082
|
databaseId?: string;
|
|
1021
1083
|
})[] {
|
|
1022
|
-
const configCollections =
|
|
1084
|
+
const configCollections = [
|
|
1085
|
+
...(this.controller!.config?.collections || []),
|
|
1086
|
+
...(this.controller!.config?.tables || [])
|
|
1087
|
+
];
|
|
1023
1088
|
// @ts-expect-error - appwrite invalid types
|
|
1024
1089
|
return configCollections.map((c) => ({
|
|
1025
1090
|
$id: c.$id || ulid(),
|
|
@@ -1046,7 +1111,7 @@ export class InteractiveCLI {
|
|
|
1046
1111
|
name: db.name,
|
|
1047
1112
|
enabled: true,
|
|
1048
1113
|
type: "tablesdb" as DatabaseType,
|
|
1049
|
-
}));
|
|
1114
|
+
} as Models.Database));
|
|
1050
1115
|
}
|
|
1051
1116
|
|
|
1052
1117
|
|