@hasna/connectors 0.3.4 → 0.3.6

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/bin/index.js CHANGED
@@ -4280,8 +4280,8 @@ function saveApiKey(name, key, field) {
4280
4280
  writeFileSync2(configFile, JSON.stringify(config, null, 2));
4281
4281
  return;
4282
4282
  }
4283
- mkdirSync2(join3(configDir, "profiles"), { recursive: true });
4284
- writeFileSync2(profileFile, JSON.stringify({ [keyField]: key }, null, 2));
4283
+ mkdirSync2(profileDir, { recursive: true });
4284
+ writeFileSync2(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
4285
4285
  }
4286
4286
  function guessKeyField(name) {
4287
4287
  const docs = getConnectorDocs(name);
@@ -6701,7 +6701,7 @@ var PRESETS = {
6701
6701
  commerce: { description: "Commerce and finance", connectors: ["stripe", "shopify", "revolut", "mercury", "pandadoc"] }
6702
6702
  };
6703
6703
  var program2 = new Command;
6704
- program2.name("connectors").description("Install API connectors for your project").version("0.3.4");
6704
+ program2.name("connectors").description("Install API connectors for your project").version("0.3.6");
6705
6705
  program2.command("interactive", { isDefault: true }).alias("i").description("Interactive connector browser").action(() => {
6706
6706
  if (!isTTY) {
6707
6707
  console.log(`Non-interactive environment detected. Use a subcommand:
package/bin/mcp.js CHANGED
@@ -20188,8 +20188,8 @@ function saveApiKey(name, key, field) {
20188
20188
  writeFileSync2(configFile, JSON.stringify(config2, null, 2));
20189
20189
  return;
20190
20190
  }
20191
- mkdirSync2(join3(configDir, "profiles"), { recursive: true });
20192
- writeFileSync2(profileFile, JSON.stringify({ [keyField]: key }, null, 2));
20191
+ mkdirSync2(profileDir, { recursive: true });
20192
+ writeFileSync2(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
20193
20193
  }
20194
20194
  function guessKeyField(name) {
20195
20195
  const docs = getConnectorDocs(name);
@@ -20309,7 +20309,7 @@ async function getConnectorCommandHelp(name, command) {
20309
20309
  loadConnectorVersions();
20310
20310
  var server = new McpServer({
20311
20311
  name: "connectors",
20312
- version: "0.3.4"
20312
+ version: "0.3.6"
20313
20313
  });
20314
20314
  server.registerTool("search_connectors", {
20315
20315
  title: "Search Connectors",
package/bin/serve.js CHANGED
@@ -790,8 +790,8 @@ function saveApiKey(name, key, field) {
790
790
  writeFileSync2(configFile, JSON.stringify(config, null, 2));
791
791
  return;
792
792
  }
793
- mkdirSync2(join3(configDir, "profiles"), { recursive: true });
794
- writeFileSync2(profileFile, JSON.stringify({ [keyField]: key }, null, 2));
793
+ mkdirSync2(profileDir, { recursive: true });
794
+ writeFileSync2(join3(profileDir, "config.json"), JSON.stringify({ [keyField]: key }, null, 2));
795
795
  }
796
796
  function guessKeyField(name) {
797
797
  const docs = getConnectorDocs(name);
@@ -170,6 +170,49 @@ export function saveProfile(config: ProfileConfig, profile?: string): void {
170
170
  writeFileSync(getProfilePath(profileName), JSON.stringify(config, null, 2));
171
171
  }
172
172
 
173
+ // ============================================
174
+ // OAuth2 Credentials (Client ID/Secret) - Root credentials.json (shared across profiles)
175
+ // ============================================
176
+
177
+ const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.json');
178
+
179
+ interface CredentialsConfig {
180
+ clientId?: string;
181
+ clientSecret?: string;
182
+ }
183
+
184
+ function loadCredentials(): CredentialsConfig {
185
+ ensureConfigDir();
186
+
187
+ if (!existsSync(CREDENTIALS_FILE)) {
188
+ // Migration: check if credentials exist in any profile and copy to base
189
+ const profiles = listProfiles();
190
+ for (const prof of profiles) {
191
+ const profileConfig = loadProfile(prof);
192
+ if (profileConfig.clientId && profileConfig.clientSecret) {
193
+ const creds = {
194
+ clientId: profileConfig.clientId,
195
+ clientSecret: profileConfig.clientSecret,
196
+ };
197
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
198
+ return creds;
199
+ }
200
+ }
201
+ return {};
202
+ }
203
+
204
+ try {
205
+ return JSON.parse(readFileSync(CREDENTIALS_FILE, 'utf-8'));
206
+ } catch {
207
+ return {};
208
+ }
209
+ }
210
+
211
+ function saveCredentials(creds: CredentialsConfig): void {
212
+ ensureConfigDir();
213
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
214
+ }
215
+
173
216
  // ============================================
174
217
  // Token Management
175
218
  // ============================================
@@ -195,23 +238,23 @@ export function setRefreshToken(refreshToken: string): void {
195
238
  }
196
239
 
197
240
  export function getClientId(): string | undefined {
198
- return process.env.GOOGLE_CALENDAR_CLIENT_ID || loadProfile().clientId;
241
+ return process.env.GOOGLE_CALENDAR_CLIENT_ID || loadCredentials().clientId || loadProfile().clientId;
199
242
  }
200
243
 
201
244
  export function setClientId(clientId: string): void {
202
- const config = loadProfile();
203
- config.clientId = clientId;
204
- saveProfile(config);
245
+ const creds = loadCredentials();
246
+ creds.clientId = clientId;
247
+ saveCredentials(creds);
205
248
  }
206
249
 
207
250
  export function getClientSecret(): string | undefined {
208
- return process.env.GOOGLE_CALENDAR_CLIENT_SECRET || loadProfile().clientSecret;
251
+ return process.env.GOOGLE_CALENDAR_CLIENT_SECRET || loadCredentials().clientSecret || loadProfile().clientSecret;
209
252
  }
210
253
 
211
254
  export function setClientSecret(clientSecret: string): void {
212
- const config = loadProfile();
213
- config.clientSecret = clientSecret;
214
- saveProfile(config);
255
+ const creds = loadCredentials();
256
+ creds.clientSecret = clientSecret;
257
+ saveCredentials(creds);
215
258
  }
216
259
 
217
260
  export function setTokens(tokens: { accessToken: string; refreshToken?: string; expiresIn?: number }): void {
@@ -191,6 +191,49 @@ export function setApiKey(apiKey: string): void {
191
191
  saveProfile(config);
192
192
  }
193
193
 
194
+ // ============================================
195
+ // OAuth2 Credentials (Client ID/Secret) - Root credentials.json (shared across profiles)
196
+ // ============================================
197
+
198
+ const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.json');
199
+
200
+ interface CredentialsConfig {
201
+ clientId?: string;
202
+ clientSecret?: string;
203
+ }
204
+
205
+ function loadCredentials(): CredentialsConfig {
206
+ ensureConfigDir();
207
+
208
+ if (!existsSync(CREDENTIALS_FILE)) {
209
+ // Migration: check if credentials exist in any profile and copy to base
210
+ const profiles = listProfiles();
211
+ for (const prof of profiles) {
212
+ const profileConfig = loadProfile(prof);
213
+ if (profileConfig.clientId && profileConfig.clientSecret) {
214
+ const creds = {
215
+ clientId: profileConfig.clientId,
216
+ clientSecret: profileConfig.clientSecret,
217
+ };
218
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
219
+ return creds;
220
+ }
221
+ }
222
+ return {};
223
+ }
224
+
225
+ try {
226
+ return JSON.parse(readFileSync(CREDENTIALS_FILE, 'utf-8'));
227
+ } catch {
228
+ return {};
229
+ }
230
+ }
231
+
232
+ function saveCredentials(creds: CredentialsConfig): void {
233
+ ensureConfigDir();
234
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
235
+ }
236
+
194
237
  // ============================================
195
238
  // OAuth Token Management
196
239
  // ============================================
@@ -219,23 +262,23 @@ export function setRefreshToken(refreshToken: string): void {
219
262
  }
220
263
 
221
264
  export function getClientId(): string | undefined {
222
- return process.env.GOOGLE_CLIENT_ID || loadProfile().clientId;
265
+ return process.env.GOOGLE_CLIENT_ID || loadCredentials().clientId || loadProfile().clientId;
223
266
  }
224
267
 
225
268
  export function setClientId(clientId: string): void {
226
- const config = loadProfile();
227
- config.clientId = clientId;
228
- saveProfile(config);
269
+ const creds = loadCredentials();
270
+ creds.clientId = clientId;
271
+ saveCredentials(creds);
229
272
  }
230
273
 
231
274
  export function getClientSecret(): string | undefined {
232
- return process.env.GOOGLE_CLIENT_SECRET || loadProfile().clientSecret;
275
+ return process.env.GOOGLE_CLIENT_SECRET || loadCredentials().clientSecret || loadProfile().clientSecret;
233
276
  }
234
277
 
235
278
  export function setClientSecret(clientSecret: string): void {
236
- const config = loadProfile();
237
- config.clientSecret = clientSecret;
238
- saveProfile(config);
279
+ const creds = loadCredentials();
280
+ creds.clientSecret = clientSecret;
281
+ saveCredentials(creds);
239
282
  }
240
283
 
241
284
  export function setOAuthTokens(accessToken: string, refreshToken?: string, expiresAt?: number): void {
@@ -193,28 +193,71 @@ export function saveProfile(config: ProfileConfig, profile?: string): void {
193
193
  writeFileSync(join(profileDir, 'config.json'), JSON.stringify(config, null, 2));
194
194
  }
195
195
 
196
+ // ============================================
197
+ // OAuth2 Credentials (Client ID/Secret) - Root credentials.json (shared across profiles)
198
+ // ============================================
199
+
200
+ const CREDENTIALS_FILE = join(BASE_CONFIG_DIR, 'credentials.json');
201
+
202
+ interface CredentialsConfig {
203
+ clientId?: string;
204
+ clientSecret?: string;
205
+ }
206
+
207
+ function loadCredentials(): CredentialsConfig {
208
+ ensureBaseConfigDir();
209
+
210
+ if (!existsSync(CREDENTIALS_FILE)) {
211
+ // Migration: check if credentials exist in any profile and copy to base
212
+ const profiles = listProfiles();
213
+ for (const prof of profiles) {
214
+ const profileConfig = loadProfile(prof);
215
+ if (profileConfig.clientId && profileConfig.clientSecret) {
216
+ const creds = {
217
+ clientId: profileConfig.clientId,
218
+ clientSecret: profileConfig.clientSecret,
219
+ };
220
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
221
+ return creds;
222
+ }
223
+ }
224
+ return {};
225
+ }
226
+
227
+ try {
228
+ return JSON.parse(readFileSync(CREDENTIALS_FILE, 'utf-8'));
229
+ } catch {
230
+ return {};
231
+ }
232
+ }
233
+
234
+ function saveCredentials(creds: CredentialsConfig): void {
235
+ ensureBaseConfigDir();
236
+ writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), { mode: 0o600 });
237
+ }
238
+
196
239
  // ============================================
197
240
  // OAuth Credentials
198
241
  // ============================================
199
242
 
200
243
  export function getClientId(): string | undefined {
201
- return process.env.GOOGLE_CLIENT_ID || loadProfile().clientId;
244
+ return process.env.GOOGLE_CLIENT_ID || loadCredentials().clientId || loadProfile().clientId;
202
245
  }
203
246
 
204
247
  export function setClientId(clientId: string): void {
205
- const config = loadProfile();
206
- config.clientId = clientId;
207
- saveProfile(config);
248
+ const creds = loadCredentials();
249
+ creds.clientId = clientId;
250
+ saveCredentials(creds);
208
251
  }
209
252
 
210
253
  export function getClientSecret(): string | undefined {
211
- return process.env.GOOGLE_CLIENT_SECRET || loadProfile().clientSecret;
254
+ return process.env.GOOGLE_CLIENT_SECRET || loadCredentials().clientSecret || loadProfile().clientSecret;
212
255
  }
213
256
 
214
257
  export function setClientSecret(clientSecret: string): void {
215
- const config = loadProfile();
216
- config.clientSecret = clientSecret;
217
- saveProfile(config);
258
+ const creds = loadCredentials();
259
+ creds.clientSecret = clientSecret;
260
+ saveCredentials(creds);
218
261
  }
219
262
 
220
263
  export function getAccessToken(): string | undefined {
@@ -248,10 +291,7 @@ export function setTokenExpiry(expiry: number): void {
248
291
  }
249
292
 
250
293
  export function setCredentials(clientId: string, clientSecret: string): void {
251
- const config = loadProfile();
252
- config.clientId = clientId;
253
- config.clientSecret = clientSecret;
254
- saveProfile(config);
294
+ saveCredentials({ clientId, clientSecret });
255
295
  }
256
296
 
257
297
  export function setTokens(accessToken: string, refreshToken: string | undefined, expiresIn: number): void {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/connectors",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "Open source connector library - Install API connectors with a single command",
5
5
  "type": "module",
6
6
  "bin": {