appwrite-utils-cli 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +199 -0
- package/README.md +251 -29
- package/dist/adapters/AdapterFactory.d.ts +10 -3
- package/dist/adapters/AdapterFactory.js +213 -17
- package/dist/adapters/TablesDBAdapter.js +60 -17
- package/dist/backups/operations/bucketBackup.d.ts +19 -0
- package/dist/backups/operations/bucketBackup.js +197 -0
- package/dist/backups/operations/collectionBackup.d.ts +30 -0
- package/dist/backups/operations/collectionBackup.js +201 -0
- package/dist/backups/operations/comprehensiveBackup.d.ts +25 -0
- package/dist/backups/operations/comprehensiveBackup.js +238 -0
- package/dist/backups/schemas/bucketManifest.d.ts +93 -0
- package/dist/backups/schemas/bucketManifest.js +33 -0
- package/dist/backups/schemas/comprehensiveManifest.d.ts +108 -0
- package/dist/backups/schemas/comprehensiveManifest.js +32 -0
- package/dist/backups/tracking/centralizedTracking.d.ts +34 -0
- package/dist/backups/tracking/centralizedTracking.js +274 -0
- package/dist/cli/commands/configCommands.d.ts +8 -0
- package/dist/cli/commands/configCommands.js +160 -0
- package/dist/cli/commands/databaseCommands.d.ts +13 -0
- package/dist/cli/commands/databaseCommands.js +478 -0
- package/dist/cli/commands/functionCommands.d.ts +7 -0
- package/dist/cli/commands/functionCommands.js +289 -0
- package/dist/cli/commands/schemaCommands.d.ts +7 -0
- package/dist/cli/commands/schemaCommands.js +134 -0
- package/dist/cli/commands/transferCommands.d.ts +5 -0
- package/dist/cli/commands/transferCommands.js +384 -0
- package/dist/collections/attributes.d.ts +5 -4
- package/dist/collections/attributes.js +539 -246
- package/dist/collections/indexes.js +39 -37
- package/dist/collections/methods.d.ts +2 -16
- package/dist/collections/methods.js +90 -538
- package/dist/collections/transferOperations.d.ts +7 -0
- package/dist/collections/transferOperations.js +331 -0
- package/dist/collections/wipeOperations.d.ts +16 -0
- package/dist/collections/wipeOperations.js +328 -0
- package/dist/config/configMigration.d.ts +87 -0
- package/dist/config/configMigration.js +390 -0
- package/dist/config/configValidation.d.ts +66 -0
- package/dist/config/configValidation.js +358 -0
- package/dist/config/yamlConfig.d.ts +455 -1
- package/dist/config/yamlConfig.js +145 -52
- package/dist/databases/methods.js +3 -2
- package/dist/databases/setup.d.ts +1 -2
- package/dist/databases/setup.js +9 -87
- package/dist/examples/yamlTerminologyExample.d.ts +42 -0
- package/dist/examples/yamlTerminologyExample.js +269 -0
- package/dist/functions/deployments.js +11 -10
- package/dist/functions/methods.d.ts +1 -1
- package/dist/functions/methods.js +5 -4
- package/dist/init.js +9 -9
- package/dist/interactiveCLI.d.ts +8 -17
- package/dist/interactiveCLI.js +186 -1171
- package/dist/main.js +364 -21
- package/dist/migrations/afterImportActions.js +22 -30
- package/dist/migrations/appwriteToX.js +71 -25
- package/dist/migrations/dataLoader.js +35 -26
- package/dist/migrations/importController.js +29 -30
- package/dist/migrations/relationships.js +13 -12
- package/dist/migrations/services/ImportOrchestrator.js +16 -19
- package/dist/migrations/transfer.js +46 -46
- package/dist/migrations/yaml/YamlImportConfigLoader.d.ts +3 -1
- package/dist/migrations/yaml/YamlImportConfigLoader.js +6 -3
- package/dist/migrations/yaml/YamlImportIntegration.d.ts +9 -3
- package/dist/migrations/yaml/YamlImportIntegration.js +22 -11
- package/dist/migrations/yaml/generateImportSchemas.d.ts +14 -1
- package/dist/migrations/yaml/generateImportSchemas.js +736 -7
- package/dist/schemas/authUser.d.ts +1 -1
- package/dist/setupController.js +3 -2
- package/dist/shared/backupMetadataSchema.d.ts +94 -0
- package/dist/shared/backupMetadataSchema.js +38 -0
- package/dist/shared/backupTracking.d.ts +18 -0
- package/dist/shared/backupTracking.js +176 -0
- package/dist/shared/confirmationDialogs.js +15 -15
- package/dist/shared/errorUtils.d.ts +54 -0
- package/dist/shared/errorUtils.js +95 -0
- package/dist/shared/functionManager.js +20 -19
- package/dist/shared/indexManager.js +12 -11
- package/dist/shared/jsonSchemaGenerator.js +10 -26
- package/dist/shared/logging.d.ts +51 -0
- package/dist/shared/logging.js +70 -0
- package/dist/shared/messageFormatter.d.ts +2 -0
- package/dist/shared/messageFormatter.js +10 -0
- package/dist/shared/migrationHelpers.d.ts +6 -16
- package/dist/shared/migrationHelpers.js +24 -21
- package/dist/shared/operationLogger.d.ts +8 -1
- package/dist/shared/operationLogger.js +11 -24
- package/dist/shared/operationQueue.d.ts +28 -1
- package/dist/shared/operationQueue.js +268 -66
- package/dist/shared/operationsTable.d.ts +26 -0
- package/dist/shared/operationsTable.js +286 -0
- package/dist/shared/operationsTableSchema.d.ts +48 -0
- package/dist/shared/operationsTableSchema.js +35 -0
- package/dist/shared/relationshipExtractor.d.ts +56 -0
- package/dist/shared/relationshipExtractor.js +138 -0
- package/dist/shared/schemaGenerator.d.ts +19 -1
- package/dist/shared/schemaGenerator.js +56 -75
- package/dist/storage/backupCompression.d.ts +20 -0
- package/dist/storage/backupCompression.js +67 -0
- package/dist/storage/methods.d.ts +16 -2
- package/dist/storage/methods.js +98 -14
- package/dist/users/methods.js +9 -8
- package/dist/utils/configDiscovery.d.ts +78 -0
- package/dist/utils/configDiscovery.js +430 -0
- package/dist/utils/directoryUtils.d.ts +22 -0
- package/dist/utils/directoryUtils.js +59 -0
- package/dist/utils/getClientFromConfig.d.ts +17 -8
- package/dist/utils/getClientFromConfig.js +162 -17
- package/dist/utils/helperFunctions.d.ts +16 -2
- package/dist/utils/helperFunctions.js +19 -5
- package/dist/utils/loadConfigs.d.ts +34 -9
- package/dist/utils/loadConfigs.js +236 -316
- package/dist/utils/pathResolvers.d.ts +53 -0
- package/dist/utils/pathResolvers.js +72 -0
- package/dist/utils/projectConfig.d.ts +119 -0
- package/dist/utils/projectConfig.js +171 -0
- package/dist/utils/retryFailedPromises.js +4 -2
- package/dist/utils/sessionAuth.d.ts +48 -0
- package/dist/utils/sessionAuth.js +164 -0
- package/dist/utils/sessionPreservationExample.d.ts +1666 -0
- package/dist/utils/sessionPreservationExample.js +101 -0
- package/dist/utils/setupFiles.js +301 -41
- package/dist/utils/typeGuards.d.ts +35 -0
- package/dist/utils/typeGuards.js +57 -0
- package/dist/utils/versionDetection.js +145 -9
- package/dist/utils/yamlConverter.d.ts +53 -3
- package/dist/utils/yamlConverter.js +232 -13
- package/dist/utils/yamlLoader.d.ts +70 -0
- package/dist/utils/yamlLoader.js +263 -0
- package/dist/utilsController.d.ts +36 -3
- package/dist/utilsController.js +186 -56
- package/package.json +12 -2
- package/src/adapters/AdapterFactory.ts +263 -35
- package/src/adapters/TablesDBAdapter.ts +225 -36
- package/src/backups/operations/bucketBackup.ts +277 -0
- package/src/backups/operations/collectionBackup.ts +310 -0
- package/src/backups/operations/comprehensiveBackup.ts +342 -0
- package/src/backups/schemas/bucketManifest.ts +78 -0
- package/src/backups/schemas/comprehensiveManifest.ts +76 -0
- package/src/backups/tracking/centralizedTracking.ts +352 -0
- package/src/cli/commands/configCommands.ts +194 -0
- package/src/cli/commands/databaseCommands.ts +635 -0
- package/src/cli/commands/functionCommands.ts +379 -0
- package/src/cli/commands/schemaCommands.ts +163 -0
- package/src/cli/commands/transferCommands.ts +457 -0
- package/src/collections/attributes.ts +900 -621
- package/src/collections/attributes.ts.backup +1555 -0
- package/src/collections/indexes.ts +116 -114
- package/src/collections/methods.ts +295 -968
- package/src/collections/transferOperations.ts +516 -0
- package/src/collections/wipeOperations.ts +501 -0
- package/src/config/README.md +274 -0
- package/src/config/configMigration.ts +575 -0
- package/src/config/configValidation.ts +445 -0
- package/src/config/yamlConfig.ts +168 -55
- package/src/databases/methods.ts +3 -2
- package/src/databases/setup.ts +11 -138
- package/src/examples/yamlTerminologyExample.ts +341 -0
- package/src/functions/deployments.ts +14 -12
- package/src/functions/methods.ts +11 -11
- package/src/functions/templates/hono-typescript/README.md +286 -0
- package/src/functions/templates/hono-typescript/package.json +26 -0
- package/src/functions/templates/hono-typescript/src/adapters/request.ts +74 -0
- package/src/functions/templates/hono-typescript/src/adapters/response.ts +106 -0
- package/src/functions/templates/hono-typescript/src/app.ts +180 -0
- package/src/functions/templates/hono-typescript/src/context.ts +103 -0
- package/src/functions/templates/hono-typescript/src/index.ts +54 -0
- package/src/functions/templates/hono-typescript/src/middleware/appwrite.ts +119 -0
- package/src/functions/templates/hono-typescript/tsconfig.json +20 -0
- package/src/functions/templates/typescript-node/package.json +2 -1
- package/src/functions/templates/typescript-node/src/context.ts +103 -0
- package/src/functions/templates/typescript-node/src/index.ts +18 -12
- package/src/functions/templates/uv/pyproject.toml +1 -0
- package/src/functions/templates/uv/src/context.py +125 -0
- package/src/functions/templates/uv/src/index.py +35 -5
- package/src/init.ts +9 -11
- package/src/interactiveCLI.ts +276 -1591
- package/src/main.ts +418 -24
- package/src/migrations/afterImportActions.ts +71 -44
- package/src/migrations/appwriteToX.ts +100 -34
- package/src/migrations/dataLoader.ts +48 -34
- package/src/migrations/importController.ts +44 -39
- package/src/migrations/relationships.ts +28 -18
- package/src/migrations/services/ImportOrchestrator.ts +24 -27
- package/src/migrations/transfer.ts +159 -121
- package/src/migrations/yaml/YamlImportConfigLoader.ts +11 -4
- package/src/migrations/yaml/YamlImportIntegration.ts +47 -20
- package/src/migrations/yaml/generateImportSchemas.ts +751 -12
- package/src/setupController.ts +3 -2
- package/src/shared/backupMetadataSchema.ts +93 -0
- package/src/shared/backupTracking.ts +211 -0
- package/src/shared/confirmationDialogs.ts +19 -19
- package/src/shared/errorUtils.ts +110 -0
- package/src/shared/functionManager.ts +21 -20
- package/src/shared/indexManager.ts +12 -11
- package/src/shared/jsonSchemaGenerator.ts +38 -52
- package/src/shared/logging.ts +75 -0
- package/src/shared/messageFormatter.ts +14 -1
- package/src/shared/migrationHelpers.ts +45 -38
- package/src/shared/operationLogger.ts +11 -36
- package/src/shared/operationQueue.ts +322 -93
- package/src/shared/operationsTable.ts +338 -0
- package/src/shared/operationsTableSchema.ts +60 -0
- package/src/shared/relationshipExtractor.ts +214 -0
- package/src/shared/schemaGenerator.ts +179 -219
- package/src/storage/backupCompression.ts +88 -0
- package/src/storage/methods.ts +131 -34
- package/src/users/methods.ts +11 -9
- package/src/utils/configDiscovery.ts +502 -0
- package/src/utils/directoryUtils.ts +61 -0
- package/src/utils/getClientFromConfig.ts +205 -22
- package/src/utils/helperFunctions.ts +23 -5
- package/src/utils/loadConfigs.ts +313 -345
- package/src/utils/pathResolvers.ts +81 -0
- package/src/utils/projectConfig.ts +299 -0
- package/src/utils/retryFailedPromises.ts +4 -2
- package/src/utils/sessionAuth.ts +230 -0
- package/src/utils/setupFiles.ts +322 -54
- package/src/utils/typeGuards.ts +65 -0
- package/src/utils/versionDetection.ts +218 -64
- package/src/utils/yamlConverter.ts +296 -13
- package/src/utils/yamlLoader.ts +364 -0
- package/src/utilsController.ts +314 -110
- package/tests/README.md +497 -0
- package/tests/adapters/AdapterFactory.test.ts +277 -0
- package/tests/integration/syncOperations.test.ts +463 -0
- package/tests/jest.config.js +25 -0
- package/tests/migration/configMigration.test.ts +546 -0
- package/tests/setup.ts +62 -0
- package/tests/testUtils.ts +340 -0
- package/tests/utils/loadConfigs.test.ts +350 -0
- package/tests/validation/configValidation.test.ts +412 -0
- package/src/utils/schemaStrings.ts +0 -517
@@ -0,0 +1,430 @@
|
|
1
|
+
import path from "path";
|
2
|
+
import fs from "fs";
|
3
|
+
import {} from "appwrite-utils";
|
4
|
+
import { register } from "tsx/esm/api";
|
5
|
+
import { pathToFileURL } from "node:url";
|
6
|
+
import yaml from "js-yaml";
|
7
|
+
import { z } from "zod";
|
8
|
+
import { MessageFormatter } from "../shared/messageFormatter.js";
|
9
|
+
import { shouldIgnoreDirectory } from "./directoryUtils.js";
|
10
|
+
import { resolveCollectionsDir, resolveTablesDir } from "./pathResolvers.js";
|
11
|
+
import { findYamlConfig } from "../config/yamlConfig.js";
|
12
|
+
/**
|
13
|
+
* Recursively searches for TypeScript configuration files (appwriteConfig.ts)
|
14
|
+
* @param dir The directory to start the search from
|
15
|
+
* @param depth Current search depth for recursion limiting
|
16
|
+
* @returns Path to the config file or null if not found
|
17
|
+
*/
|
18
|
+
export const findAppwriteConfigTS = (dir, depth = 0) => {
|
19
|
+
// Limit search depth to prevent infinite recursion
|
20
|
+
if (depth > 10) {
|
21
|
+
return null;
|
22
|
+
}
|
23
|
+
if (shouldIgnoreDirectory(path.basename(dir))) {
|
24
|
+
return null;
|
25
|
+
}
|
26
|
+
try {
|
27
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
28
|
+
// First check current directory for appwriteConfig.ts
|
29
|
+
for (const entry of entries) {
|
30
|
+
if (entry.isFile() && entry.name === "appwriteConfig.ts") {
|
31
|
+
return path.join(dir, entry.name);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
// Then search subdirectories
|
35
|
+
for (const entry of entries) {
|
36
|
+
if (entry.isDirectory() && !shouldIgnoreDirectory(entry.name)) {
|
37
|
+
const result = findAppwriteConfigTS(path.join(dir, entry.name), depth + 1);
|
38
|
+
if (result)
|
39
|
+
return result;
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
catch (error) {
|
44
|
+
// Ignore directory access errors
|
45
|
+
}
|
46
|
+
return null;
|
47
|
+
};
|
48
|
+
/**
|
49
|
+
* Recursively searches for configuration files starting from the given directory.
|
50
|
+
* Priority: 1) YAML configs in .appwrite directories, 2) appwriteConfig.ts files in subdirectories
|
51
|
+
* @param dir The directory to start the search from
|
52
|
+
* @returns The directory path where the config was found, suitable for passing to loadConfig()
|
53
|
+
*/
|
54
|
+
export const findAppwriteConfig = (dir) => {
|
55
|
+
// First try to find YAML config (already searches recursively for .appwrite dirs)
|
56
|
+
const yamlConfig = findYamlConfig(dir);
|
57
|
+
if (yamlConfig) {
|
58
|
+
// Return the directory containing the config file
|
59
|
+
return path.dirname(yamlConfig);
|
60
|
+
}
|
61
|
+
// Fall back to TypeScript config search
|
62
|
+
const tsConfigPath = findAppwriteConfigTS(dir);
|
63
|
+
if (tsConfigPath) {
|
64
|
+
return path.dirname(tsConfigPath);
|
65
|
+
}
|
66
|
+
return null;
|
67
|
+
};
|
68
|
+
/**
|
69
|
+
* Recursively searches for the functions directory
|
70
|
+
* @param dir The directory to start searching from
|
71
|
+
* @param depth Current search depth for recursion limiting
|
72
|
+
* @returns Path to the functions directory or null if not found
|
73
|
+
*/
|
74
|
+
export const findFunctionsDir = (dir, depth = 0) => {
|
75
|
+
// Limit search depth to prevent infinite recursion
|
76
|
+
if (depth > 5) {
|
77
|
+
return null;
|
78
|
+
}
|
79
|
+
if (shouldIgnoreDirectory(path.basename(dir))) {
|
80
|
+
return null;
|
81
|
+
}
|
82
|
+
try {
|
83
|
+
const files = fs.readdirSync(dir, { withFileTypes: true });
|
84
|
+
for (const entry of files) {
|
85
|
+
if (!entry.isDirectory() || shouldIgnoreDirectory(entry.name)) {
|
86
|
+
continue;
|
87
|
+
}
|
88
|
+
if (entry.name === "functions") {
|
89
|
+
return path.join(dir, entry.name);
|
90
|
+
}
|
91
|
+
const result = findFunctionsDir(path.join(dir, entry.name), depth + 1);
|
92
|
+
if (result)
|
93
|
+
return result;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
catch (error) {
|
97
|
+
// Ignore directory access errors
|
98
|
+
}
|
99
|
+
return null;
|
100
|
+
};
|
101
|
+
// YAML Collection Schema
|
102
|
+
const YamlCollectionSchema = z.object({
|
103
|
+
name: z.string(),
|
104
|
+
id: z.string().optional(),
|
105
|
+
documentSecurity: z.boolean().default(false),
|
106
|
+
enabled: z.boolean().default(true),
|
107
|
+
permissions: z.array(z.object({
|
108
|
+
permission: z.string(),
|
109
|
+
target: z.string()
|
110
|
+
})).optional().default([]),
|
111
|
+
attributes: z.array(z.object({
|
112
|
+
key: z.string(),
|
113
|
+
type: z.string(),
|
114
|
+
size: z.number().optional(),
|
115
|
+
required: z.boolean().default(false),
|
116
|
+
array: z.boolean().optional(),
|
117
|
+
default: z.any().optional(),
|
118
|
+
min: z.number().optional(),
|
119
|
+
max: z.number().optional(),
|
120
|
+
elements: z.array(z.string()).optional(),
|
121
|
+
relatedCollection: z.string().optional(),
|
122
|
+
relationType: z.string().optional(),
|
123
|
+
twoWay: z.boolean().optional(),
|
124
|
+
twoWayKey: z.string().optional(),
|
125
|
+
onDelete: z.string().optional(),
|
126
|
+
side: z.string().optional()
|
127
|
+
})).optional().default([]),
|
128
|
+
indexes: z.array(z.object({
|
129
|
+
key: z.string(),
|
130
|
+
type: z.string(),
|
131
|
+
attributes: z.array(z.string()),
|
132
|
+
orders: z.array(z.string()).optional()
|
133
|
+
})).optional().default([]),
|
134
|
+
importDefs: z.array(z.any()).optional().default([])
|
135
|
+
});
|
136
|
+
/**
|
137
|
+
* Loads a YAML collection file and converts it to CollectionCreate format
|
138
|
+
* @param filePath Path to the YAML collection file
|
139
|
+
* @returns CollectionCreate object or null if loading fails
|
140
|
+
*/
|
141
|
+
export const loadYamlCollection = (filePath) => {
|
142
|
+
try {
|
143
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
144
|
+
const yamlData = yaml.load(fileContent);
|
145
|
+
const parsedCollection = YamlCollectionSchema.parse(yamlData);
|
146
|
+
// Convert YAML collection to CollectionCreate format
|
147
|
+
const collection = {
|
148
|
+
name: parsedCollection.name,
|
149
|
+
$id: parsedCollection.id || parsedCollection.name.toLowerCase().replace(/\s+/g, '_'),
|
150
|
+
documentSecurity: parsedCollection.documentSecurity,
|
151
|
+
enabled: parsedCollection.enabled,
|
152
|
+
$permissions: parsedCollection.permissions.map(p => ({
|
153
|
+
permission: p.permission,
|
154
|
+
target: p.target
|
155
|
+
})),
|
156
|
+
attributes: parsedCollection.attributes.map(attr => ({
|
157
|
+
key: attr.key,
|
158
|
+
type: attr.type,
|
159
|
+
size: attr.size,
|
160
|
+
required: attr.required,
|
161
|
+
array: attr.array,
|
162
|
+
xdefault: attr.default,
|
163
|
+
min: attr.min,
|
164
|
+
max: attr.max,
|
165
|
+
elements: attr.elements,
|
166
|
+
relatedCollection: attr.relatedCollection,
|
167
|
+
relationType: attr.relationType,
|
168
|
+
twoWay: attr.twoWay,
|
169
|
+
twoWayKey: attr.twoWayKey,
|
170
|
+
onDelete: attr.onDelete,
|
171
|
+
side: attr.side
|
172
|
+
})),
|
173
|
+
indexes: parsedCollection.indexes.map(idx => ({
|
174
|
+
key: idx.key,
|
175
|
+
type: idx.type,
|
176
|
+
attributes: idx.attributes,
|
177
|
+
orders: idx.orders
|
178
|
+
})),
|
179
|
+
importDefs: parsedCollection.importDefs && Array.isArray(parsedCollection.importDefs) && parsedCollection.importDefs.length > 0 ? parsedCollection.importDefs : []
|
180
|
+
};
|
181
|
+
return collection;
|
182
|
+
}
|
183
|
+
catch (error) {
|
184
|
+
MessageFormatter.error(`Error loading YAML collection from ${filePath}`, error, { prefix: "Config" });
|
185
|
+
return null;
|
186
|
+
}
|
187
|
+
};
|
188
|
+
/**
|
189
|
+
* Loads a YAML table file and converts it to table format
|
190
|
+
* @param filePath Path to the YAML table file
|
191
|
+
* @returns Table object or null if loading fails
|
192
|
+
*/
|
193
|
+
export const loadYamlTable = (filePath) => {
|
194
|
+
try {
|
195
|
+
const fileContent = fs.readFileSync(filePath, "utf8");
|
196
|
+
const yamlData = yaml.load(fileContent);
|
197
|
+
// For now, use the collection schema as base and adapt for tables
|
198
|
+
const parsedTable = YamlCollectionSchema.parse(yamlData);
|
199
|
+
// Convert YAML table to TableCreate format
|
200
|
+
const table = {
|
201
|
+
name: parsedTable.name,
|
202
|
+
tableId: yamlData.tableId || parsedTable.id || parsedTable.name.toLowerCase().replace(/\s+/g, '_'),
|
203
|
+
documentSecurity: parsedTable.documentSecurity,
|
204
|
+
enabled: parsedTable.enabled,
|
205
|
+
$permissions: parsedTable.permissions.map(p => ({
|
206
|
+
permission: p.permission,
|
207
|
+
target: p.target
|
208
|
+
})),
|
209
|
+
attributes: parsedTable.attributes.map(attr => ({
|
210
|
+
key: attr.key,
|
211
|
+
type: attr.type,
|
212
|
+
size: attr.size,
|
213
|
+
required: attr.required,
|
214
|
+
array: attr.array,
|
215
|
+
xdefault: attr.default,
|
216
|
+
min: attr.min,
|
217
|
+
max: attr.max,
|
218
|
+
elements: attr.elements,
|
219
|
+
relatedCollection: attr.relatedCollection,
|
220
|
+
relationType: attr.relationType,
|
221
|
+
twoWay: attr.twoWay,
|
222
|
+
twoWayKey: attr.twoWayKey,
|
223
|
+
onDelete: attr.onDelete,
|
224
|
+
side: attr.side
|
225
|
+
})),
|
226
|
+
indexes: parsedTable.indexes.map(idx => ({
|
227
|
+
key: idx.key,
|
228
|
+
type: idx.type,
|
229
|
+
attributes: idx.attributes,
|
230
|
+
orders: idx.orders
|
231
|
+
})),
|
232
|
+
importDefs: parsedTable.importDefs,
|
233
|
+
databaseId: yamlData.databaseId,
|
234
|
+
// Add backward compatibility field
|
235
|
+
$id: yamlData.$id || parsedTable.id
|
236
|
+
};
|
237
|
+
return table;
|
238
|
+
}
|
239
|
+
catch (error) {
|
240
|
+
MessageFormatter.error(`Error loading YAML table from ${filePath}`, error, { prefix: "Config" });
|
241
|
+
return null;
|
242
|
+
}
|
243
|
+
};
|
244
|
+
/**
|
245
|
+
* Discovers and loads collections from a collections/ directory
|
246
|
+
* @param collectionsDir Path to the collections directory
|
247
|
+
* @returns Discovery result with loaded collections and metadata
|
248
|
+
*/
|
249
|
+
export const discoverCollections = async (collectionsDir) => {
|
250
|
+
const collections = [];
|
251
|
+
const loadedNames = new Set();
|
252
|
+
const conflicts = [];
|
253
|
+
if (!fs.existsSync(collectionsDir)) {
|
254
|
+
return { collections, loadedNames, conflicts };
|
255
|
+
}
|
256
|
+
const unregister = register(); // Register tsx for collections
|
257
|
+
try {
|
258
|
+
const collectionFiles = fs.readdirSync(collectionsDir);
|
259
|
+
MessageFormatter.success(`Loading from collections/ directory: ${collectionFiles.length} files found`, { prefix: "Config" });
|
260
|
+
for (const file of collectionFiles) {
|
261
|
+
if (file === "index.ts") {
|
262
|
+
continue;
|
263
|
+
}
|
264
|
+
const filePath = path.join(collectionsDir, file);
|
265
|
+
let collection = null;
|
266
|
+
// Handle YAML collections
|
267
|
+
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
268
|
+
collection = loadYamlCollection(filePath);
|
269
|
+
}
|
270
|
+
// Handle TypeScript collections
|
271
|
+
else if (file.endsWith('.ts')) {
|
272
|
+
const fileUrl = pathToFileURL(filePath).href;
|
273
|
+
const collectionModule = (await import(fileUrl));
|
274
|
+
const importedCollection = collectionModule.default?.default || collectionModule.default || collectionModule;
|
275
|
+
if (importedCollection) {
|
276
|
+
collection = importedCollection;
|
277
|
+
// Ensure importDefs are properly loaded
|
278
|
+
if (collectionModule.importDefs || collection.importDefs) {
|
279
|
+
collection.importDefs = collectionModule.importDefs || collection.importDefs;
|
280
|
+
}
|
281
|
+
}
|
282
|
+
}
|
283
|
+
if (collection) {
|
284
|
+
const collectionName = collection.name || collection.$id || file;
|
285
|
+
loadedNames.add(collectionName);
|
286
|
+
collections.push(collection);
|
287
|
+
}
|
288
|
+
}
|
289
|
+
}
|
290
|
+
finally {
|
291
|
+
unregister(); // Unregister tsx when done
|
292
|
+
}
|
293
|
+
return { collections, loadedNames, conflicts };
|
294
|
+
};
|
295
|
+
/**
|
296
|
+
* Discovers and loads tables from a tables/ directory
|
297
|
+
* @param tablesDir Path to the tables directory
|
298
|
+
* @param existingNames Set of already-loaded collection names to check for conflicts
|
299
|
+
* @returns Discovery result with loaded tables and metadata
|
300
|
+
*/
|
301
|
+
export const discoverTables = async (tablesDir, existingNames = new Set()) => {
|
302
|
+
const tables = [];
|
303
|
+
const loadedNames = new Set();
|
304
|
+
const conflicts = [];
|
305
|
+
if (!fs.existsSync(tablesDir)) {
|
306
|
+
return { tables, loadedNames, conflicts };
|
307
|
+
}
|
308
|
+
const unregister = register(); // Register tsx for tables
|
309
|
+
try {
|
310
|
+
const tableFiles = fs.readdirSync(tablesDir);
|
311
|
+
MessageFormatter.success(`Loading from tables/ directory: ${tableFiles.length} files found`, { prefix: "Config" });
|
312
|
+
for (const file of tableFiles) {
|
313
|
+
if (file === "index.ts") {
|
314
|
+
continue;
|
315
|
+
}
|
316
|
+
const filePath = path.join(tablesDir, file);
|
317
|
+
let table = null;
|
318
|
+
// Handle YAML tables
|
319
|
+
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
320
|
+
table = loadYamlTable(filePath);
|
321
|
+
}
|
322
|
+
// Handle TypeScript tables
|
323
|
+
else if (file.endsWith('.ts')) {
|
324
|
+
const fileUrl = pathToFileURL(filePath).href;
|
325
|
+
const tableModule = (await import(fileUrl));
|
326
|
+
const importedTable = tableModule.default?.default || tableModule.default || tableModule;
|
327
|
+
if (importedTable) {
|
328
|
+
table = importedTable;
|
329
|
+
// Ensure importDefs are properly loaded
|
330
|
+
if (tableModule.importDefs || table.importDefs) {
|
331
|
+
table.importDefs = tableModule.importDefs || table.importDefs;
|
332
|
+
}
|
333
|
+
}
|
334
|
+
}
|
335
|
+
if (table) {
|
336
|
+
const tableName = table.name || table.tableId || table.$id || file;
|
337
|
+
// Check for naming conflicts with existing collections
|
338
|
+
if (existingNames.has(tableName)) {
|
339
|
+
conflicts.push({
|
340
|
+
name: tableName,
|
341
|
+
source1: "collections/",
|
342
|
+
source2: "tables/"
|
343
|
+
});
|
344
|
+
MessageFormatter.warning(`Skipping duplicate '${tableName}' from tables/ (collections/ takes priority)`, { prefix: "Config" });
|
345
|
+
}
|
346
|
+
else {
|
347
|
+
loadedNames.add(tableName);
|
348
|
+
// Mark as coming from tables directory
|
349
|
+
table._isFromTablesDir = true;
|
350
|
+
tables.push(table);
|
351
|
+
}
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
finally {
|
356
|
+
unregister(); // Unregister tsx when done
|
357
|
+
}
|
358
|
+
return { tables, loadedNames, conflicts };
|
359
|
+
};
|
360
|
+
/**
|
361
|
+
* Discovers and loads collections/tables from legacy single directory structure
|
362
|
+
* @param configFileDir Directory containing the config file
|
363
|
+
* @param dirName Directory name to search for ('collections' or 'tables')
|
364
|
+
* @returns Array of discovered collections/tables
|
365
|
+
*/
|
366
|
+
export const discoverLegacyDirectory = async (configFileDir, dirName) => {
|
367
|
+
const legacyDir = path.join(configFileDir, dirName);
|
368
|
+
const items = [];
|
369
|
+
if (!fs.existsSync(legacyDir)) {
|
370
|
+
return items;
|
371
|
+
}
|
372
|
+
MessageFormatter.info(`Using legacy single directory: ${dirName}/`, { prefix: "Config" });
|
373
|
+
const unregister = register(); // Register tsx for legacy collections
|
374
|
+
try {
|
375
|
+
const collectionFiles = fs.readdirSync(legacyDir);
|
376
|
+
for (const file of collectionFiles) {
|
377
|
+
if (file === "index.ts") {
|
378
|
+
continue;
|
379
|
+
}
|
380
|
+
const filePath = path.join(legacyDir, file);
|
381
|
+
// Handle YAML collections
|
382
|
+
if (file.endsWith('.yaml') || file.endsWith('.yml')) {
|
383
|
+
const collection = loadYamlCollection(filePath);
|
384
|
+
if (collection) {
|
385
|
+
if (dirName === 'tables') {
|
386
|
+
// Mark as coming from tables directory
|
387
|
+
const table = {
|
388
|
+
...collection,
|
389
|
+
_isFromTablesDir: true,
|
390
|
+
tableId: collection.$id || collection.name.toLowerCase().replace(/\s+/g, '_')
|
391
|
+
};
|
392
|
+
items.push(table);
|
393
|
+
}
|
394
|
+
else {
|
395
|
+
items.push(collection);
|
396
|
+
}
|
397
|
+
}
|
398
|
+
continue;
|
399
|
+
}
|
400
|
+
// Handle TypeScript collections
|
401
|
+
if (file.endsWith('.ts')) {
|
402
|
+
const fileUrl = pathToFileURL(filePath).href;
|
403
|
+
const collectionModule = (await import(fileUrl));
|
404
|
+
const collection = collectionModule.default?.default || collectionModule.default || collectionModule;
|
405
|
+
if (collection) {
|
406
|
+
// Ensure importDefs are properly loaded
|
407
|
+
if (collectionModule.importDefs || collection.importDefs) {
|
408
|
+
collection.importDefs = collectionModule.importDefs || collection.importDefs;
|
409
|
+
}
|
410
|
+
if (dirName === 'tables') {
|
411
|
+
// Mark as coming from tables directory
|
412
|
+
const table = {
|
413
|
+
...collection,
|
414
|
+
_isFromTablesDir: true,
|
415
|
+
tableId: collection.$id || collection.name.toLowerCase().replace(/\s+/g, '_')
|
416
|
+
};
|
417
|
+
items.push(table);
|
418
|
+
}
|
419
|
+
else {
|
420
|
+
items.push(collection);
|
421
|
+
}
|
422
|
+
}
|
423
|
+
}
|
424
|
+
}
|
425
|
+
}
|
426
|
+
finally {
|
427
|
+
unregister(); // Unregister tsx when done
|
428
|
+
}
|
429
|
+
return items;
|
430
|
+
};
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/**
|
2
|
+
* Directory utility functions for filtering and managing directory traversal
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* List of directories that should be ignored during recursive searches
|
6
|
+
* Includes common build outputs, dependencies, caches, and system folders
|
7
|
+
*/
|
8
|
+
export declare const IGNORED_DIRECTORIES: string[];
|
9
|
+
/**
|
10
|
+
* Determines if a directory should be ignored during recursive file operations
|
11
|
+
*
|
12
|
+
* @param dirName - The name of the directory to check
|
13
|
+
* @returns true if the directory should be ignored, false otherwise
|
14
|
+
*
|
15
|
+
* @remarks
|
16
|
+
* A directory is ignored if:
|
17
|
+
* - It matches one of the entries in IGNORED_DIRECTORIES
|
18
|
+
* - It starts with '.git' prefix
|
19
|
+
* - It starts with 'node_modules' prefix
|
20
|
+
* - It starts with '.' (hidden directory) except for '.appwrite'
|
21
|
+
*/
|
22
|
+
export declare const shouldIgnoreDirectory: (dirName: string) => boolean;
|
@@ -0,0 +1,59 @@
|
|
1
|
+
/**
|
2
|
+
* Directory utility functions for filtering and managing directory traversal
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* List of directories that should be ignored during recursive searches
|
6
|
+
* Includes common build outputs, dependencies, caches, and system folders
|
7
|
+
*/
|
8
|
+
export const IGNORED_DIRECTORIES = [
|
9
|
+
'node_modules',
|
10
|
+
'dist',
|
11
|
+
'build',
|
12
|
+
'coverage',
|
13
|
+
'.next',
|
14
|
+
'.nuxt',
|
15
|
+
'.cache',
|
16
|
+
'.git',
|
17
|
+
'.svn',
|
18
|
+
'.hg',
|
19
|
+
'__pycache__',
|
20
|
+
'.pytest_cache',
|
21
|
+
'.mypy_cache',
|
22
|
+
'venv',
|
23
|
+
'.venv',
|
24
|
+
'env',
|
25
|
+
'.env',
|
26
|
+
'target',
|
27
|
+
'out',
|
28
|
+
'bin',
|
29
|
+
'obj',
|
30
|
+
'.vs',
|
31
|
+
'.vscode',
|
32
|
+
'.idea',
|
33
|
+
'temp',
|
34
|
+
'tmp',
|
35
|
+
'.tmp',
|
36
|
+
'logs',
|
37
|
+
'log',
|
38
|
+
'.DS_Store',
|
39
|
+
'Thumbs.db'
|
40
|
+
];
|
41
|
+
/**
|
42
|
+
* Determines if a directory should be ignored during recursive file operations
|
43
|
+
*
|
44
|
+
* @param dirName - The name of the directory to check
|
45
|
+
* @returns true if the directory should be ignored, false otherwise
|
46
|
+
*
|
47
|
+
* @remarks
|
48
|
+
* A directory is ignored if:
|
49
|
+
* - It matches one of the entries in IGNORED_DIRECTORIES
|
50
|
+
* - It starts with '.git' prefix
|
51
|
+
* - It starts with 'node_modules' prefix
|
52
|
+
* - It starts with '.' (hidden directory) except for '.appwrite'
|
53
|
+
*/
|
54
|
+
export const shouldIgnoreDirectory = (dirName) => {
|
55
|
+
return IGNORED_DIRECTORIES.includes(dirName) ||
|
56
|
+
dirName.startsWith('.git') ||
|
57
|
+
dirName.startsWith('node_modules') ||
|
58
|
+
(dirName.startsWith('.') && dirName !== '.appwrite');
|
59
|
+
};
|
@@ -2,29 +2,38 @@ import { type AppwriteConfig } from "appwrite-utils";
|
|
2
2
|
import { Client } from "node-appwrite";
|
3
3
|
import type { DatabaseAdapter } from "../adapters/DatabaseAdapter.js";
|
4
4
|
/**
|
5
|
-
*
|
6
|
-
* @deprecated Use getAdapterFromConfig for dual API support
|
5
|
+
* Enhanced client creation from config with session authentication support
|
6
|
+
* @deprecated Use getAdapterFromConfig for dual API support with session auth
|
7
7
|
*/
|
8
|
-
export declare const getClientFromConfig: (config: AppwriteConfig) => Client | undefined;
|
8
|
+
export declare const getClientFromConfig: (config: AppwriteConfig, sessionCookie?: string) => Client | undefined;
|
9
|
+
/**
|
10
|
+
* Enhanced client creation with session authentication support
|
11
|
+
* Priority: explicit session > session from prefs > API key
|
12
|
+
*/
|
13
|
+
export declare const getClientWithAuth: (endpoint: string, project: string, key?: string, sessionCookie?: string) => Client;
|
9
14
|
/**
|
10
15
|
* Legacy function - returns basic Client
|
11
|
-
* @deprecated Use createDatabaseAdapter for dual API support
|
16
|
+
* @deprecated Use getClientWithAuth for session support or createDatabaseAdapter for dual API support
|
12
17
|
*/
|
13
18
|
export declare const getClient: (endpoint: string, project: string, key: string) => Client;
|
14
19
|
/**
|
15
|
-
* Modern adapter-based client creation with dual API support
|
20
|
+
* Modern adapter-based client creation with dual API support and session authentication
|
16
21
|
* Returns both adapter and legacy client for compatibility
|
17
22
|
*/
|
18
|
-
export declare const getAdapterFromConfig: (config: AppwriteConfig, forceRefresh?: boolean) => Promise<{
|
23
|
+
export declare const getAdapterFromConfig: (config: AppwriteConfig, forceRefresh?: boolean, sessionCookie?: string) => Promise<{
|
19
24
|
adapter: DatabaseAdapter;
|
20
25
|
client: Client;
|
21
26
|
apiMode: "legacy" | "tablesdb";
|
22
27
|
}>;
|
23
28
|
/**
|
24
|
-
* Create adapter from individual parameters
|
29
|
+
* Create adapter from individual parameters with session authentication support
|
25
30
|
*/
|
26
|
-
export declare const getAdapter: (endpoint: string, project: string, key
|
31
|
+
export declare const getAdapter: (endpoint: string, project: string, key?: string, apiMode?: "auto" | "legacy" | "tablesdb", sessionCookie?: string) => Promise<{
|
27
32
|
adapter: DatabaseAdapter;
|
28
33
|
client: Client;
|
29
34
|
apiMode: "legacy" | "tablesdb";
|
30
35
|
}>;
|
36
|
+
/**
|
37
|
+
* Check if session authentication is available for a project
|
38
|
+
*/
|
39
|
+
export declare const checkSessionAuth: (endpoint: string, project: string) => boolean;
|