@dereekb/dbx-cli 14.6.0 → 14.7.0

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli-lint-cache",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "sideEffects": false,
5
5
  "private": true,
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  "eslint": "10.9.1"
10
10
  },
11
11
  "peerDependencies": {
12
- "@dereekb/util": "14.6.0",
12
+ "@dereekb/util": "14.7.0",
13
13
  "yargs": "^18.0.0"
14
14
  }
15
15
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/manifest-extract",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.6.0",
8
- "@dereekb/dbx-cli": "14.6.0",
9
- "@dereekb/firebase": "14.6.0",
10
- "@dereekb/model": "14.6.0",
11
- "@dereekb/nestjs": "14.6.0",
12
- "@dereekb/oauth-resource": "14.6.0",
13
- "@dereekb/rxjs": "14.6.0",
14
- "@dereekb/util": "14.6.0",
7
+ "@dereekb/date": "14.7.0",
8
+ "@dereekb/dbx-cli": "14.7.0",
9
+ "@dereekb/firebase": "14.7.0",
10
+ "@dereekb/model": "14.7.0",
11
+ "@dereekb/nestjs": "14.7.0",
12
+ "@dereekb/oauth-resource": "14.7.0",
13
+ "@dereekb/rxjs": "14.7.0",
14
+ "@dereekb/util": "14.7.0",
15
15
  "ts-morph": "^28.0.0"
16
16
  },
17
17
  "devDependencies": {
18
- "@dereekb/firebase": "14.6.0"
18
+ "@dereekb/firebase": "14.7.0"
19
19
  },
20
20
  "exports": {
21
21
  "./package.json": "./package.json",
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/model-test",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/util": "14.6.0",
7
+ "@dereekb/util": "14.7.0",
8
8
  "ts-morph": "^28.0.0"
9
9
  },
10
10
  "exports": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "bin": {
@@ -66,12 +66,12 @@
66
66
  }
67
67
  },
68
68
  "peerDependencies": {
69
- "@dereekb/date": "14.6.0",
70
- "@dereekb/firebase": "14.6.0",
71
- "@dereekb/model": "14.6.0",
72
- "@dereekb/nestjs": "14.6.0",
73
- "@dereekb/oauth-resource": "14.6.0",
74
- "@dereekb/util": "14.6.0",
69
+ "@dereekb/date": "14.7.0",
70
+ "@dereekb/firebase": "14.7.0",
71
+ "@dereekb/model": "14.7.0",
72
+ "@dereekb/nestjs": "14.7.0",
73
+ "@dereekb/oauth-resource": "14.7.0",
74
+ "@dereekb/util": "14.7.0",
75
75
  "@nestjs/common": "^12.0.1",
76
76
  "arktype": "^2.2.0",
77
77
  "firebase": "^12.18.0",
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/route",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.6.0",
8
- "@dereekb/dbx-cli": "14.6.0",
9
- "@dereekb/firebase": "14.6.0",
10
- "@dereekb/model": "14.6.0",
11
- "@dereekb/nestjs": "14.6.0",
12
- "@dereekb/oauth-resource": "14.6.0",
13
- "@dereekb/util": "14.6.0"
7
+ "@dereekb/date": "14.7.0",
8
+ "@dereekb/dbx-cli": "14.7.0",
9
+ "@dereekb/firebase": "14.7.0",
10
+ "@dereekb/model": "14.7.0",
11
+ "@dereekb/nestjs": "14.7.0",
12
+ "@dereekb/oauth-resource": "14.7.0",
13
+ "@dereekb/util": "14.7.0"
14
14
  },
15
15
  "exports": {
16
16
  "./package.json": "./package.json",
@@ -1,4 +1,4 @@
1
- import { type AsyncKeyedValueCache, type Maybe } from '@dereekb/util';
1
+ import { type AsyncKeyedValueCache, type Maybe, type OidcTokenResponse } from '@dereekb/util';
2
2
  /**
3
3
  * A cached token entry for a single env.
4
4
  */
@@ -67,3 +67,34 @@ export declare function createCliTokenCacheStore(input: CreateCliTokenCacheStore
67
67
  * @returns `true` when the token is at or within `bufferMs` of expiry, otherwise `false`.
68
68
  */
69
69
  export declare function isTokenExpired(entry: Maybe<CliTokenEntry>, nowMs?: number, bufferMs?: number): boolean;
70
+ /**
71
+ * Input for {@link mergeRefreshedTokenEntry}.
72
+ */
73
+ export interface MergeRefreshedTokenEntryInput {
74
+ readonly entry: CliTokenEntry;
75
+ readonly refreshed: OidcTokenResponse;
76
+ /**
77
+ * The current time in unix epoch milliseconds, used to derive `expiresAt`. Defaults to `Date.now()`.
78
+ */
79
+ readonly nowMs?: number;
80
+ }
81
+ /**
82
+ * Folds an OIDC refresh response into the cached entry it was obtained with.
83
+ *
84
+ * EVERY refresh must persist the result of this merge. A refresh CONSUMES the supplied refresh
85
+ * token whenever the grant rotates, so keeping the old entry leaves the cache holding a spent
86
+ * credential and strands the session on the next refresh — with replay detection on the provider
87
+ * side, reusing the spent token can revoke the whole grant. Centralized so the refresh call sites
88
+ * (auth middleware, `auth check`, `doctor`) cannot drift apart on this.
89
+ *
90
+ * @param input - The entry that was refreshed and the token response it produced.
91
+ * @returns The updated entry to persist. Fields the provider omits fall back to the previous entry.
92
+ */
93
+ export declare function mergeRefreshedTokenEntry(input: MergeRefreshedTokenEntryInput): CliTokenEntry;
94
+ /**
95
+ * Whether a refresh response rotated the refresh token it was obtained with.
96
+ *
97
+ * @param input - The entry that was refreshed and the token response it produced.
98
+ * @returns `true` when the provider issued a DIFFERENT refresh token, meaning the old one is spent.
99
+ */
100
+ export declare function didRotateRefreshToken(input: Pick<MergeRefreshedTokenEntryInput, 'entry' | 'refreshed'>): boolean;
@@ -1,3 +1,4 @@
1
1
  export * from './build-drift.check';
2
2
  export * from './doctor.command.factory';
3
3
  export * from './firestore-session.check';
4
+ export * from './token-refresh.check';
@@ -0,0 +1,32 @@
1
+ import { discoverOidcMetadata, refreshAccessToken } from '../auth/oidc.client';
2
+ import { type CliTokenCacheStore } from '../config/token.cache';
3
+ import { type DoctorCheck } from './doctor.command.factory';
4
+ /**
5
+ * Name reported by the check {@link createTokenRefreshDoctorCheck} builds.
6
+ */
7
+ export declare const TOKEN_REFRESH_DOCTOR_CHECK_NAME = "token-refresh-round-trip";
8
+ /**
9
+ * Seams for {@link createTokenRefreshDoctorCheck}. Production omits all of them and gets the real
10
+ * OIDC client plus the on-disk token cache; tests substitute fakes so the check's PERSIST step can
11
+ * be asserted without a network or a home directory.
12
+ */
13
+ export interface TokenRefreshDoctorCheckOverrides {
14
+ readonly tokenStoreForCli?: (cliName: string) => CliTokenCacheStore;
15
+ readonly discoverOidcMetadata?: typeof discoverOidcMetadata;
16
+ readonly refreshAccessToken?: typeof refreshAccessToken;
17
+ }
18
+ /**
19
+ * Builds the doctor check that proves the cached refresh token still works.
20
+ *
21
+ * The round-trip is a REAL refresh, so on a rotating grant it consumes the cached refresh token and
22
+ * the response must be written back — see `mergeRefreshedTokenEntry`. Discarding it (as this check
23
+ * once did) leaves the cache holding a spent credential: the very next refresh fails
24
+ * `invalid_grant`, and a provider doing replay detection revokes the whole grant. The symptom is
25
+ * maximally confusing because the session dies only AFTER the cached access token lapses, so the
26
+ * damage surfaces well away from the `doctor` run that caused it.
27
+ *
28
+ * @param overrides - Optional test seams; production passes none.
29
+ * @returns The {@link DoctorCheck}.
30
+ * @__NO_SIDE_EFFECTS__
31
+ */
32
+ export declare function createTokenRefreshDoctorCheck(overrides?: TokenRefreshDoctorCheckOverrides): DoctorCheck;
@@ -44,6 +44,15 @@ export interface LoadUtilRegistryResult {
44
44
  readonly loaderWarnings: readonly UtilLoaderWarning[];
45
45
  readonly externalSourceCount: number;
46
46
  }
47
+ /**
48
+ * The bundled `@dereekb/*` utils manifests to load at startup. Must stay in step with the `utils.scan` entries in
49
+ * `dbx-mcp.config.json` — a generated manifest that is missing from this list is silently invisible to
50
+ * `dbx_util_lookup`/`dbx_util_search` no matter how well its exports are tagged.
51
+ *
52
+ * Loading is non-strict, so naming a file that a given workspace has not generated warns and skips rather than
53
+ * failing server startup.
54
+ */
55
+ export declare const DEFAULT_BUNDLED_FILENAMES: readonly ["dereekb-util.utils.mcp.generated.json", "dereekb-util-fetch.utils.mcp.generated.json", "dereekb-date.utils.mcp.generated.json", "dereekb-rxjs.utils.mcp.generated.json", "dereekb-model.utils.mcp.generated.json", "dereekb-firebase.utils.mcp.generated.json", "dereekb-firebase-server.utils.mcp.generated.json"];
47
56
  /**
48
57
  * Loads the merged utils registry for the current MCP server.
49
58
  *
@@ -185,6 +185,32 @@ export declare function buildDumpFilePath(extension: 'json' | 'ndjson', suffix?:
185
185
  * @returns The filtered value (typed as the input).
186
186
  */
187
187
  export declare function pickFields<T>(data: T, pick: string): T;
188
+ /**
189
+ * Applies the configured `--pick` filter to the document payload(s) carried by a command result.
190
+ *
191
+ * Returns `unknown` rather than `T` because picking REDUCES each payload — the reduced value is a
192
+ * partial view of the document and does not satisfy the result's own type.
193
+ *
194
+ * @param data - The full command result.
195
+ * @param pick - Reduces a document to the configured fields. Apply it to each payload, not the wrapper.
196
+ * @returns The result with its payload(s) reduced, wrapper fields intact.
197
+ */
198
+ export type CliOutputPickApplier<T> = (data: T, pick: (value: unknown) => unknown) => unknown;
199
+ /**
200
+ * Per-command output overrides for {@link outputResult}.
201
+ */
202
+ export interface CliOutputResultOptions<T> {
203
+ /**
204
+ * Redirects the `--pick` filter into the result's document payload(s).
205
+ *
206
+ * Read commands wrap documents in an envelope (`{ key, data }`, `{ results, errors }`), so the
207
+ * default top-level pick can only ever match the wrapper's own keys — a pick naming real document
208
+ * fields silently yields `{}`, which is indistinguishable from an empty document. Supplied by the
209
+ * command because only it knows its envelope shape. Commands whose result *is* the payload
210
+ * (the common case) omit this and keep the top-level behavior.
211
+ */
212
+ readonly applyPick?: CliOutputPickApplier<T>;
213
+ }
188
214
  /**
189
215
  * Prints a successful command result as a `{ ok: true, data, meta? }` JSON envelope on stdout.
190
216
  *
@@ -194,8 +220,9 @@ export declare function pickFields<T>(data: T, pick: string): T;
194
220
  *
195
221
  * @param data - The command result to emit.
196
222
  * @param meta - Optional additional metadata to attach to the envelope.
223
+ * @param options - Optional per-command overrides — see {@link CliOutputResultOptions}.
197
224
  */
198
- export declare function outputResult<T>(data: T, meta?: Record<string, unknown>): void;
225
+ export declare function outputResult<T>(data: T, meta?: Record<string, unknown>, options?: CliOutputResultOptions<T>): void;
199
226
  /**
200
227
  * Prints a failed command result as a `{ ok: false, error, code, suggestion? }` JSON envelope on stdout.
201
228
  *
package/test/package.json CHANGED
@@ -1,18 +1,18 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/test",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.6.0",
8
- "@dereekb/dbx-cli": "14.6.0",
9
- "@dereekb/firebase": "14.6.0",
10
- "@dereekb/firebase-server/test": "14.5.1",
11
- "@dereekb/model": "14.6.0",
12
- "@dereekb/nestjs": "14.6.0",
13
- "@dereekb/oauth-resource": "14.6.0",
14
- "@dereekb/rxjs": "14.6.0",
15
- "@dereekb/util": "14.6.0",
7
+ "@dereekb/date": "14.7.0",
8
+ "@dereekb/dbx-cli": "14.7.0",
9
+ "@dereekb/firebase": "14.7.0",
10
+ "@dereekb/firebase-server/test": "14.6.0",
11
+ "@dereekb/model": "14.7.0",
12
+ "@dereekb/nestjs": "14.7.0",
13
+ "@dereekb/oauth-resource": "14.7.0",
14
+ "@dereekb/rxjs": "14.7.0",
15
+ "@dereekb/util": "14.7.0",
16
16
  "@nestjs/common": "^12.0.1",
17
17
  "arktype": "^2.2.0",
18
18
  "vitest": "4.1.11",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/validate",
3
- "version": "14.6.0",
3
+ "version": "14.7.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/dbx-cli": "14.6.0",
8
- "@dereekb/util": "14.6.0",
7
+ "@dereekb/dbx-cli": "14.7.0",
8
+ "@dereekb/util": "14.7.0",
9
9
  "ts-morph": "^28.0.0"
10
10
  }
11
11
  }