githits 0.4.8 → 0.4.9

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.
@@ -6,7 +6,7 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "GitHits plugins for Claude Code - code examples from global open source",
9
- "version": "0.4.8"
9
+ "version": "0.4.9"
10
10
  },
11
11
  "plugins": [
12
12
  {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"
package/dist/cli.js CHANGED
@@ -51,11 +51,11 @@ import {
51
51
  shouldRunUpdateCheck,
52
52
  startTelemetrySpan,
53
53
  withTelemetrySpan
54
- } from "./shared/chunk-6hq1gf0g.js";
54
+ } from "./shared/chunk-v23wr0eq.js";
55
55
  import {
56
56
  __require,
57
57
  version
58
- } from "./shared/chunk-wyphcypv.js";
58
+ } from "./shared/chunk-yqx01jh9.js";
59
59
 
60
60
  // src/cli.ts
61
61
  import { Command } from "commander";
@@ -8001,7 +8001,7 @@ grep run. --symbol-field hydrates enclosing symbol metadata (appears under each
8001
8001
  match in --verbose output; full payload in --json).`;
8002
8002
  function registerCodeGrepCommand(pkgCommand) {
8003
8003
  return pkgCommand.command("grep").summary("Deterministic text grep over indexed dependency source").description(PKG_GREP_DESCRIPTION).argument("[spec-or-pattern]", "Spec mode: package spec (e.g. npm:express). Repo mode (with --repo-url): the pattern.").argument("[pattern-or-prefix]", "Spec mode: the pattern. Repo mode: optional path-prefix.").argument("[path-prefix]", "Spec mode only: optional path-prefix. Ignored with --repo-url.").option("--repo-url <url>", "Repository URL addressing (defaults to the repo default branch)").option("--git-ref <ref>", "Optional tag, commit, branch, or HEAD for --repo-url.").option("--path <path>", "Exact file path to grep").option("--glob <glob>", "Glob scope (repeatable)", collectRepeatable2, []).option("--ext <ext>", "Extension filter without leading dot (repeatable)", collectRepeatable2, []).option("--regex", "Interpret the pattern as RE2 regex").option("--case-sensitive", "Enable ASCII case-sensitive matching").option("-C, --context <n>", "Context lines before and after each match (0-10)").option("-B, --before-context <n>", "Context lines before each match (0-10)").option("-A, --after-context <n>", "Context lines after each match (0-10)").option("--exclude-docs", "Skip files classified as documentation").option("--exclude-tests", "Skip files classified as tests").option("--limit <n>", "Max matches to return on this page (1-1000, default 50)").option("--per-file-limit <n>", "Cap matches per file within this page (0-1000, 0 = unlimited)").option("--cursor <cursor>", "Opaque nextCursor from a previous grep result").option("--symbol-field <field>", `Repeatable; surfaces in --json and under each --verbose match. ${GREP_REPO_SYMBOL_FIELDS_NOTE}`, collectRepeatable2, []).option("--wait <ms>", `Indexing wait timeout (0-${MAX_WAIT_TIMEOUT_MS}, default ${DEFAULT_WAIT_TIMEOUT_MS})`).option("-v, --verbose", "Render grouped output with file headers").option("--json", "Emit the JSON envelope").action(async (arg1, arg2, arg3, options) => {
8004
- const { createContainer: createContainer2 } = await import("./shared/chunk-681avsyw.js");
8004
+ const { createContainer: createContainer2 } = await import("./shared/chunk-phdms6y7.js");
8005
8005
  const deps = await createContainer2();
8006
8006
  await pkgGrepAction(arg1, arg2, arg3, options, {
8007
8007
  codeNavigationService: deps.codeNavigationService,
@@ -8465,7 +8465,7 @@ function registerExampleCommand(program) {
8465
8465
  });
8466
8466
  }
8467
8467
  async function loadContainer() {
8468
- const { createContainer: createContainer2 } = await import("./shared/chunk-681avsyw.js");
8468
+ const { createContainer: createContainer2 } = await import("./shared/chunk-phdms6y7.js");
8469
8469
  return createContainer2();
8470
8470
  }
8471
8471
  // src/commands/feedback.ts
@@ -13642,7 +13642,7 @@ function requireSearchService(deps) {
13642
13642
  return deps.codeNavigationService;
13643
13643
  }
13644
13644
  async function loadContainer2() {
13645
- const { createContainer: createContainer2 } = await import("./shared/chunk-681avsyw.js");
13645
+ const { createContainer: createContainer2 } = await import("./shared/chunk-phdms6y7.js");
13646
13646
  return createContainer2();
13647
13647
  }
13648
13648
  function parseTargetSpecs(specs) {
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  version
3
- } from "./shared/chunk-wyphcypv.js";
3
+ } from "./shared/chunk-yqx01jh9.js";
4
4
  export {
5
5
  version
6
6
  };
@@ -4,8 +4,8 @@ import {
4
4
  createAuthStatusDependencies,
5
5
  createContainer,
6
6
  loadAutoLoginAuthSessionMetadata
7
- } from "./chunk-6hq1gf0g.js";
8
- import"./chunk-wyphcypv.js";
7
+ } from "./chunk-v23wr0eq.js";
8
+ import"./chunk-yqx01jh9.js";
9
9
  export {
10
10
  loadAutoLoginAuthSessionMetadata,
11
11
  createContainer,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  __require,
3
3
  version
4
- } from "./chunk-wyphcypv.js";
4
+ } from "./chunk-yqx01jh9.js";
5
5
 
6
6
  // src/services/app-config-paths.ts
7
7
  var APP_DIR = "githits";
@@ -6217,7 +6217,8 @@ class TokenManager {
6217
6217
  authStorage;
6218
6218
  mcpUrl;
6219
6219
  cachedToken = null;
6220
- refreshPromise = null;
6220
+ softRefreshPromise = null;
6221
+ forceRefreshPromise = null;
6221
6222
  constructor(deps) {
6222
6223
  this.authService = deps.authService;
6223
6224
  this.authStorage = deps.authStorage;
@@ -6225,6 +6226,9 @@ class TokenManager {
6225
6226
  }
6226
6227
  async getToken() {
6227
6228
  return withTelemetrySpan("token-manager.get-token", async () => {
6229
+ if (this.forceRefreshPromise) {
6230
+ return (await this.forceRefreshPromise).accessToken;
6231
+ }
6228
6232
  if (!this.cachedToken) {
6229
6233
  this.cachedToken = await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6230
6234
  if (!this.cachedToken)
@@ -6235,7 +6239,9 @@ class TokenManager {
6235
6239
  if (!shouldRefresh) {
6236
6240
  return currentToken;
6237
6241
  }
6238
- const refreshedToken = await this.doRefresh();
6242
+ const refreshedToken = await this.doRefresh({
6243
+ allowFreshExternalToken: true
6244
+ });
6239
6245
  if (refreshedToken) {
6240
6246
  return refreshedToken;
6241
6247
  }
@@ -6246,27 +6252,56 @@ class TokenManager {
6246
6252
  });
6247
6253
  }
6248
6254
  async forceRefresh() {
6249
- return withTelemetrySpan("token-manager.force-refresh", () => this.doRefresh());
6250
- }
6251
- async doRefresh() {
6252
- if (this.refreshPromise) {
6253
- return this.refreshPromise;
6255
+ return withTelemetrySpan("token-manager.force-refresh", () => this.doRefresh({ allowFreshExternalToken: false }));
6256
+ }
6257
+ async doRefresh(options) {
6258
+ const result = await this.doRefreshResult(options);
6259
+ return result.accessToken;
6260
+ }
6261
+ async doRefreshResult(options) {
6262
+ if (!options.allowFreshExternalToken) {
6263
+ if (this.forceRefreshPromise)
6264
+ return this.forceRefreshPromise;
6265
+ this.forceRefreshPromise = (async () => {
6266
+ const softResult = await this.softRefreshPromise?.catch(() => {
6267
+ return;
6268
+ });
6269
+ if (softResult?.accessToken && softResult.refreshedViaEndpoint) {
6270
+ return softResult;
6271
+ }
6272
+ return this.executeRefresh(options);
6273
+ })();
6274
+ try {
6275
+ return await this.forceRefreshPromise;
6276
+ } finally {
6277
+ this.forceRefreshPromise = null;
6278
+ }
6254
6279
  }
6255
- this.refreshPromise = this.executeRefresh();
6280
+ if (this.forceRefreshPromise)
6281
+ return this.forceRefreshPromise;
6282
+ if (this.softRefreshPromise)
6283
+ return this.softRefreshPromise;
6284
+ this.softRefreshPromise = this.executeRefresh(options);
6256
6285
  try {
6257
- return await this.refreshPromise;
6286
+ return await this.softRefreshPromise;
6258
6287
  } finally {
6259
- this.refreshPromise = null;
6288
+ this.softRefreshPromise = null;
6260
6289
  }
6261
6290
  }
6262
- async executeRefresh() {
6291
+ async executeRefresh(options) {
6263
6292
  return withTelemetrySpan("token-manager.refresh", async () => {
6264
- const tokens = this.cachedToken ?? await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6265
- if (!tokens)
6266
- return;
6293
+ const candidate = await this.loadRefreshCandidate();
6294
+ if (!candidate)
6295
+ return refreshResult(undefined, false);
6296
+ if (candidate.externallyUpdated && options.allowFreshExternalToken) {
6297
+ const { shouldRefresh } = shouldRefreshToken(candidate.tokens, PROACTIVE_REFRESH_RATIO, new Date);
6298
+ if (!shouldRefresh)
6299
+ return refreshResult(candidate.tokens.accessToken, false);
6300
+ }
6301
+ const tokens = candidate.tokens;
6267
6302
  const client = await withTelemetrySpan("token-manager.load-client", () => this.authStorage.loadClient(this.mcpUrl));
6268
6303
  if (!client)
6269
- return;
6304
+ return refreshResult(undefined, false);
6270
6305
  let response;
6271
6306
  try {
6272
6307
  const metadata = await withTelemetrySpan("token-manager.discover-endpoints", () => this.authService.discoverEndpoints(this.mcpUrl));
@@ -6279,21 +6314,25 @@ class TokenManager {
6279
6314
  } catch {
6280
6315
  const reloadedToken = await this.loadExternallyUpdatedToken(tokens);
6281
6316
  if (reloadedToken)
6282
- return reloadedToken.accessToken;
6317
+ return refreshResult(reloadedToken.accessToken, false);
6283
6318
  const isExpired = tokens.expiresAt ? new Date >= new Date(tokens.expiresAt) : false;
6319
+ if (candidate.externallyUpdated && !isExpired) {
6320
+ return refreshResult(tokens.accessToken, false);
6321
+ }
6284
6322
  if (isExpired) {
6285
6323
  const currentStoredTokens = await this.loadExternallyUpdatedToken(tokens);
6286
- if (currentStoredTokens)
6287
- return currentStoredTokens.accessToken;
6324
+ if (currentStoredTokens) {
6325
+ return refreshResult(currentStoredTokens.accessToken, false);
6326
+ }
6288
6327
  const cleared = await withTelemetrySpan("token-manager.clear-tokens-if-unchanged", () => this.authStorage.clearTokensIfUnchanged(this.mcpUrl, tokens));
6289
6328
  if (!cleared) {
6290
6329
  const currentToken = await this.authStorage.loadTokens(this.mcpUrl);
6291
6330
  this.cachedToken = currentToken;
6292
- return currentToken?.accessToken;
6331
+ return refreshResult(currentToken?.accessToken, false);
6293
6332
  }
6294
6333
  this.cachedToken = null;
6295
6334
  }
6296
- return;
6335
+ return refreshResult(undefined, false);
6297
6336
  }
6298
6337
  const newTokenData = {
6299
6338
  accessToken: response.accessToken,
@@ -6301,30 +6340,53 @@ class TokenManager {
6301
6340
  expiresAt: new Date(Date.now() + response.expiresIn * 1000).toISOString(),
6302
6341
  createdAt: new Date().toISOString()
6303
6342
  };
6304
- const externallyUpdatedToken = await this.loadExternallyUpdatedToken(tokens, {
6305
- treatMissingAsExternalUpdate: true
6306
- });
6307
- if (externallyUpdatedToken === null)
6308
- return;
6309
- if (externallyUpdatedToken)
6310
- return externallyUpdatedToken.accessToken;
6311
6343
  const saved = await withTelemetrySpan("token-manager.save-tokens", () => this.authStorage.saveTokensIfUnchanged(this.mcpUrl, tokens, newTokenData));
6312
6344
  if (!saved) {
6313
- const currentToken = await this.authStorage.loadTokens(this.mcpUrl);
6314
- this.cachedToken = currentToken;
6315
- return currentToken?.accessToken;
6345
+ return this.resolveSuccessfulRefreshConflict(tokens, response, newTokenData);
6316
6346
  }
6317
6347
  this.cachedToken = newTokenData;
6318
- return response.accessToken;
6348
+ return refreshResult(response.accessToken, true);
6319
6349
  });
6320
6350
  }
6321
- async loadExternallyUpdatedToken(failedTokens, options = {}) {
6322
- const storedTokens = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6351
+ async resolveSuccessfulRefreshConflict(refreshedFrom, response, newTokenData) {
6352
+ const currentToken = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6353
+ if (!currentToken) {
6354
+ this.cachedToken = null;
6355
+ return refreshResult(undefined, false);
6356
+ }
6357
+ if (!response.refreshToken || currentToken.refreshToken !== refreshedFrom.refreshToken) {
6358
+ this.cachedToken = currentToken;
6359
+ return refreshResult(currentToken.accessToken, false);
6360
+ }
6361
+ const saved = await withTelemetrySpan("token-manager.save-rotated-tokens-after-conflict", () => this.authStorage.saveTokensIfUnchanged(this.mcpUrl, currentToken, newTokenData));
6362
+ if (saved) {
6363
+ this.cachedToken = newTokenData;
6364
+ return refreshResult(newTokenData.accessToken, true);
6365
+ }
6366
+ const latestToken = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6367
+ this.cachedToken = latestToken;
6368
+ return refreshResult(latestToken?.accessToken, false);
6369
+ }
6370
+ async loadRefreshCandidate() {
6371
+ const storedTokens = await withTelemetrySpan("token-manager.load-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6372
+ if (!this.cachedToken) {
6373
+ this.cachedToken = storedTokens;
6374
+ return storedTokens ? { tokens: storedTokens, externallyUpdated: false } : null;
6375
+ }
6323
6376
  if (!storedTokens) {
6324
- if (options.treatMissingAsExternalUpdate)
6325
- this.cachedToken = null;
6326
- return options.treatMissingAsExternalUpdate ? null : undefined;
6377
+ this.cachedToken = null;
6378
+ return null;
6327
6379
  }
6380
+ if (!areSameTokenData(storedTokens, this.cachedToken)) {
6381
+ this.cachedToken = storedTokens;
6382
+ return { tokens: storedTokens, externallyUpdated: true };
6383
+ }
6384
+ return { tokens: this.cachedToken, externallyUpdated: false };
6385
+ }
6386
+ async loadExternallyUpdatedToken(failedTokens) {
6387
+ const storedTokens = await withTelemetrySpan("token-manager.reload-tokens", () => this.authStorage.loadTokens(this.mcpUrl));
6388
+ if (!storedTokens)
6389
+ return;
6328
6390
  if (areSameTokenData(storedTokens, failedTokens))
6329
6391
  return;
6330
6392
  this.cachedToken = storedTokens;
@@ -6334,6 +6396,9 @@ class TokenManager {
6334
6396
  function areSameTokenData(a, b) {
6335
6397
  return a.accessToken === b.accessToken && a.refreshToken === b.refreshToken && a.expiresAt === b.expiresAt && a.createdAt === b.createdAt;
6336
6398
  }
6399
+ function refreshResult(accessToken, refreshedViaEndpoint) {
6400
+ return { accessToken, refreshedViaEndpoint };
6401
+ }
6337
6402
  // src/services/update-check-service.ts
6338
6403
  import semver from "semver";
6339
6404
  var NPM_DIST_TAGS_URL = "https://registry.npmjs.org/-/package/githits/dist-tags";
@@ -1,6 +1,6 @@
1
1
  import { createRequire } from "node:module";
2
2
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
3
  // package.json
4
- var version = "0.4.8";
4
+ var version = "0.4.9";
5
5
 
6
6
  export { __require, version };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Code examples from global open source for developers and AI assistants.",
5
5
  "mcpServers": {
6
6
  "githits": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "githits",
3
3
  "description": "CLI companion for GitHits - code examples from global open source for developers and AI assistants",
4
- "version": "0.4.8",
4
+ "version": "0.4.9",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "githits",
3
- "version": "0.4.8",
3
+ "version": "0.4.9",
4
4
  "description": "Code examples from global open source for developers and AI assistants",
5
5
  "author": {
6
6
  "name": "GitHits"