@ncukondo/gcal-cli 0.1.7 → 0.2.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/dist/index.js +86 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -587718,7 +587718,7 @@ function errorCodeToExitCode(code) {
|
|
|
587718
587718
|
// package.json
|
|
587719
587719
|
var package_default = {
|
|
587720
587720
|
name: "@ncukondo/gcal-cli",
|
|
587721
|
-
version: "0.1
|
|
587721
|
+
version: "0.2.1",
|
|
587722
587722
|
type: "module",
|
|
587723
587723
|
exports: {
|
|
587724
587724
|
".": "./dist/index.js"
|
|
@@ -587872,9 +587872,58 @@ function getClientCredentials(fs) {
|
|
|
587872
587872
|
}
|
|
587873
587873
|
throw new AuthError("AUTH_REQUIRED", "No client credentials found. Place client_secret.json in ~/.config/gcal-cli/ or set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET environment variables.");
|
|
587874
587874
|
}
|
|
587875
|
+
async function getClientCredentialsOrPrompt(fs, write, promptFn) {
|
|
587876
|
+
try {
|
|
587877
|
+
return getClientCredentials(fs);
|
|
587878
|
+
} catch (err) {
|
|
587879
|
+
if (!(err instanceof AuthError)) {
|
|
587880
|
+
throw err;
|
|
587881
|
+
}
|
|
587882
|
+
const { clientId, clientSecret } = await promptForClientCredentials(write, promptFn);
|
|
587883
|
+
saveClientCredentials(fs, clientId, clientSecret);
|
|
587884
|
+
return {
|
|
587885
|
+
clientId,
|
|
587886
|
+
clientSecret,
|
|
587887
|
+
redirectUri: DEFAULT_REDIRECT_URI
|
|
587888
|
+
};
|
|
587889
|
+
}
|
|
587890
|
+
}
|
|
587875
587891
|
function getCredentialsPath() {
|
|
587876
587892
|
return `${getCredentialsDir()}/credentials.json`;
|
|
587877
587893
|
}
|
|
587894
|
+
async function promptForClientCredentials(write, promptFn) {
|
|
587895
|
+
write("No client credentials found.");
|
|
587896
|
+
write("");
|
|
587897
|
+
write("To set up Google Calendar API access:");
|
|
587898
|
+
write(" 1. Go to https://console.cloud.google.com");
|
|
587899
|
+
write(" 2. Create a project and enable the Google Calendar API");
|
|
587900
|
+
write(" 3. Create OAuth 2.0 credentials (Desktop app)");
|
|
587901
|
+
write(" 4. Copy the Client ID and Client Secret below");
|
|
587902
|
+
write("");
|
|
587903
|
+
const clientId = (await promptFn("Client ID: ")).trim();
|
|
587904
|
+
if (!clientId) {
|
|
587905
|
+
throw new AuthError("AUTH_REQUIRED", "Client ID is required.");
|
|
587906
|
+
}
|
|
587907
|
+
const clientSecret = (await promptFn("Client Secret: ")).trim();
|
|
587908
|
+
if (!clientSecret) {
|
|
587909
|
+
throw new AuthError("AUTH_REQUIRED", "Client Secret is required.");
|
|
587910
|
+
}
|
|
587911
|
+
return { clientId, clientSecret };
|
|
587912
|
+
}
|
|
587913
|
+
function saveClientCredentials(fs, clientId, clientSecret) {
|
|
587914
|
+
const dir = getCredentialsDir();
|
|
587915
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
587916
|
+
const clientSecretPath = `${dir}/client_secret.json`;
|
|
587917
|
+
const data = {
|
|
587918
|
+
installed: {
|
|
587919
|
+
client_id: clientId,
|
|
587920
|
+
client_secret: clientSecret,
|
|
587921
|
+
redirect_uris: [DEFAULT_REDIRECT_URI]
|
|
587922
|
+
}
|
|
587923
|
+
};
|
|
587924
|
+
fs.writeFileSync(clientSecretPath, JSON.stringify(data, null, 2));
|
|
587925
|
+
fs.chmodSync(clientSecretPath, 384);
|
|
587926
|
+
}
|
|
587878
587927
|
function loadTokens(fs) {
|
|
587879
587928
|
const credPath = getCredentialsPath();
|
|
587880
587929
|
if (!fs.existsSync(credPath)) {
|
|
@@ -588036,14 +588085,18 @@ async function fetchUserEmail(accessToken, fetchFn) {
|
|
|
588036
588085
|
}
|
|
588037
588086
|
}
|
|
588038
588087
|
async function handleAuth(opts) {
|
|
588039
|
-
const { fs, format, write, openUrl, fetchFn, startOAuthFlowFn = startOAuthFlow } = opts;
|
|
588088
|
+
const { fs, format, write, openUrl, fetchFn, startOAuthFlowFn = startOAuthFlow, promptFn } = opts;
|
|
588040
588089
|
const tokens = loadTokens(fs);
|
|
588041
588090
|
if (tokens) {
|
|
588042
588091
|
return handleAuthStatus({ fs, format, write, fetchFn, cachedTokens: tokens });
|
|
588043
588092
|
}
|
|
588044
588093
|
let credentials;
|
|
588045
588094
|
try {
|
|
588046
|
-
|
|
588095
|
+
if (promptFn && format === "text") {
|
|
588096
|
+
credentials = await getClientCredentialsOrPrompt(fs, write, promptFn);
|
|
588097
|
+
} else {
|
|
588098
|
+
credentials = getClientCredentials(fs);
|
|
588099
|
+
}
|
|
588047
588100
|
} catch (err) {
|
|
588048
588101
|
if (err instanceof AuthError) {
|
|
588049
588102
|
if (format === "json") {
|
|
@@ -588082,8 +588135,16 @@ async function handleAuthStatus(opts) {
|
|
|
588082
588135
|
}
|
|
588083
588136
|
return { exitCode: ExitCode.AUTH };
|
|
588084
588137
|
}
|
|
588085
|
-
|
|
588086
|
-
|
|
588138
|
+
let currentTokens = tokens;
|
|
588139
|
+
if (isTokenExpired(tokens.expiry_date)) {
|
|
588140
|
+
try {
|
|
588141
|
+
const credentials = getClientCredentials(fs);
|
|
588142
|
+
currentTokens = await refreshAccessToken(credentials, tokens, fetchFn);
|
|
588143
|
+
saveTokens(fs, currentTokens);
|
|
588144
|
+
} catch {}
|
|
588145
|
+
}
|
|
588146
|
+
const email2 = await fetchUserEmail(currentTokens.access_token, fetchFn);
|
|
588147
|
+
const expiresAt = new Date(currentTokens.expiry_date);
|
|
588087
588148
|
if (format === "json") {
|
|
588088
588149
|
write(formatJsonSuccess({
|
|
588089
588150
|
authenticated: true,
|
|
@@ -592238,6 +592299,22 @@ function handleError2(error, format3) {
|
|
|
592238
592299
|
process.exit(errorCodeToExitCode(errorCode));
|
|
592239
592300
|
}
|
|
592240
592301
|
|
|
592302
|
+
// src/lib/prompt.ts
|
|
592303
|
+
import { createInterface } from "node:readline/promises";
|
|
592304
|
+
function createReadlinePrompt() {
|
|
592305
|
+
return async (message2) => {
|
|
592306
|
+
const rl = createInterface({
|
|
592307
|
+
input: process.stdin,
|
|
592308
|
+
output: process.stderr
|
|
592309
|
+
});
|
|
592310
|
+
try {
|
|
592311
|
+
return await rl.question(message2);
|
|
592312
|
+
} finally {
|
|
592313
|
+
rl.close();
|
|
592314
|
+
}
|
|
592315
|
+
};
|
|
592316
|
+
}
|
|
592317
|
+
|
|
592241
592318
|
// src/lib/resolve-calendar.ts
|
|
592242
592319
|
async function resolveEventCalendar(api2, eventId, calendars) {
|
|
592243
592320
|
const results = await Promise.all(calendars.map(async (cal) => {
|
|
@@ -592288,7 +592365,8 @@ function registerCommands(program2) {
|
|
|
592288
592365
|
openUrl: (url) => {
|
|
592289
592366
|
write(`Open this URL in your browser:
|
|
592290
592367
|
${url}`);
|
|
592291
|
-
}
|
|
592368
|
+
},
|
|
592369
|
+
promptFn: createReadlinePrompt()
|
|
592292
592370
|
});
|
|
592293
592371
|
}
|
|
592294
592372
|
process.exit(result.exitCode);
|
|
@@ -592507,7 +592585,8 @@ ${url}`);
|
|
|
592507
592585
|
},
|
|
592508
592586
|
requestAuth: async () => {
|
|
592509
592587
|
apiRef = null;
|
|
592510
|
-
const
|
|
592588
|
+
const promptFn = createReadlinePrompt();
|
|
592589
|
+
const credentials = globalOpts.format === "text" ? await getClientCredentialsOrPrompt(fsAdapter, write, promptFn) : getClientCredentials(fsAdapter);
|
|
592511
592590
|
const { authUrl, waitForCode, server } = await startOAuthFlow(credentials, fsAdapter, globalThis.fetch);
|
|
592512
592591
|
write(`Not authenticated. Starting OAuth flow...`);
|
|
592513
592592
|
write(`Open this URL in your browser:
|