@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
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { mapToCreateAttributeParams, mapToUpdateAttributeParams } from "
|
|
1
|
+
import { mapToCreateAttributeParams, mapToUpdateAttributeParams } from "@njdamstra/appwrite-utils-helpers";
|
|
2
2
|
import { Decimal } from "decimal.js";
|
|
3
3
|
const EXTREME_BOUND = new Decimal('1e12');
|
|
4
4
|
// Property configuration for different column types
|
|
5
5
|
const MUTABLE_PROPERTIES = {
|
|
6
6
|
string: ["required", "default", "size", "array"],
|
|
7
|
+
varchar: ["required", "default", "size", "array"],
|
|
8
|
+
text: ["required", "default", "array"],
|
|
9
|
+
mediumtext: ["required", "default", "array"],
|
|
10
|
+
longtext: ["required", "default", "array"],
|
|
7
11
|
integer: ["required", "default", "min", "max", "array"],
|
|
8
12
|
float: ["required", "default", "min", "max", "array"],
|
|
9
13
|
double: ["required", "default", "min", "max", "array"],
|
|
@@ -13,10 +17,17 @@ const MUTABLE_PROPERTIES = {
|
|
|
13
17
|
ip: ["required", "default", "array"],
|
|
14
18
|
url: ["required", "default", "array"],
|
|
15
19
|
enum: ["required", "default", "elements", "array"],
|
|
20
|
+
point: ["required", "default"],
|
|
21
|
+
line: ["required", "default"],
|
|
22
|
+
polygon: ["required", "default"],
|
|
16
23
|
relationship: ["required", "default"],
|
|
17
24
|
};
|
|
18
25
|
const IMMUTABLE_PROPERTIES = {
|
|
19
26
|
string: ["encrypt", "key"],
|
|
27
|
+
varchar: ["encrypt", "key"],
|
|
28
|
+
text: ["encrypt", "key"],
|
|
29
|
+
mediumtext: ["encrypt", "key"],
|
|
30
|
+
longtext: ["encrypt", "key"],
|
|
20
31
|
integer: ["encrypt", "key"],
|
|
21
32
|
float: ["encrypt", "key"],
|
|
22
33
|
double: ["encrypt", "key"],
|
|
@@ -26,10 +37,17 @@ const IMMUTABLE_PROPERTIES = {
|
|
|
26
37
|
ip: ["key"],
|
|
27
38
|
url: ["key"],
|
|
28
39
|
enum: ["key"],
|
|
40
|
+
point: ["key"],
|
|
41
|
+
line: ["key"],
|
|
42
|
+
polygon: ["key"],
|
|
29
43
|
relationship: ["key", "relatedCollection", "relationType", "twoWay", "twoWayKey", "onDelete"],
|
|
30
44
|
};
|
|
31
45
|
const TYPE_CHANGE_REQUIRES_RECREATE = [
|
|
32
46
|
"string",
|
|
47
|
+
"varchar",
|
|
48
|
+
"text",
|
|
49
|
+
"mediumtext",
|
|
50
|
+
"longtext",
|
|
33
51
|
"integer",
|
|
34
52
|
"float",
|
|
35
53
|
"double",
|
|
@@ -39,6 +57,9 @@ const TYPE_CHANGE_REQUIRES_RECREATE = [
|
|
|
39
57
|
"ip",
|
|
40
58
|
"url",
|
|
41
59
|
"enum",
|
|
60
|
+
"point",
|
|
61
|
+
"line",
|
|
62
|
+
"polygon",
|
|
42
63
|
"relationship",
|
|
43
64
|
];
|
|
44
65
|
function normDefault(val) {
|
|
@@ -64,6 +85,13 @@ export function normalizeAttributeToComparable(attr) {
|
|
|
64
85
|
base.size = attr.size ?? 255;
|
|
65
86
|
base.encrypt = !!(attr.encrypt);
|
|
66
87
|
}
|
|
88
|
+
if (t === 'varchar') {
|
|
89
|
+
base.size = attr.size ?? 255;
|
|
90
|
+
base.encrypt = !!(attr.encrypt);
|
|
91
|
+
}
|
|
92
|
+
if (t === 'text' || t === 'mediumtext' || t === 'longtext') {
|
|
93
|
+
base.encrypt = !!(attr.encrypt);
|
|
94
|
+
}
|
|
67
95
|
if (t === 'integer' || t === 'float' || t === 'double') {
|
|
68
96
|
const min = toNumber(attr.min);
|
|
69
97
|
const max = toNumber(attr.max);
|
|
@@ -90,11 +118,13 @@ export function normalizeAttributeToComparable(attr) {
|
|
|
90
118
|
return base;
|
|
91
119
|
}
|
|
92
120
|
export function normalizeColumnToComparable(col) {
|
|
93
|
-
// Detect enum surfaced as string+elements from server and normalize to enum for comparison
|
|
121
|
+
// Detect enum surfaced as string+elements or string+format:enum from server and normalize to enum for comparison
|
|
94
122
|
let t = String((col?.type ?? col?.columnType ?? '')).toLowerCase();
|
|
95
123
|
const hasElements = Array.isArray(col?.elements) && col.elements.length > 0;
|
|
96
|
-
|
|
124
|
+
const hasEnumFormat = (col?.format === 'enum');
|
|
125
|
+
if (t === 'string' && (hasElements || hasEnumFormat)) {
|
|
97
126
|
t = 'enum';
|
|
127
|
+
}
|
|
98
128
|
const base = {
|
|
99
129
|
key: col?.key,
|
|
100
130
|
type: t,
|
|
@@ -106,6 +136,13 @@ export function normalizeColumnToComparable(col) {
|
|
|
106
136
|
base.size = typeof col?.size === 'number' ? col.size : undefined;
|
|
107
137
|
base.encrypt = !!col?.encrypt;
|
|
108
138
|
}
|
|
139
|
+
if (t === 'varchar') {
|
|
140
|
+
base.size = typeof col?.size === 'number' ? col.size : undefined;
|
|
141
|
+
base.encrypt = !!col?.encrypt;
|
|
142
|
+
}
|
|
143
|
+
if (t === 'text' || t === 'mediumtext' || t === 'longtext') {
|
|
144
|
+
base.encrypt = !!col?.encrypt;
|
|
145
|
+
}
|
|
109
146
|
if (t === 'integer' || t === 'float' || t === 'double') {
|
|
110
147
|
// Preserve raw min/max without forcing extremes; compare with Decimal in shallowEqual
|
|
111
148
|
const rawMin = col?.min;
|
|
@@ -185,18 +222,27 @@ export function isIndexEqualToIndex(a, b) {
|
|
|
185
222
|
if (String(a.type).toLowerCase() !== String(b.type).toLowerCase())
|
|
186
223
|
return false;
|
|
187
224
|
// Compare attributes as sets (order-insensitive)
|
|
188
|
-
|
|
189
|
-
const
|
|
225
|
+
// Support TablesDB which returns 'columns' instead of 'attributes'
|
|
226
|
+
const attrsAraw = Array.isArray(a.attributes)
|
|
227
|
+
? a.attributes
|
|
228
|
+
: (Array.isArray(a.columns) ? a.columns : []);
|
|
229
|
+
const attrsA = [...attrsAraw].sort();
|
|
230
|
+
const attrsB = Array.isArray(b.attributes)
|
|
231
|
+
? [...b.attributes].sort()
|
|
232
|
+
: (Array.isArray(b.columns) ? [...b.columns].sort() : []);
|
|
190
233
|
if (attrsA.length !== attrsB.length)
|
|
191
234
|
return false;
|
|
192
235
|
for (let i = 0; i < attrsA.length; i++)
|
|
193
236
|
if (attrsA[i] !== attrsB[i])
|
|
194
237
|
return false;
|
|
195
|
-
// Orders are only considered if
|
|
196
|
-
|
|
197
|
-
const
|
|
198
|
-
if (
|
|
199
|
-
|
|
238
|
+
// Orders are only considered if CONFIG (b) has orders defined
|
|
239
|
+
// This prevents false positives when Appwrite returns orders but user didn't specify them
|
|
240
|
+
const hasConfigOrders = Array.isArray(b.orders) && b.orders.length > 0;
|
|
241
|
+
if (hasConfigOrders) {
|
|
242
|
+
// Some APIs may expose 'directions' instead of 'orders'
|
|
243
|
+
const ordersA = Array.isArray(a.orders)
|
|
244
|
+
? [...a.orders].sort()
|
|
245
|
+
: (Array.isArray(a.directions) ? [...a.directions].sort() : []);
|
|
200
246
|
const ordersB = [...b.orders].sort();
|
|
201
247
|
if (ordersA.length !== ordersB.length)
|
|
202
248
|
return false;
|
|
@@ -204,7 +250,6 @@ export function isIndexEqualToIndex(a, b) {
|
|
|
204
250
|
if (ordersA[i] !== ordersB[i])
|
|
205
251
|
return false;
|
|
206
252
|
}
|
|
207
|
-
// If only one side has orders, treat as equal (orders unspecified by user)
|
|
208
253
|
return true;
|
|
209
254
|
}
|
|
210
255
|
/**
|
|
@@ -213,6 +258,7 @@ export function isIndexEqualToIndex(a, b) {
|
|
|
213
258
|
function compareColumnProperties(oldColumn, newAttribute, columnType) {
|
|
214
259
|
const changes = [];
|
|
215
260
|
const t = String(columnType || newAttribute.type || '').toLowerCase();
|
|
261
|
+
const key = newAttribute?.key || 'unknown';
|
|
216
262
|
const mutableProps = MUTABLE_PROPERTIES[t] || [];
|
|
217
263
|
const immutableProps = IMMUTABLE_PROPERTIES[t] || [];
|
|
218
264
|
const getNewVal = (prop) => {
|
|
@@ -233,8 +279,9 @@ function compareColumnProperties(oldColumn, newAttribute, columnType) {
|
|
|
233
279
|
let newValue = getNewVal(prop);
|
|
234
280
|
// Special-case: enum elements empty/missing should not trigger updates
|
|
235
281
|
if (t === 'enum' && prop === 'elements') {
|
|
236
|
-
if (!Array.isArray(newValue) || newValue.length === 0)
|
|
282
|
+
if (!Array.isArray(newValue) || newValue.length === 0) {
|
|
237
283
|
newValue = oldValue;
|
|
284
|
+
}
|
|
238
285
|
}
|
|
239
286
|
if (Array.isArray(oldValue) && Array.isArray(newValue)) {
|
|
240
287
|
if (oldValue.length !== newValue.length || oldValue.some((v, i) => v !== newValue[i])) {
|
|
@@ -260,7 +307,8 @@ function compareColumnProperties(oldColumn, newAttribute, columnType) {
|
|
|
260
307
|
// Type change requires recreate (normalize string+elements to enum on old side)
|
|
261
308
|
const oldTypeRaw = String(oldColumn?.type || oldColumn?.columnType || '').toLowerCase();
|
|
262
309
|
const oldHasElements = Array.isArray(oldColumn?.elements) && oldColumn.elements.length > 0;
|
|
263
|
-
const
|
|
310
|
+
const oldHasEnumFormat = (oldColumn?.format === 'enum');
|
|
311
|
+
const oldType = oldTypeRaw === 'string' && (oldHasElements || oldHasEnumFormat) ? 'enum' : oldTypeRaw;
|
|
264
312
|
if (oldType && t && oldType !== t && TYPE_CHANGE_REQUIRES_RECREATE.includes(oldType)) {
|
|
265
313
|
changes.push({ property: 'type', oldValue: oldType, newValue: t, requiresRecreate: true });
|
|
266
314
|
}
|
|
@@ -299,29 +347,48 @@ function analyzeColumnChanges(oldColumn, newAttribute) {
|
|
|
299
347
|
/**
|
|
300
348
|
* Enhanced version of columns diff with detailed change analysis
|
|
301
349
|
* Order: desired first, then existing (matches internal usage here)
|
|
350
|
+
* Handles case-insensitive key matches as renames (recreates)
|
|
302
351
|
*/
|
|
303
352
|
export function diffColumnsDetailed(desiredAttributes, existingColumns) {
|
|
353
|
+
// Exact key lookup (case-sensitive)
|
|
304
354
|
const byKey = new Map((existingColumns || []).map((col) => [col?.key, col]));
|
|
355
|
+
// Case-insensitive key lookup for detecting renames
|
|
356
|
+
const byKeyLower = new Map((existingColumns || []).map((col) => [col?.key?.toLowerCase(), col]));
|
|
305
357
|
const toCreate = [];
|
|
306
358
|
const toUpdate = [];
|
|
307
359
|
const toRecreate = [];
|
|
308
360
|
const unchanged = [];
|
|
361
|
+
const handledExistingKeys = new Set(); // Track which existing columns we've handled
|
|
309
362
|
for (const attr of desiredAttributes || []) {
|
|
310
363
|
const key = attr?.key;
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
364
|
+
if (!key)
|
|
365
|
+
continue;
|
|
366
|
+
// First try exact match
|
|
367
|
+
const exactMatch = byKey.get(key);
|
|
368
|
+
if (exactMatch) {
|
|
369
|
+
handledExistingKeys.add(key);
|
|
370
|
+
const analysis = analyzeColumnChanges(exactMatch, attr);
|
|
371
|
+
if (!analysis.hasChanges)
|
|
372
|
+
unchanged.push(analysis.columnKey);
|
|
373
|
+
else if (analysis.requiresRecreate)
|
|
374
|
+
toRecreate.push({ oldAttribute: exactMatch, newAttribute: attr });
|
|
375
|
+
else
|
|
376
|
+
toUpdate.push({ attribute: attr, changes: analysis.changes });
|
|
314
377
|
continue;
|
|
315
378
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
379
|
+
// Check for case-insensitive match (rename scenario like oAuthAccounts -> oauthAccounts)
|
|
380
|
+
const caseInsensitiveMatch = byKeyLower.get(key.toLowerCase());
|
|
381
|
+
if (caseInsensitiveMatch && caseInsensitiveMatch.key !== key) {
|
|
382
|
+
// This is a rename - treat as recreate (delete old, create new)
|
|
383
|
+
handledExistingKeys.add(caseInsensitiveMatch.key);
|
|
384
|
+
toRecreate.push({ oldAttribute: caseInsensitiveMatch, newAttribute: attr });
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
// No match - it's a new attribute
|
|
388
|
+
toCreate.push(attr);
|
|
323
389
|
}
|
|
324
390
|
// Note: we keep toDelete empty for now (conservative behavior)
|
|
391
|
+
// Deletions are handled separately in methods.ts
|
|
325
392
|
return { toCreate, toUpdate, toRecreate, toDelete: [], unchanged };
|
|
326
393
|
}
|
|
327
394
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Databases } from "node-appwrite";
|
|
2
|
-
import type { DatabaseAdapter } from "
|
|
2
|
+
import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
|
|
3
3
|
/**
|
|
4
4
|
* Transfers all documents from one collection to another in a different database
|
|
5
5
|
* within the same Appwrite Project
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Client, Databases, ID, Query, } from "node-appwrite";
|
|
2
|
-
import { tryAwaitWithRetry, delay, calculateExponentialBackoff } from "
|
|
3
|
-
import { MessageFormatter } from "../shared/messageFormatter.js";
|
|
2
|
+
import { tryAwaitWithRetry, delay, calculateExponentialBackoff, MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
4
3
|
import { chunk } from "es-toolkit";
|
|
5
|
-
import { isLegacyDatabases } from "
|
|
6
|
-
import { getAdapter } from "
|
|
4
|
+
import { isLegacyDatabases } from "@njdamstra/appwrite-utils-helpers";
|
|
5
|
+
import { getAdapter } from "@njdamstra/appwrite-utils-helpers";
|
|
7
6
|
/**
|
|
8
7
|
* Transfers all documents from one collection to another in a different database
|
|
9
8
|
* within the same Appwrite Project
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Databases } from "node-appwrite";
|
|
2
|
-
import type { DatabaseAdapter } from "
|
|
2
|
+
import type { DatabaseAdapter } from "@njdamstra/appwrite-utils-helpers";
|
|
3
3
|
export declare const wipeDatabase: (database: Databases, databaseId: string) => Promise<{
|
|
4
4
|
collectionId: string;
|
|
5
5
|
collectionName: string;
|
|
@@ -10,7 +10,8 @@ export declare const wipeAllTables: (adapter: DatabaseAdapter, databaseId: strin
|
|
|
10
10
|
tableName: string;
|
|
11
11
|
}[]>;
|
|
12
12
|
/**
|
|
13
|
-
* Optimized deletion of all rows from a table
|
|
14
|
-
* Uses
|
|
13
|
+
* Optimized deletion of all rows from a table.
|
|
14
|
+
* Uses bulk deletion when possible, but falls back to individual row deletion
|
|
15
|
+
* for tables with relationship columns (bulk delete not supported for those).
|
|
15
16
|
*/
|
|
16
17
|
export declare const wipeTableRows: (adapter: DatabaseAdapter, databaseId: string, tableId: string) => Promise<void>;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Databases, Query, } from "node-appwrite";
|
|
2
|
-
import { tryAwaitWithRetry } from "
|
|
3
|
-
import { MessageFormatter } from "
|
|
2
|
+
import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
|
|
3
|
+
import { MessageFormatter, isRetryableError, isCriticalError } from "@njdamstra/appwrite-utils-helpers";
|
|
4
4
|
import { ProgressManager } from "../shared/progressManager.js";
|
|
5
|
-
import {
|
|
6
|
-
import { delay } from "../utils/helperFunctions.js";
|
|
5
|
+
import { delay } from "@njdamstra/appwrite-utils-helpers";
|
|
7
6
|
import { chunk } from "es-toolkit";
|
|
8
7
|
import pLimit from "p-limit";
|
|
9
8
|
import { fetchAllCollections } from "./methods.js";
|
|
@@ -167,52 +166,126 @@ export const wipeAllTables = async (adapter, databaseId) => {
|
|
|
167
166
|
return deleted;
|
|
168
167
|
};
|
|
169
168
|
/**
|
|
170
|
-
* Optimized deletion of all rows from a table
|
|
171
|
-
* Uses
|
|
169
|
+
* Optimized deletion of all rows from a table.
|
|
170
|
+
* Uses bulk deletion when possible, but falls back to individual row deletion
|
|
171
|
+
* for tables with relationship columns (bulk delete not supported for those).
|
|
172
172
|
*/
|
|
173
173
|
export const wipeTableRows = async (adapter, databaseId, tableId) => {
|
|
174
174
|
try {
|
|
175
|
-
// Check if bulk
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
const DELETE_BATCH_SIZE = 250; // How many rows to delete per batch
|
|
175
|
+
// Check if the table has relationship columns — bulk delete is not supported for those
|
|
176
|
+
const tableInfo = await adapter.getTable({ databaseId, tableId });
|
|
177
|
+
const columns = tableInfo.data?.columns || [];
|
|
178
|
+
const hasRelationships = columns.some((col) => col.type === "relationship");
|
|
179
|
+
const DELETE_BATCH_SIZE = 250;
|
|
181
180
|
let totalDeleted = 0;
|
|
182
181
|
let hasMoreRows = true;
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
|
|
182
|
+
const progress = ProgressManager.create(`delete-${tableId}`, 1, { title: "Deleting table rows" });
|
|
183
|
+
if (hasRelationships) {
|
|
184
|
+
// ── Relationship table: fetch rows then delete individually ──
|
|
185
|
+
MessageFormatter.info("Table has relationship columns — using individual row deletion (bulk delete not supported)", { prefix: "Wipe" });
|
|
186
|
+
const FETCH_BATCH_SIZE = 1000;
|
|
187
|
+
const MAX_CONCURRENT_DELETES = 25;
|
|
188
|
+
const limit = pLimit(MAX_CONCURRENT_DELETES);
|
|
189
|
+
// Pipeline: prefetch the first batch, then overlap fetch+delete
|
|
190
|
+
let pendingRows = [];
|
|
191
|
+
let totalDiscovered = 0;
|
|
192
|
+
// Fetch helper — always fetches from the top since we're deleting everything
|
|
193
|
+
const fetchBatch = async () => {
|
|
194
|
+
const queries = [Query.limit(FETCH_BATCH_SIZE)];
|
|
195
|
+
const response = await tryAwaitWithRetry(async () => adapter.listRows({ databaseId, tableId, queries }));
|
|
196
|
+
return response.rows || response.data || [];
|
|
197
|
+
};
|
|
198
|
+
// Kick off the first fetch
|
|
199
|
+
let nextFetchPromise = fetchBatch();
|
|
200
|
+
while (hasMoreRows) {
|
|
201
|
+
// Await the prefetched batch
|
|
202
|
+
const rows = nextFetchPromise ? await nextFetchPromise : [];
|
|
203
|
+
nextFetchPromise = null;
|
|
204
|
+
if (rows.length === 0) {
|
|
197
205
|
hasMoreRows = false;
|
|
198
206
|
break;
|
|
199
207
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
208
|
+
totalDiscovered += rows.length;
|
|
209
|
+
const isLastBatch = rows.length < FETCH_BATCH_SIZE;
|
|
210
|
+
if (!isLastBatch) {
|
|
211
|
+
progress.setTotal(totalDiscovered + 1000);
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
progress.setTotal(totalDiscovered);
|
|
215
|
+
}
|
|
216
|
+
MessageFormatter.progress(`Fetched ${rows.length} rows (${totalDiscovered} discovered, ${totalDeleted} deleted so far)`, { prefix: "Wipe" });
|
|
217
|
+
// Start deleting this batch — and prefetch the next one concurrently
|
|
218
|
+
// (only prefetch if we expect more rows)
|
|
219
|
+
if (!isLastBatch) {
|
|
220
|
+
// Wait a moment before prefetching so the first few deletes free up API capacity
|
|
221
|
+
nextFetchPromise = delay(200).then(() => fetchBatch());
|
|
222
|
+
}
|
|
223
|
+
// Delete each row with concurrency limit
|
|
224
|
+
const deletePromises = rows.map((row) => limit(async () => {
|
|
225
|
+
try {
|
|
226
|
+
await tryAwaitWithRetry(async () => adapter.deleteRow({ databaseId, tableId, id: row.$id }));
|
|
227
|
+
totalDeleted++;
|
|
228
|
+
progress.update(totalDeleted);
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const errorMessage = error.message || String(error);
|
|
232
|
+
if (errorMessage.includes("could not be found")) {
|
|
233
|
+
totalDeleted++;
|
|
234
|
+
progress.update(totalDeleted);
|
|
235
|
+
}
|
|
236
|
+
else if (isCriticalError(errorMessage)) {
|
|
237
|
+
MessageFormatter.error(`Critical error deleting row ${row.$id}: ${errorMessage}`, error, { prefix: "Wipe" });
|
|
238
|
+
throw error;
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
MessageFormatter.error(`Failed to delete row ${row.$id}: ${errorMessage}`, error, { prefix: "Wipe" });
|
|
242
|
+
totalDeleted++;
|
|
243
|
+
progress.update(totalDeleted);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}));
|
|
247
|
+
await Promise.all(deletePromises);
|
|
248
|
+
if (isLastBatch) {
|
|
249
|
+
hasMoreRows = false;
|
|
250
|
+
}
|
|
205
251
|
await delay(10);
|
|
206
252
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// ── No relationships: use fast bulk deletion ──
|
|
256
|
+
if (!adapter.bulkDeleteRows) {
|
|
257
|
+
MessageFormatter.error("Bulk deletion not available for this adapter - wipe operation not supported", new Error("bulkDeleteRows not available"), { prefix: "Wipe" });
|
|
258
|
+
throw new Error("Bulk deletion required for wipe operations");
|
|
259
|
+
}
|
|
260
|
+
MessageFormatter.info("Starting optimized table row deletion...", { prefix: "Wipe" });
|
|
261
|
+
while (hasMoreRows) {
|
|
262
|
+
try {
|
|
263
|
+
const result = await tryAwaitWithRetry(async () => adapter.bulkDeleteRows({
|
|
264
|
+
databaseId,
|
|
265
|
+
tableId,
|
|
266
|
+
rowIds: [],
|
|
267
|
+
batchSize: DELETE_BATCH_SIZE
|
|
268
|
+
}));
|
|
269
|
+
const deletedCount = result.total || 0;
|
|
270
|
+
if (deletedCount === 0) {
|
|
271
|
+
hasMoreRows = false;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
totalDeleted += deletedCount;
|
|
275
|
+
progress.setTotal(totalDeleted + 100);
|
|
276
|
+
progress.update(totalDeleted);
|
|
277
|
+
MessageFormatter.progress(`Deleted ${deletedCount} rows (${totalDeleted} total so far)`, { prefix: "Wipe" });
|
|
278
|
+
await delay(10);
|
|
212
279
|
}
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
280
|
+
catch (error) {
|
|
281
|
+
const errorMessage = error.message || String(error);
|
|
282
|
+
if (isCriticalError(errorMessage)) {
|
|
283
|
+
MessageFormatter.error(`Critical error during bulk deletion: ${errorMessage}`, error, { prefix: "Wipe" });
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
MessageFormatter.error(`Error during deletion batch: ${errorMessage}`, error, { prefix: "Wipe" });
|
|
288
|
+
}
|
|
216
289
|
}
|
|
217
290
|
}
|
|
218
291
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Databases, Query } 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
|
export const fetchAllDatabases = async (database) => {
|
|
6
6
|
const databases = await tryAwaitWithRetry(async () => await database.list([Query.limit(25)]));
|
|
7
7
|
const allDatabases = databases.databases;
|
package/dist/databases/setup.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Databases, Query } from "node-appwrite";
|
|
2
|
-
import { tryAwaitWithRetry } from "
|
|
2
|
+
import { tryAwaitWithRetry } from "@njdamstra/appwrite-utils-helpers";
|
|
3
3
|
import {} from "@njdamstra/appwrite-utils";
|
|
4
4
|
import { ulid } from "ulidx";
|
|
5
|
-
import { MessageFormatter } from "
|
|
5
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
6
6
|
export const ensureDatabasesExist = async (config, databasesToEnsure) => {
|
|
7
7
|
if (!config.appwriteClient) {
|
|
8
8
|
throw new Error("Appwrite client is not initialized in the config");
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
* 3. Validate terminology consistency
|
|
8
8
|
* 4. Migrate between formats
|
|
9
9
|
*/
|
|
10
|
-
import { collectionToYaml, generateYamlTemplate, generateExampleYamls, convertTerminology, normalizeYamlData, usesTableTerminology } from "
|
|
11
|
-
import { createYamlLoader } from "
|
|
10
|
+
import { collectionToYaml, generateYamlTemplate, generateExampleYamls, convertTerminology, normalizeYamlData, usesTableTerminology } from "@njdamstra/appwrite-utils-helpers";
|
|
11
|
+
import { createYamlLoader } from "@njdamstra/appwrite-utils-helpers";
|
|
12
12
|
import { YamlImportIntegration } from "../migrations/yaml/YamlImportIntegration.js";
|
|
13
13
|
import { createImportSchemas } from "../migrations/yaml/generateImportSchemas.js";
|
|
14
14
|
import { CollectionCreateSchema } from "@njdamstra/appwrite-utils";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Client, type Models } from "node-appwrite";
|
|
2
2
|
import { type AppwriteFunction } from "@njdamstra/appwrite-utils";
|
|
3
3
|
export declare const deployFunction: (client: Client, functionId: string, codePath: string, activate?: boolean, entrypoint?: string, commands?: string, ignored?: string[]) => Promise<Models.Deployment>;
|
|
4
|
-
export declare const deployLocalFunction: (client: Client, functionName: string, functionConfig: AppwriteFunction, functionPath?: string) => Promise<Models.Deployment>;
|
|
4
|
+
export declare const deployLocalFunction: (client: Client, functionName: string, functionConfig: AppwriteFunction, functionPath?: string, configDirPath?: string) => Promise<Models.Deployment>;
|
|
@@ -10,8 +10,8 @@ import cliProgress from "cli-progress";
|
|
|
10
10
|
import { execSync } from "child_process";
|
|
11
11
|
import { createFunction, getFunction, updateFunction, updateFunctionSpecifications, } from "./methods.js";
|
|
12
12
|
import ignore from "ignore";
|
|
13
|
-
import { MessageFormatter } from "
|
|
14
|
-
import { resolveFunctionDirectory, validateFunctionDirectory } from '
|
|
13
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
14
|
+
import { resolveFunctionDirectory, validateFunctionDirectory } from '@njdamstra/appwrite-utils-helpers';
|
|
15
15
|
export const deployFunction = async (client, functionId, codePath, activate = true, entrypoint = "index.js", commands = "npm install", ignored = [
|
|
16
16
|
"node_modules",
|
|
17
17
|
".git",
|
|
@@ -98,7 +98,7 @@ export const deployFunction = async (client, functionId, codePath, activate = tr
|
|
|
98
98
|
throw error;
|
|
99
99
|
}
|
|
100
100
|
};
|
|
101
|
-
export const deployLocalFunction = async (client, functionName, functionConfig, functionPath) => {
|
|
101
|
+
export const deployLocalFunction = async (client, functionName, functionConfig, functionPath, configDirPath) => {
|
|
102
102
|
let functionExists = true;
|
|
103
103
|
let functionThatExists;
|
|
104
104
|
try {
|
|
@@ -107,8 +107,8 @@ export const deployLocalFunction = async (client, functionName, functionConfig,
|
|
|
107
107
|
catch (error) {
|
|
108
108
|
functionExists = false;
|
|
109
109
|
}
|
|
110
|
-
const
|
|
111
|
-
const resolvedPath = resolveFunctionDirectory(functionName,
|
|
110
|
+
const resolvedConfigDir = configDirPath ?? process.cwd();
|
|
111
|
+
const resolvedPath = resolveFunctionDirectory(functionName, resolvedConfigDir, functionConfig.dirPath, functionPath);
|
|
112
112
|
if (!validateFunctionDirectory(resolvedPath)) {
|
|
113
113
|
throw new Error(`Function directory is invalid or missing required files: ${resolvedPath}`);
|
|
114
114
|
}
|
|
@@ -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 } 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
|
function findGitRoot(startDir) {
|
|
9
9
|
let dir = path.resolve(startDir);
|
|
10
10
|
while (dir !== path.parse(dir).root) {
|
|
@@ -2,14 +2,15 @@ import { AppwriteException, Client, Functions, Query, Runtime, } from "node-appw
|
|
|
2
2
|
import { join, dirname } from "node:path";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import fs from "node:fs";
|
|
5
|
-
import {} from "@njdamstra/appwrite-utils";
|
|
5
|
+
import { EventTypeSchema, } from "@njdamstra/appwrite-utils";
|
|
6
6
|
import chalk from "chalk";
|
|
7
7
|
import { extract as extractTar } from "tar";
|
|
8
|
-
import { MessageFormatter } from "
|
|
9
|
-
import { expandTildePath, normalizeFunctionName } from
|
|
8
|
+
import { MessageFormatter } from "@njdamstra/appwrite-utils-helpers";
|
|
9
|
+
import { expandTildePath, normalizeFunctionName } from '@njdamstra/appwrite-utils-helpers';
|
|
10
10
|
/**
|
|
11
11
|
* Validates and filters events array for Appwrite functions
|
|
12
12
|
* - Filters out empty/invalid strings
|
|
13
|
+
* - Validates against EventTypeSchema
|
|
13
14
|
* - Limits to 100 items maximum (Appwrite limit)
|
|
14
15
|
* - Returns empty array if input is invalid
|
|
15
16
|
*/
|
|
@@ -17,7 +18,18 @@ const validateEvents = (events) => {
|
|
|
17
18
|
if (!events || !Array.isArray(events))
|
|
18
19
|
return [];
|
|
19
20
|
return events
|
|
20
|
-
.filter(event =>
|
|
21
|
+
.filter(event => {
|
|
22
|
+
if (!event || typeof event !== 'string' || event.trim().length === 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Validate against EventTypeSchema
|
|
26
|
+
const result = EventTypeSchema.safeParse(event);
|
|
27
|
+
if (!result.success) {
|
|
28
|
+
MessageFormatter.warning(`Invalid event type "${event}" will be filtered out`, { prefix: "Functions" });
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
return true;
|
|
32
|
+
})
|
|
21
33
|
.slice(0, 100);
|
|
22
34
|
};
|
|
23
35
|
export const listFunctions = async (client, queries, search) => {
|
package/dist/init.js
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
|
MessageFormatter.banner("Appwrite Utils CLI Tool", "For more information, visit https://github.com/njdamstra/AppwriteUtils");
|
|
6
6
|
async function main() {
|
|
7
7
|
const answers = await inquirer.prompt([
|
package/dist/interactiveCLI.d.ts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
+
export interface InteractiveCLIOptions {
|
|
2
|
+
useSession?: boolean;
|
|
3
|
+
sessionCookie?: string;
|
|
4
|
+
}
|
|
1
5
|
export declare class InteractiveCLI {
|
|
2
6
|
private currentDir;
|
|
3
7
|
private controller;
|
|
4
8
|
private isUsingTypeScriptConfig;
|
|
5
9
|
private lastSelectedCollectionIds;
|
|
6
|
-
|
|
10
|
+
private options;
|
|
11
|
+
constructor(currentDir: string, options?: InteractiveCLIOptions);
|
|
7
12
|
run(): Promise<void>;
|
|
8
13
|
private initControllerIfNeeded;
|
|
9
14
|
private manageBuckets;
|