@clipdone/cli 0.1.2 → 0.1.3

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.
Files changed (2) hide show
  1. package/bin/clipdone.js +30 -5
  2. package/package.json +1 -1
package/bin/clipdone.js CHANGED
@@ -148,8 +148,9 @@ var OAUTH_AUTHORIZE_PATH = "/api/auth/oauth2/authorize";
148
148
  var OAUTH_REGISTER_PATH = "/api/auth/oauth2/register";
149
149
  var OAUTH_TOKEN_PATH = "/api/auth/oauth2/token";
150
150
  var OAUTH_REVOKE_PATH = "/api/auth/oauth2/revoke";
151
- var OAUTH_CLIENT_REGISTRATION_VERSION = 2;
151
+ var OAUTH_CLIENT_REGISTRATION_VERSION = 3;
152
152
  var OAUTH_LOOPBACK_PORTS = [59852, 59853, 59854, 59855, 59856, 59857, 59858, 59859];
153
+ var OAUTH_CALLBACK_PATH = "/agents/callback";
153
154
  var PRODUCTION_APP_URL = "https://app.clipdone.app";
154
155
  var LOCAL_APP_URL = "http://localhost:3000";
155
156
  var REQUEST_TIMEOUT_MS = 15e3;
@@ -537,7 +538,7 @@ async function oauthRegisterClient({ scope }) {
537
538
  },
538
539
  body: JSON.stringify({
539
540
  client_name: "ClipDone CLI",
540
- redirect_uris: OAUTH_LOOPBACK_PORTS.map((port) => `http://127.0.0.1:${port}/callback`),
541
+ redirect_uris: [new URL(OAUTH_CALLBACK_PATH, appBase()).toString()],
541
542
  grant_types: ["authorization_code", "refresh_token"],
542
543
  response_types: ["code"],
543
544
  token_endpoint_auth_method: "none",
@@ -955,6 +956,9 @@ function parseLegacyCommand(args, parts) {
955
956
  }
956
957
  function parseTopLevelCommand(args) {
957
958
  const parts = Array.isArray(args._) ? args._ : [];
959
+ if (args.version === true || parts[0] === "version") {
960
+ return { key: "version" };
961
+ }
958
962
  if (parts.length === 0 || parts[0] === "help") {
959
963
  return { key: "help" };
960
964
  }
@@ -1044,6 +1048,7 @@ function printHelp() {
1044
1048
  writeLine();
1045
1049
  writeLine("Useful options:");
1046
1050
  writeLine(" --help Show command help");
1051
+ writeLine(" --version Show the installed CLI version");
1047
1052
  if (devHelp) {
1048
1053
  writeLine();
1049
1054
  writeLine("Development target options:");
@@ -1060,6 +1065,10 @@ function readJsonFile(filePath) {
1060
1065
  throw new Error(`Could not read JSON from ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
1061
1066
  }
1062
1067
  }
1068
+ function cliVersion() {
1069
+ const packageJson = readJsonFile(join(BIN_DIR, "..", "package.json"));
1070
+ return normalizeString(packageJson?.version) || "0.0.0";
1071
+ }
1063
1072
  function normalizeFeedbackNotes(value) {
1064
1073
  if (!value) return [];
1065
1074
  if (Array.isArray(value)) return value;
@@ -1106,6 +1115,16 @@ function base64UrlEncode(bytes) {
1106
1115
  function randomState() {
1107
1116
  return base64UrlEncode(webcrypto.getRandomValues(new Uint8Array(24)));
1108
1117
  }
1118
+ function buildOAuthState(csrfState, localRedirectUri) {
1119
+ return base64UrlEncode(
1120
+ new TextEncoder().encode(
1121
+ JSON.stringify({
1122
+ csrfState,
1123
+ localRedirectUri
1124
+ })
1125
+ )
1126
+ );
1127
+ }
1109
1128
  function generateCodeVerifier() {
1110
1129
  return base64UrlEncode(webcrypto.getRandomValues(new Uint8Array(48)));
1111
1130
  }
@@ -1139,11 +1158,13 @@ async function listenOnLoopbackPort() {
1139
1158
  async function login(args) {
1140
1159
  const authConfig = { resource: API_OAUTH_RESOURCE, scope: API_OAUTH_SCOPES.join(" ") };
1141
1160
  const oauthClient = await resolveOAuthClient(authConfig);
1142
- const state = randomState();
1161
+ const csrfState = randomState();
1143
1162
  const codeVerifier = generateCodeVerifier();
1144
1163
  const codeChallenge = await generateCodeChallenge(codeVerifier);
1145
1164
  const { server, port } = await listenOnLoopbackPort();
1146
- const redirectUri = `http://127.0.0.1:${port}/callback`;
1165
+ const localRedirectUri = `http://127.0.0.1:${port}/callback`;
1166
+ const state = buildOAuthState(csrfState, localRedirectUri);
1167
+ const redirectUri = new URL(OAUTH_CALLBACK_PATH, appBase()).toString();
1147
1168
  const authUrl = new URL(OAUTH_AUTHORIZE_PATH, appBase());
1148
1169
  authUrl.searchParams.set("client_id", oauthClient.clientId);
1149
1170
  authUrl.searchParams.set("response_type", "code");
@@ -1166,7 +1187,7 @@ async function login(args) {
1166
1187
  }, 5 * 60 * 1e3);
1167
1188
  server.on("request", async (req, res) => {
1168
1189
  try {
1169
- const url = new URL(req.url || "/", redirectUri);
1190
+ const url = new URL(req.url || "/", localRedirectUri);
1170
1191
  if (url.pathname !== "/callback") {
1171
1192
  res.writeHead(404).end("Not found");
1172
1193
  return;
@@ -1332,6 +1353,10 @@ async function main() {
1332
1353
  printHelp();
1333
1354
  return;
1334
1355
  }
1356
+ if (command === "version") {
1357
+ writeLine(cliVersion());
1358
+ return;
1359
+ }
1335
1360
  if (command === "login") return await login(args);
1336
1361
  if (command === "logout") {
1337
1362
  if (!hasStoredAuth()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clipdone/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Command line access to ClipDone projects and exports",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",