appwrite-utils-cli 1.7.2 → 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 +64 -16
- 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 +72 -18
@@ -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,80 @@ export class ClientFactory {
|
|
60
60
|
const client = new Client()
|
61
61
|
.setEndpoint(config.appwriteEndpoint)
|
62
62
|
.setProject(config.appwriteProject);
|
63
|
-
// Apply authentication
|
64
|
-
|
65
|
-
|
63
|
+
// Apply authentication based on authMethod preference with mode headers
|
64
|
+
// Mode headers: "admin" for sessions (elevated permissions), "default" for API keys
|
65
|
+
const authMethod = config.authMethod || "auto";
|
66
|
+
logger.debug("Applying authentication with mode headers", {
|
67
|
+
prefix: "ClientFactory",
|
68
|
+
authMethod,
|
69
|
+
hasApiKey: !!config.appwriteKey,
|
70
|
+
hasSession: !!config.sessionCookie,
|
71
|
+
});
|
72
|
+
if (authMethod === "session") {
|
73
|
+
// Explicit session preference - use only session with admin mode
|
74
|
+
if (!config.sessionCookie) {
|
75
|
+
const error = new Error("authMethod set to 'session' but no session cookie available.\n\n" +
|
76
|
+
"Either:\n" +
|
77
|
+
" - Run 'appwrite login' to create a session\n" +
|
78
|
+
" - Change authMethod to 'apikey' or 'auto'\n" +
|
79
|
+
" - Provide --sessionCookie flag");
|
80
|
+
logger.error("Failed to create client - session required", { prefix: "ClientFactory" });
|
81
|
+
throw error;
|
82
|
+
}
|
66
83
|
client.setSession(config.sessionCookie);
|
67
|
-
|
84
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
85
|
+
logger.debug("Applied session authentication with admin mode (explicit preference)", {
|
68
86
|
prefix: "ClientFactory",
|
69
87
|
email: config.sessionMetadata?.email,
|
70
88
|
});
|
71
89
|
}
|
72
|
-
else if (
|
73
|
-
// API key
|
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
|
+
}
|
74
101
|
client.setKey(config.appwriteKey);
|
75
|
-
|
102
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
103
|
+
logger.debug("Applied API key authentication with default mode (explicit preference)", {
|
76
104
|
prefix: "ClientFactory",
|
77
105
|
});
|
78
106
|
}
|
79
107
|
else {
|
80
|
-
//
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
"
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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)", {
|
113
|
+
prefix: "ClientFactory",
|
114
|
+
email: config.sessionMetadata?.email,
|
115
|
+
});
|
116
|
+
}
|
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)", {
|
121
|
+
prefix: "ClientFactory",
|
122
|
+
});
|
123
|
+
}
|
124
|
+
else {
|
125
|
+
// No authentication available
|
126
|
+
const error = new Error("No authentication method available in configuration.\n\n" +
|
127
|
+
"Expected either:\n" +
|
128
|
+
" - config.sessionCookie (from session authentication via 'appwrite login')\n" +
|
129
|
+
" - config.appwriteKey (from config file, CLI flags, or environment)\n\n" +
|
130
|
+
"Suggestion:\n" +
|
131
|
+
" - Run 'appwrite login' to create a session, OR\n" +
|
132
|
+
" - Add appwriteKey to your config file, OR\n" +
|
133
|
+
" - Provide --apiKey flag");
|
134
|
+
logger.error("Failed to create client - no authentication", { prefix: "ClientFactory" });
|
135
|
+
throw error;
|
136
|
+
}
|
89
137
|
}
|
90
138
|
// Create adapter with version detection
|
91
139
|
// AdapterFactory uses internal caching, so repeated calls are fast
|
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,32 +67,86 @@ export class ClientFactory {
|
|
67
67
|
.setEndpoint(config.appwriteEndpoint)
|
68
68
|
.setProject(config.appwriteProject);
|
69
69
|
|
70
|
-
// Apply authentication
|
71
|
-
|
72
|
-
|
70
|
+
// Apply authentication based on authMethod preference with mode headers
|
71
|
+
// Mode headers: "admin" for sessions (elevated permissions), "default" for API keys
|
72
|
+
const authMethod = config.authMethod || "auto";
|
73
|
+
|
74
|
+
logger.debug("Applying authentication with mode headers", {
|
75
|
+
prefix: "ClientFactory",
|
76
|
+
authMethod,
|
77
|
+
hasApiKey: !!config.appwriteKey,
|
78
|
+
hasSession: !!config.sessionCookie,
|
79
|
+
});
|
80
|
+
|
81
|
+
if (authMethod === "session") {
|
82
|
+
// Explicit session preference - use only session with admin mode
|
83
|
+
if (!config.sessionCookie) {
|
84
|
+
const error = new Error(
|
85
|
+
"authMethod set to 'session' but no session cookie available.\n\n" +
|
86
|
+
"Either:\n" +
|
87
|
+
" - Run 'appwrite login' to create a session\n" +
|
88
|
+
" - Change authMethod to 'apikey' or 'auto'\n" +
|
89
|
+
" - Provide --sessionCookie flag"
|
90
|
+
);
|
91
|
+
logger.error("Failed to create client - session required", { prefix: "ClientFactory" });
|
92
|
+
throw error;
|
93
|
+
}
|
73
94
|
client.setSession(config.sessionCookie);
|
74
|
-
|
95
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
96
|
+
logger.debug("Applied session authentication with admin mode (explicit preference)", {
|
75
97
|
prefix: "ClientFactory",
|
76
98
|
email: config.sessionMetadata?.email,
|
77
99
|
});
|
78
|
-
|
79
|
-
|
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
|
+
}
|
80
114
|
client.setKey(config.appwriteKey);
|
81
|
-
|
115
|
+
client.headers['X-Appwrite-Mode'] = 'default';
|
116
|
+
logger.debug("Applied API key authentication with default mode (explicit preference)", {
|
82
117
|
prefix: "ClientFactory",
|
83
118
|
});
|
119
|
+
|
84
120
|
} else {
|
85
|
-
//
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
"
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
)
|
94
|
-
|
95
|
-
|
121
|
+
// Auto mode: Prefer session with admin mode (like official CLI), fallback to API key
|
122
|
+
if (config.sessionCookie) {
|
123
|
+
client.setSession(config.sessionCookie);
|
124
|
+
client.headers['X-Appwrite-Mode'] = 'admin';
|
125
|
+
logger.debug("Applied session authentication with admin mode (auto - preferred)", {
|
126
|
+
prefix: "ClientFactory",
|
127
|
+
email: config.sessionMetadata?.email,
|
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
|
+
});
|
135
|
+
} else {
|
136
|
+
// No authentication available
|
137
|
+
const error = new Error(
|
138
|
+
"No authentication method available in configuration.\n\n" +
|
139
|
+
"Expected either:\n" +
|
140
|
+
" - config.sessionCookie (from session authentication via 'appwrite login')\n" +
|
141
|
+
" - config.appwriteKey (from config file, CLI flags, or environment)\n\n" +
|
142
|
+
"Suggestion:\n" +
|
143
|
+
" - Run 'appwrite login' to create a session, OR\n" +
|
144
|
+
" - Add appwriteKey to your config file, OR\n" +
|
145
|
+
" - Provide --apiKey flag"
|
146
|
+
);
|
147
|
+
logger.error("Failed to create client - no authentication", { prefix: "ClientFactory" });
|
148
|
+
throw error;
|
149
|
+
}
|
96
150
|
}
|
97
151
|
|
98
152
|
// Create adapter with version detection
|