appwrite-utils-cli 1.7.3 → 1.7.4
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/dist/adapters/AdapterFactory.js +14 -2
- package/dist/config/ConfigManager.js +3 -20
- package/dist/config/services/ConfigMergeService.js +2 -5
- package/dist/utils/ClientFactory.js +37 -32
- package/package.json +1 -1
- package/src/adapters/AdapterFactory.ts +12 -2
- package/src/config/ConfigManager.ts +4 -24
- package/src/config/services/ConfigMergeService.ts +2 -5
- package/src/utils/ClientFactory.ts +39 -34
@@ -178,9 +178,11 @@ export class AdapterFactory {
|
|
178
178
|
client = new Client()
|
179
179
|
.setEndpoint(config.appwriteEndpoint)
|
180
180
|
.setProject(config.appwriteProject);
|
181
|
-
// Set authentication method
|
181
|
+
// Set authentication method with mode headers
|
182
|
+
// Prefer session with admin mode, fallback to API key with default mode
|
182
183
|
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
183
184
|
client.setSession(config.sessionCookie);
|
185
|
+
client.setHeader('X-Appwrite-Mode', 'admin');
|
184
186
|
logger.debug('Using session authentication for TablesDB adapter', {
|
185
187
|
project: config.appwriteProject,
|
186
188
|
operation: 'createTablesDBAdapter'
|
@@ -188,11 +190,15 @@ export class AdapterFactory {
|
|
188
190
|
}
|
189
191
|
else if (config.appwriteKey) {
|
190
192
|
client.setKey(config.appwriteKey);
|
193
|
+
client.setHeader('X-Appwrite-Mode', 'default');
|
191
194
|
logger.debug('Using API key authentication for TablesDB adapter', {
|
192
195
|
project: config.appwriteProject,
|
193
196
|
operation: 'createTablesDBAdapter'
|
194
197
|
});
|
195
198
|
}
|
199
|
+
else {
|
200
|
+
throw new Error("No authentication available for adapter");
|
201
|
+
}
|
196
202
|
}
|
197
203
|
const tablesDB = new TablesDB(client);
|
198
204
|
const adapter = new TablesDBAdapter(tablesDB);
|
@@ -246,9 +252,11 @@ export class AdapterFactory {
|
|
246
252
|
client = new Client()
|
247
253
|
.setEndpoint(config.appwriteEndpoint)
|
248
254
|
.setProject(config.appwriteProject);
|
249
|
-
// Set authentication method
|
255
|
+
// Set authentication method with mode headers
|
256
|
+
// Prefer session with admin mode, fallback to API key with default mode
|
250
257
|
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
251
258
|
client.setSession(config.sessionCookie);
|
259
|
+
client.setHeader('X-Appwrite-Mode', 'admin');
|
252
260
|
logger.debug('Using session authentication for Legacy adapter', {
|
253
261
|
project: config.appwriteProject,
|
254
262
|
operation: 'createLegacyAdapter'
|
@@ -256,11 +264,15 @@ export class AdapterFactory {
|
|
256
264
|
}
|
257
265
|
else if (config.appwriteKey) {
|
258
266
|
client.setKey(config.appwriteKey);
|
267
|
+
client.setHeader('X-Appwrite-Mode', 'default');
|
259
268
|
logger.debug('Using API key authentication for Legacy adapter', {
|
260
269
|
project: config.appwriteProject,
|
261
270
|
operation: 'createLegacyAdapter'
|
262
271
|
});
|
263
272
|
}
|
273
|
+
else {
|
274
|
+
throw new Error("No authentication available for adapter");
|
275
|
+
}
|
264
276
|
}
|
265
277
|
const databases = new Databases(client);
|
266
278
|
const adapter = new LegacyAdapter(databases);
|
@@ -149,26 +149,9 @@ export class ConfigManager {
|
|
149
149
|
logger.debug(`Config discovered at: ${configPath}`, { prefix: "ConfigManager" });
|
150
150
|
// 3. Load config from file
|
151
151
|
let config = await this.loaderService.loadFromPath(configPath);
|
152
|
-
// 4. Load session authentication
|
153
|
-
|
154
|
-
|
155
|
-
// - Load if authMethod is "auto" or undefined AND no API key exists
|
156
|
-
// - Skip if authMethod is "apikey" or if API key is present with "auto" mode
|
157
|
-
const hasApiKey = !!(config.appwriteKey && config.appwriteKey.trim().length > 0);
|
158
|
-
const authMethod = config.authMethod || "auto";
|
159
|
-
const shouldLoadSession = options.sessionOverride !== undefined ||
|
160
|
-
authMethod === "session" ||
|
161
|
-
(authMethod === "auto" && !hasApiKey);
|
162
|
-
logger.debug("Session loading decision", {
|
163
|
-
prefix: "ConfigManager",
|
164
|
-
hasApiKey,
|
165
|
-
authMethod,
|
166
|
-
shouldLoadSession,
|
167
|
-
});
|
168
|
-
const session = shouldLoadSession
|
169
|
-
? options.sessionOverride ||
|
170
|
-
(await this.sessionService.findSession(config.appwriteEndpoint, config.appwriteProject))
|
171
|
-
: null;
|
152
|
+
// 4. Load session authentication
|
153
|
+
const session = options.sessionOverride ||
|
154
|
+
(await this.sessionService.findSession(config.appwriteEndpoint, config.appwriteProject));
|
172
155
|
// 5. Merge session into config
|
173
156
|
if (session) {
|
174
157
|
logger.debug("Merging session authentication into config", { prefix: "ConfigManager" });
|
@@ -57,11 +57,8 @@ export class ConfigMergeService {
|
|
57
57
|
const merged = cloneDeep(config);
|
58
58
|
// Add session authentication (map 'cookie' to 'sessionCookie')
|
59
59
|
merged.sessionCookie = session.cookie;
|
60
|
-
//
|
61
|
-
|
62
|
-
if (merged.authMethod !== "apikey") {
|
63
|
-
merged.authMethod = "session";
|
64
|
-
}
|
60
|
+
// Set authMethod to session (priority handled by ClientFactory)
|
61
|
+
merged.authMethod = "session";
|
65
62
|
// Add session metadata if available
|
66
63
|
if (session.email || session.expiresAt) {
|
67
64
|
merged.sessionMetadata = {
|
@@ -60,32 +60,17 @@ export class ClientFactory {
|
|
60
60
|
const client = new Client()
|
61
61
|
.setEndpoint(config.appwriteEndpoint)
|
62
62
|
.setProject(config.appwriteProject);
|
63
|
-
// Apply authentication based on authMethod preference
|
63
|
+
// Apply authentication based on authMethod preference with mode headers
|
64
|
+
// Mode headers: "admin" for sessions (elevated permissions), "default" for API keys
|
64
65
|
const authMethod = config.authMethod || "auto";
|
65
|
-
logger.debug("Applying authentication", {
|
66
|
+
logger.debug("Applying authentication with mode headers", {
|
66
67
|
prefix: "ClientFactory",
|
67
68
|
authMethod,
|
68
69
|
hasApiKey: !!config.appwriteKey,
|
69
70
|
hasSession: !!config.sessionCookie,
|
70
71
|
});
|
71
|
-
if (authMethod === "
|
72
|
-
// Explicit
|
73
|
-
if (!config.appwriteKey || config.appwriteKey.trim().length === 0) {
|
74
|
-
const error = new Error("authMethod set to 'apikey' but no API key provided.\n\n" +
|
75
|
-
"Either:\n" +
|
76
|
-
" - Set appwriteKey in your config file\n" +
|
77
|
-
" - Provide --apiKey flag\n" +
|
78
|
-
" - Set APPWRITE_API_KEY environment variable");
|
79
|
-
logger.error("Failed to create client - API key required", { prefix: "ClientFactory" });
|
80
|
-
throw error;
|
81
|
-
}
|
82
|
-
client.setKey(config.appwriteKey);
|
83
|
-
logger.debug("Applied API key authentication (explicit preference)", {
|
84
|
-
prefix: "ClientFactory",
|
85
|
-
});
|
86
|
-
}
|
87
|
-
else if (authMethod === "session") {
|
88
|
-
// Explicit session preference - use only session
|
72
|
+
if (authMethod === "session") {
|
73
|
+
// Explicit session preference - use only session with admin mode
|
89
74
|
if (!config.sessionCookie) {
|
90
75
|
const error = new Error("authMethod set to 'session' but no session cookie available.\n\n" +
|
91
76
|
"Either:\n" +
|
@@ -96,35 +81,55 @@ export class ClientFactory {
|
|
96
81
|
throw error;
|
97
82
|
}
|
98
83
|
client.setSession(config.sessionCookie);
|
99
|
-
|
84
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
85
|
+
logger.debug("Applied session authentication with admin mode (explicit preference)", {
|
100
86
|
prefix: "ClientFactory",
|
101
87
|
email: config.sessionMetadata?.email,
|
102
88
|
});
|
103
89
|
}
|
90
|
+
else if (authMethod === "apikey") {
|
91
|
+
// Explicit API key preference - use only API key with default mode
|
92
|
+
if (!config.appwriteKey || config.appwriteKey.trim().length === 0) {
|
93
|
+
const error = new Error("authMethod set to 'apikey' but no API key provided.\n\n" +
|
94
|
+
"Either:\n" +
|
95
|
+
" - Set appwriteKey in your config file\n" +
|
96
|
+
" - Provide --apiKey flag\n" +
|
97
|
+
" - Set APPWRITE_API_KEY environment variable");
|
98
|
+
logger.error("Failed to create client - API key required", { prefix: "ClientFactory" });
|
99
|
+
throw error;
|
100
|
+
}
|
101
|
+
client.setKey(config.appwriteKey);
|
102
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
103
|
+
logger.debug("Applied API key authentication with default mode (explicit preference)", {
|
104
|
+
prefix: "ClientFactory",
|
105
|
+
});
|
106
|
+
}
|
104
107
|
else {
|
105
|
-
// Auto mode: Prefer
|
106
|
-
if (config.
|
107
|
-
client.
|
108
|
-
|
108
|
+
// Auto mode: Prefer session with admin mode (like official CLI), fallback to API key
|
109
|
+
if (config.sessionCookie) {
|
110
|
+
client.setSession(config.sessionCookie);
|
111
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
112
|
+
logger.debug("Applied session authentication with admin mode (auto - preferred)", {
|
109
113
|
prefix: "ClientFactory",
|
114
|
+
email: config.sessionMetadata?.email,
|
110
115
|
});
|
111
116
|
}
|
112
|
-
else if (config.
|
113
|
-
client.
|
114
|
-
|
117
|
+
else if (config.appwriteKey && config.appwriteKey.trim().length > 0) {
|
118
|
+
client.setKey(config.appwriteKey);
|
119
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
120
|
+
logger.debug("Applied API key authentication with default mode (auto - fallback)", {
|
115
121
|
prefix: "ClientFactory",
|
116
|
-
email: config.sessionMetadata?.email,
|
117
122
|
});
|
118
123
|
}
|
119
124
|
else {
|
120
125
|
// No authentication available
|
121
126
|
const error = new Error("No authentication method available in configuration.\n\n" +
|
122
127
|
"Expected either:\n" +
|
123
|
-
" - config.
|
124
|
-
" - config.
|
128
|
+
" - config.sessionCookie (from session authentication via 'appwrite login')\n" +
|
129
|
+
" - config.appwriteKey (from config file, CLI flags, or environment)\n\n" +
|
125
130
|
"Suggestion:\n" +
|
126
|
-
" - Add appwriteKey to your config file, OR\n" +
|
127
131
|
" - Run 'appwrite login' to create a session, OR\n" +
|
132
|
+
" - Add appwriteKey to your config file, OR\n" +
|
128
133
|
" - Provide --apiKey flag");
|
129
134
|
logger.error("Failed to create client - no authentication", { prefix: "ClientFactory" });
|
130
135
|
throw error;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "appwrite-utils-cli",
|
3
3
|
"description": "Appwrite Utility Functions to help with database management, data conversion, data import, migrations, and much more. Meant to be used as a CLI tool, I do not recommend installing this in frontend environments.",
|
4
|
-
"version": "1.7.
|
4
|
+
"version": "1.7.4",
|
5
5
|
"main": "src/main.ts",
|
6
6
|
"type": "module",
|
7
7
|
"repository": {
|
@@ -231,19 +231,24 @@ export class AdapterFactory {
|
|
231
231
|
.setEndpoint(config.appwriteEndpoint)
|
232
232
|
.setProject(config.appwriteProject);
|
233
233
|
|
234
|
-
// Set authentication method
|
234
|
+
// Set authentication method with mode headers
|
235
|
+
// Prefer session with admin mode, fallback to API key with default mode
|
235
236
|
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
236
237
|
(client as any).setSession(config.sessionCookie);
|
238
|
+
client.setHeader('X-Appwrite-Mode', 'admin');
|
237
239
|
logger.debug('Using session authentication for TablesDB adapter', {
|
238
240
|
project: config.appwriteProject,
|
239
241
|
operation: 'createTablesDBAdapter'
|
240
242
|
});
|
241
243
|
} else if (config.appwriteKey) {
|
242
244
|
client.setKey(config.appwriteKey);
|
245
|
+
client.setHeader('X-Appwrite-Mode', 'default');
|
243
246
|
logger.debug('Using API key authentication for TablesDB adapter', {
|
244
247
|
project: config.appwriteProject,
|
245
248
|
operation: 'createTablesDBAdapter'
|
246
249
|
});
|
250
|
+
} else {
|
251
|
+
throw new Error("No authentication available for adapter");
|
247
252
|
}
|
248
253
|
}
|
249
254
|
|
@@ -311,19 +316,24 @@ export class AdapterFactory {
|
|
311
316
|
.setEndpoint(config.appwriteEndpoint)
|
312
317
|
.setProject(config.appwriteProject);
|
313
318
|
|
314
|
-
// Set authentication method
|
319
|
+
// Set authentication method with mode headers
|
320
|
+
// Prefer session with admin mode, fallback to API key with default mode
|
315
321
|
if (config.sessionCookie && isValidSessionCookie(config.sessionCookie)) {
|
316
322
|
(client as any).setSession(config.sessionCookie);
|
323
|
+
client.setHeader('X-Appwrite-Mode', 'admin');
|
317
324
|
logger.debug('Using session authentication for Legacy adapter', {
|
318
325
|
project: config.appwriteProject,
|
319
326
|
operation: 'createLegacyAdapter'
|
320
327
|
});
|
321
328
|
} else if (config.appwriteKey) {
|
322
329
|
client.setKey(config.appwriteKey);
|
330
|
+
client.setHeader('X-Appwrite-Mode', 'default');
|
323
331
|
logger.debug('Using API key authentication for Legacy adapter', {
|
324
332
|
project: config.appwriteProject,
|
325
333
|
operation: 'createLegacyAdapter'
|
326
334
|
});
|
335
|
+
} else {
|
336
|
+
throw new Error("No authentication available for adapter");
|
327
337
|
}
|
328
338
|
}
|
329
339
|
|
@@ -249,30 +249,10 @@ export class ConfigManager {
|
|
249
249
|
// 3. Load config from file
|
250
250
|
let config = await this.loaderService.loadFromPath(configPath);
|
251
251
|
|
252
|
-
// 4. Load session authentication
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
// - Skip if authMethod is "apikey" or if API key is present with "auto" mode
|
257
|
-
const hasApiKey = !!(config.appwriteKey && config.appwriteKey.trim().length > 0);
|
258
|
-
const authMethod = config.authMethod || "auto";
|
259
|
-
|
260
|
-
const shouldLoadSession =
|
261
|
-
options.sessionOverride !== undefined ||
|
262
|
-
authMethod === "session" ||
|
263
|
-
(authMethod === "auto" && !hasApiKey);
|
264
|
-
|
265
|
-
logger.debug("Session loading decision", {
|
266
|
-
prefix: "ConfigManager",
|
267
|
-
hasApiKey,
|
268
|
-
authMethod,
|
269
|
-
shouldLoadSession,
|
270
|
-
});
|
271
|
-
|
272
|
-
const session = shouldLoadSession
|
273
|
-
? options.sessionOverride ||
|
274
|
-
(await this.sessionService.findSession(config.appwriteEndpoint, config.appwriteProject))
|
275
|
-
: null;
|
252
|
+
// 4. Load session authentication
|
253
|
+
const session =
|
254
|
+
options.sessionOverride ||
|
255
|
+
(await this.sessionService.findSession(config.appwriteEndpoint, config.appwriteProject));
|
276
256
|
|
277
257
|
// 5. Merge session into config
|
278
258
|
if (session) {
|
@@ -81,11 +81,8 @@ export class ConfigMergeService {
|
|
81
81
|
// Add session authentication (map 'cookie' to 'sessionCookie')
|
82
82
|
merged.sessionCookie = session.cookie;
|
83
83
|
|
84
|
-
//
|
85
|
-
|
86
|
-
if (merged.authMethod !== "apikey") {
|
87
|
-
merged.authMethod = "session";
|
88
|
-
}
|
84
|
+
// Set authMethod to session (priority handled by ClientFactory)
|
85
|
+
merged.authMethod = "session";
|
89
86
|
|
90
87
|
// Add session metadata if available
|
91
88
|
if (session.email || session.expiresAt) {
|
@@ -67,36 +67,19 @@ export class ClientFactory {
|
|
67
67
|
.setEndpoint(config.appwriteEndpoint)
|
68
68
|
.setProject(config.appwriteProject);
|
69
69
|
|
70
|
-
// Apply authentication based on authMethod preference
|
70
|
+
// Apply authentication based on authMethod preference with mode headers
|
71
|
+
// Mode headers: "admin" for sessions (elevated permissions), "default" for API keys
|
71
72
|
const authMethod = config.authMethod || "auto";
|
72
73
|
|
73
|
-
logger.debug("Applying authentication", {
|
74
|
+
logger.debug("Applying authentication with mode headers", {
|
74
75
|
prefix: "ClientFactory",
|
75
76
|
authMethod,
|
76
77
|
hasApiKey: !!config.appwriteKey,
|
77
78
|
hasSession: !!config.sessionCookie,
|
78
79
|
});
|
79
80
|
|
80
|
-
if (authMethod === "
|
81
|
-
// Explicit
|
82
|
-
if (!config.appwriteKey || config.appwriteKey.trim().length === 0) {
|
83
|
-
const error = new Error(
|
84
|
-
"authMethod set to 'apikey' but no API key provided.\n\n" +
|
85
|
-
"Either:\n" +
|
86
|
-
" - Set appwriteKey in your config file\n" +
|
87
|
-
" - Provide --apiKey flag\n" +
|
88
|
-
" - Set APPWRITE_API_KEY environment variable"
|
89
|
-
);
|
90
|
-
logger.error("Failed to create client - API key required", { prefix: "ClientFactory" });
|
91
|
-
throw error;
|
92
|
-
}
|
93
|
-
client.setKey(config.appwriteKey);
|
94
|
-
logger.debug("Applied API key authentication (explicit preference)", {
|
95
|
-
prefix: "ClientFactory",
|
96
|
-
});
|
97
|
-
|
98
|
-
} else if (authMethod === "session") {
|
99
|
-
// Explicit session preference - use only session
|
81
|
+
if (authMethod === "session") {
|
82
|
+
// Explicit session preference - use only session with admin mode
|
100
83
|
if (!config.sessionCookie) {
|
101
84
|
const error = new Error(
|
102
85
|
"authMethod set to 'session' but no session cookie available.\n\n" +
|
@@ -109,34 +92,56 @@ export class ClientFactory {
|
|
109
92
|
throw error;
|
110
93
|
}
|
111
94
|
client.setSession(config.sessionCookie);
|
112
|
-
|
95
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
96
|
+
logger.debug("Applied session authentication with admin mode (explicit preference)", {
|
113
97
|
prefix: "ClientFactory",
|
114
98
|
email: config.sessionMetadata?.email,
|
115
99
|
});
|
116
100
|
|
101
|
+
} else if (authMethod === "apikey") {
|
102
|
+
// Explicit API key preference - use only API key with default mode
|
103
|
+
if (!config.appwriteKey || config.appwriteKey.trim().length === 0) {
|
104
|
+
const error = new Error(
|
105
|
+
"authMethod set to 'apikey' but no API key provided.\n\n" +
|
106
|
+
"Either:\n" +
|
107
|
+
" - Set appwriteKey in your config file\n" +
|
108
|
+
" - Provide --apiKey flag\n" +
|
109
|
+
" - Set APPWRITE_API_KEY environment variable"
|
110
|
+
);
|
111
|
+
logger.error("Failed to create client - API key required", { prefix: "ClientFactory" });
|
112
|
+
throw error;
|
113
|
+
}
|
114
|
+
client.setKey(config.appwriteKey);
|
115
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
116
|
+
logger.debug("Applied API key authentication with default mode (explicit preference)", {
|
117
|
+
prefix: "ClientFactory",
|
118
|
+
});
|
119
|
+
|
117
120
|
} else {
|
118
|
-
// Auto mode: Prefer
|
119
|
-
if (config.
|
120
|
-
client.setKey(config.appwriteKey);
|
121
|
-
logger.debug("Applied API key authentication (auto mode - preferred)", {
|
122
|
-
prefix: "ClientFactory",
|
123
|
-
});
|
124
|
-
} else if (config.sessionCookie) {
|
121
|
+
// Auto mode: Prefer session with admin mode (like official CLI), fallback to API key
|
122
|
+
if (config.sessionCookie) {
|
125
123
|
client.setSession(config.sessionCookie);
|
126
|
-
|
124
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
125
|
+
logger.debug("Applied session authentication with admin mode (auto - preferred)", {
|
127
126
|
prefix: "ClientFactory",
|
128
127
|
email: config.sessionMetadata?.email,
|
129
128
|
});
|
129
|
+
} else if (config.appwriteKey && config.appwriteKey.trim().length > 0) {
|
130
|
+
client.setKey(config.appwriteKey);
|
131
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
132
|
+
logger.debug("Applied API key authentication with default mode (auto - fallback)", {
|
133
|
+
prefix: "ClientFactory",
|
134
|
+
});
|
130
135
|
} else {
|
131
136
|
// No authentication available
|
132
137
|
const error = new Error(
|
133
138
|
"No authentication method available in configuration.\n\n" +
|
134
139
|
"Expected either:\n" +
|
135
|
-
" - config.
|
136
|
-
" - config.
|
140
|
+
" - config.sessionCookie (from session authentication via 'appwrite login')\n" +
|
141
|
+
" - config.appwriteKey (from config file, CLI flags, or environment)\n\n" +
|
137
142
|
"Suggestion:\n" +
|
138
|
-
" - Add appwriteKey to your config file, OR\n" +
|
139
143
|
" - Run 'appwrite login' to create a session, OR\n" +
|
144
|
+
" - Add appwriteKey to your config file, OR\n" +
|
140
145
|
" - Provide --apiKey flag"
|
141
146
|
);
|
142
147
|
logger.error("Failed to create client - no authentication", { prefix: "ClientFactory" });
|