@dereekb/dbx-cli 14.3.0 → 14.4.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,7 +1,4 @@
1
- import { type FirebaseApp } from 'firebase/app';
2
- import { type Auth } from 'firebase/auth';
3
- import { type Firestore } from 'firebase/firestore';
4
- import { type FirestoreContext } from '@dereekb/firebase';
1
+ import { type FirebaseUserSession } from '@dereekb/oauth-resource/firebase';
5
2
  import { type CliFirestoreSession } from '../api/firestore-session.client';
6
3
  import { type CliEnvConfig } from '../config/env';
7
4
  import { type CliFirestoreSessionCacheStore } from '../config/firestore-session.cache';
@@ -9,25 +6,23 @@ import { type CliFirestoreSessionCacheStore } from '../config/firestore-session.
9
6
  * A live direct-Firestore session: the Firebase client objects the CLI signed in with, plus the
10
7
  * `FirestoreContext` an app's collections factory consumes.
11
8
  *
9
+ * The CLI's view of {@link FirebaseUserSession}, whose implementation lives in
10
+ * `@dereekb/oauth-resource/firebase` so any resource server that verified a bearer token carrying the
11
+ * `session.firestore` scope gets the same bridge.
12
+ *
12
13
  * The `firestoreContext` is built by `clientFirebaseFirestoreContextFactory`, the exact analogue of
13
14
  * the server's `googleCloudFirestoreContextFactory` — both satisfy `FirestoreContextFactory` — so an
14
15
  * app's `make<App>FirestoreCollections(context)` accepts it unchanged, and the CLI runs the SAME
15
16
  * queries the Angular app runs, through the SAME security rules.
16
17
  */
17
- export interface CliFirestoreSessionContext {
18
+ export interface CliFirestoreSessionContext extends FirebaseUserSession {
18
19
  /**
19
20
  * The credential bundle the API minted for this session.
21
+ *
22
+ * The CLI's long-standing name for {@link FirebaseUserSession.credentials}; both name the same
23
+ * object.
20
24
  */
21
25
  readonly session: CliFirestoreSession;
22
- /**
23
- * True when {@link session} came from the on-disk session cache rather than a fresh
24
- * `GET /session/firestore`. Surfaced for `doctor` and `--verbose`, not for control flow.
25
- */
26
- readonly fromCache: boolean;
27
- readonly app: FirebaseApp;
28
- readonly auth: Auth;
29
- readonly firestore: Firestore;
30
- readonly firestoreContext: FirestoreContext;
31
26
  }
32
27
  export interface CreateCliFirestoreSessionContextInput {
33
28
  readonly cliName: string;
@@ -49,39 +44,15 @@ export interface CreateCliFirestoreSessionContextInput {
49
44
  */
50
45
  readonly refreshSession?: boolean;
51
46
  }
52
- /**
53
- * The Firebase app name a direct-Firestore session registers for a CLI + env pair.
54
- *
55
- * Deriving the name rather than tracking apps in a side registry is what makes ONE app per CLI + env
56
- * per process a property of the code instead of a convention: {@link createCliFirestoreSessionContext}
57
- * looks this name up in `getApps()` before initializing, so repeated session opens in one process —
58
- * a doctor probe alongside a command's own session, an action that re-resolves the accessor — all
59
- * share a single app, and {@link closeAllCliFirebaseApps} finds it again from the name alone.
60
- *
61
- * @param input - The CLI name and env name the session targets.
62
- * @returns The Firebase app name for that pair.
63
- * @__NO_SIDE_EFFECTS__
64
- */
65
- export declare function cliFirebaseAppName(input: Pick<CreateCliFirestoreSessionContextInput, 'cliName' | 'envName'>): string;
66
47
  /**
67
48
  * Opens a direct Firestore connection as the authenticated CLI user.
68
49
  *
69
- * Steps, in a strict order:
50
+ * A thin wrapper over `openFirebaseUserSession`: it validates the env's Firebase client config with
51
+ * the CLI's own env-var-naming remediation, then delegates. The strict step ORDER (mint → fresh app →
52
+ * App Check FIRST → emulator wiring → sign-in) and its reasoning live with the implementation.
70
53
  *
71
- * 0. When a `sessionCache` is supplied, reuse the env's cached credential envelope if it is still
72
- * live. Sessions are cached for up to an hour (see `CLI_FIRESTORE_SESSION_MAX_CACHE_MS`), which is
73
- * the ceiling the Firebase credentials themselves sit under. A hit skips step 1 only — the
74
- * Firebase app is per-process, so the sign-in in step 5 always runs.
75
- * 1. `GET <apiBaseUrl>/session/firestore` for a custom token + App Check attestation.
76
- * 2. `initializeApp` with the env's Firebase client config.
77
- * 3. `initializeAppCheck` with a `CustomProvider` handing back the server-minted token. **This must
78
- * happen before any other Firebase call** — `dbx-firebase`'s provider documents the same
79
- * constraint: "App Check must be initialized before any Firebase request goes out, otherwise
80
- * requests are sent without an App Check token and are rejected in production." Skipped when the
81
- * env targets emulators (which do not verify attestations) or when the API minted no token.
82
- * 4. `getAuth` / `getFirestore`, connecting each to its emulator when configured.
83
- * 5. `signInWithCustomToken`. The user's stored custom claims land at the top level of the exchanged
84
- * ID token, so `request.auth.token.<claim>` reads in security rules behave exactly as in the app.
54
+ * The session's Firebase app is named `<cliName>::<envName>::<uid>`, so
55
+ * {@link closeAllCliFirebaseApps} finds every app this CLI opened from the name alone.
85
56
  *
86
57
  * There is deliberately NO fallback to the HTTP model API — a failure here throws so the operator
87
58
  * sees it. `createFirestoreSessionDoctorCheck` is the diagnostic surface for why.
@@ -96,15 +67,7 @@ export declare function createCliFirestoreSessionContext(input: CreateCliFiresto
96
67
  *
97
68
  * Required for the CLI to EXIT. A signed-in `Auth` and a live `Firestore` both hold open handles
98
69
  * that keep the Node event loop alive indefinitely, so without this a command prints its result and
99
- * then hangs forever — the process never returns to the shell. Nothing in the CLI is long-lived
100
- * enough to want that: a session is opened for one invocation and is dead weight afterwards.
101
- *
102
- * `deleteApp` is the single call that covers it — it disposes every registered component, which for
103
- * Firestore runs the same shutdown `terminate()` does, and for Auth stops the token-refresh timer.
104
- *
105
- * Deliberately tolerant: teardown runs in a `finally` after the command has already produced its
106
- * output, so a failure here must not change the exit code or mask the real result. A session that
107
- * was never opened is a no-op.
70
+ * then hangs forever — the process never returns to the shell.
108
71
  *
109
72
  * @param session - The session context to close.
110
73
  */
@@ -112,23 +75,15 @@ export declare function closeCliFirestoreSessionContext(session: CliFirestoreSes
112
75
  /**
113
76
  * Deletes every still-live Firebase app this CLI opened, whether or not a session was handed back.
114
77
  *
115
- * The CLI's last line of defence against a hang. `closeCliFirestoreSessionContext` covers the normal
116
- * path, but it needs a session to be handed to it, and three cases never produce one:
78
+ * The CLI's last line of defence against a hang. {@link closeCliFirestoreSessionContext} covers the
79
+ * normal path, but it needs a session to be handed to it, and three cases never produce one:
117
80
  *
118
- * - a handshake that fails AFTER `initializeApp` — a rejected custom token, a failed App Check
119
- * registration — throws, so the caller that catches it has an initialized app and no session;
81
+ * - a handshake that fails AFTER `initializeApp` — a failed App Check registration, a broken emulator
82
+ * connection — throws, so the caller that catches it has an initialized app and no session;
120
83
  * - a caller that opens its own session outside the context memo (the doctor probe) owns its own
121
84
  * teardown, and forgetting it hangs the process;
122
85
  * - a {@link CliContext} orphaned mid-invocation carries the only reference to its session memo.
123
86
  *
124
- * Each leaves an app whose `Firestore` and signed-in `Auth` hold the Node event loop open forever.
125
- * `getApps()` already tracks every live app and `deleteApp` removes it from that list, so the app
126
- * names {@link cliFirebaseAppName} derives are enough to find them again — no side registry to keep
127
- * in sync, and idempotent by construction.
128
- *
129
- * Tolerant of failures for the same reason {@link closeCliFirestoreSessionContext} is: it runs after
130
- * the result is already on stdout.
131
- *
132
87
  * @param input - The function inputs.
133
88
  * @param input.cliName - The CLI whose apps should be closed. Apps belonging to other Firebase
134
89
  * consumers in the same process are left alone.
package/test/package.json CHANGED
@@ -1,17 +1,18 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/test",
3
- "version": "14.3.0",
3
+ "version": "14.4.0",
4
4
  "sideEffects": false,
5
5
  "type": "module",
6
6
  "peerDependencies": {
7
- "@dereekb/date": "14.3.0",
8
- "@dereekb/dbx-cli": "14.3.0",
9
- "@dereekb/firebase": "14.3.0",
10
- "@dereekb/firebase-server/test": "14.3.0",
11
- "@dereekb/model": "14.3.0",
12
- "@dereekb/nestjs": "14.3.0",
13
- "@dereekb/rxjs": "14.3.0",
14
- "@dereekb/util": "14.3.0",
7
+ "@dereekb/date": "14.4.0",
8
+ "@dereekb/dbx-cli": "14.4.0",
9
+ "@dereekb/firebase": "14.4.0",
10
+ "@dereekb/firebase-server/test": "14.4.0",
11
+ "@dereekb/model": "14.4.0",
12
+ "@dereekb/nestjs": "14.4.0",
13
+ "@dereekb/oauth-resource": "14.4.0",
14
+ "@dereekb/rxjs": "14.4.0",
15
+ "@dereekb/util": "14.4.0",
15
16
  "@nestjs/common": "^12.0.1",
16
17
  "arktype": "^2.2.0",
17
18
  "vitest": "4.1.11",
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli/validate",
3
- "version": "14.3.0",
3
+ "version": "14.4.0",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "peerDependencies": {
7
- "@dereekb/dbx-cli": "14.3.0",
8
- "@dereekb/util": "14.3.0",
7
+ "@dereekb/dbx-cli": "14.4.0",
8
+ "@dereekb/util": "14.4.0",
9
9
  "ts-morph": "^28.0.0"
10
10
  }
11
11
  }