@dereekb/dbx-cli 13.37.0 → 13.39.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.
- package/eslint/package.json +8 -8
- package/firebase-api-manifest/main.js +191 -166
- package/firebase-api-manifest/package.json +3 -3
- package/firestore-query-manifest/main.js +2063 -0
- package/firestore-query-manifest/package.json +13 -0
- package/firestore-rules/src/firestore-rules-scan.d.ts +89 -0
- package/firestore-rules/src/index.d.ts +1 -0
- package/generate-firestore-indexes/main.js +2 -2
- package/generate-firestore-indexes/package.json +2 -2
- package/generate-mcp-manifest/main.js +1 -0
- package/generate-mcp-manifest/package.json +3 -3
- package/generate-route-manifest/package.json +2 -2
- package/index.esm.js +12615 -6863
- package/lint-cache/package.json +2 -2
- package/manifest-extract/index.esm.js +4 -1
- package/manifest-extract/package.json +7 -7
- package/manifest-extract/src/lib/types.d.ts +6 -0
- package/model-test/LICENSE +21 -0
- package/model-test/index.d.ts +1 -0
- package/model-test/index.esm.js +5984 -0
- package/model-test/package.json +21 -0
- package/model-test/src/index.d.ts +41 -0
- package/model-test/src/lib/fixture/archetype.d.ts +33 -0
- package/model-test/src/lib/fixture/extract.d.ts +37 -0
- package/model-test/src/lib/fixture/format.json.d.ts +24 -0
- package/model-test/src/lib/fixture/format.markdown.d.ts +23 -0
- package/model-test/src/lib/fixture/forward.d.ts +48 -0
- package/model-test/src/lib/fixture/framework-fixtures.d.ts +70 -0
- package/model-test/src/lib/fixture/inspect.d.ts +22 -0
- package/model-test/src/lib/fixture/scaffold.d.ts +74 -0
- package/model-test/src/lib/fixture/types.d.ts +175 -0
- package/model-test/src/lib/test/discover.d.ts +81 -0
- package/model-test/src/lib/test/extract.d.ts +49 -0
- package/model-test/src/lib/test/format.hotspots.d.ts +23 -0
- package/model-test/src/lib/test/format.json.d.ts +25 -0
- package/model-test/src/lib/test/format.list-app.d.ts +30 -0
- package/model-test/src/lib/test/format.markdown.d.ts +25 -0
- package/model-test/src/lib/test/hotspots.d.ts +98 -0
- package/model-test/src/lib/test/inspect.d.ts +32 -0
- package/model-test/src/lib/test/search.d.ts +34 -0
- package/model-test/src/lib/test/types.d.ts +179 -0
- package/package.json +23 -22
- package/route/package.json +12 -12
- package/src/lib/api/firestore-session.client.d.ts +54 -0
- package/src/lib/api/get-args.helper.d.ts +4 -1
- package/src/lib/api/get-many.command.d.ts +8 -3
- package/src/lib/api/get.command.d.ts +13 -5
- package/src/lib/api/index.d.ts +1 -0
- package/src/lib/config/env.d.ts +106 -0
- package/src/lib/config/firestore-session.cache.d.ts +86 -0
- package/src/lib/config/index.d.ts +1 -0
- package/src/lib/config/paths.d.ts +3 -1
- package/src/lib/context/cli.context.d.ts +87 -3
- package/src/lib/doctor/firestore-session.check.d.ts +113 -0
- package/src/lib/doctor/index.d.ts +1 -0
- package/src/lib/firestore/firestore-get.command.d.ts +28 -0
- package/src/lib/firestore/firestore-queries.command.d.ts +26 -0
- package/src/lib/firestore/firestore-query.command.d.ts +25 -0
- package/src/lib/firestore/firestore.accessor.d.ts +85 -0
- package/src/lib/firestore/firestore.collection.d.ts +44 -0
- package/src/lib/firestore/firestore.error.d.ts +14 -0
- package/src/lib/firestore/firestore.models.d.ts +223 -0
- package/src/lib/firestore/firestore.query-params.d.ts +34 -0
- package/src/lib/firestore/firestore.query.d.ts +79 -0
- package/src/lib/firestore/firestore.read.d.ts +180 -0
- package/src/lib/firestore/firestore.session.d.ts +97 -0
- package/src/lib/firestore/index.d.ts +13 -0
- package/src/lib/firestore/query-info-utils.d.ts +48 -0
- package/src/lib/firestore/query-registry.d.ts +32 -0
- package/src/lib/index.d.ts +3 -0
- package/src/lib/manifest/types.d.ts +117 -0
- package/src/lib/mcp-scan/manifest/dbx-docs-ui-examples-schema.d.ts +2 -2
- package/src/lib/mcp-scan/manifest/model-snapshot-fields-schema.d.ts +2 -2
- package/src/lib/mcp-scan/manifest/pipes-schema.d.ts +2 -2
- package/src/lib/mcp-scan/manifest/ui-components-schema.d.ts +2 -2
- package/src/lib/mcp-scan/manifest/utils-schema.d.ts +2 -2
- package/src/lib/mcp-scan/scan/dbx-docs-ui-examples-extract.d.ts +1 -1
- package/src/lib/mcp-scan/scan/extract-models/types.d.ts +5 -0
- package/src/lib/mcp-scan/scan/ui-components-extract.d.ts +1 -1
- package/src/lib/middleware/auth.middleware.d.ts +6 -0
- package/src/lib/runner/run.d.ts +28 -1
- package/src/lib/scan-helpers/emit-generated-ts.d.ts +76 -0
- package/src/lib/scan-helpers/exported-from-package.d.ts +29 -0
- package/src/lib/util/index.d.ts +1 -0
- package/src/lib/util/output.d.ts +10 -0
- package/src/lib/util/stdin.d.ts +39 -2
- package/src/lib/util/table.d.ts +40 -0
- package/test/index.esm.js +4 -2
- package/test/package.json +14 -14
- package/test/src/lib/cli-test.d.ts +12 -2
- package/validate/LICENSE +21 -0
- package/validate/index.js +16641 -0
- package/validate/package.json +11 -0
- package/eslint/index.cjs.default.js +0 -1
- package/eslint/index.cjs.js +0 -1112
- package/eslint/index.cjs.mjs +0 -2
- package/index.cjs.js +0 -59813
- package/manifest-extract/index.cjs.default.js +0 -1
- package/manifest-extract/index.cjs.js +0 -1592
- package/manifest-extract/index.cjs.mjs +0 -2
- package/route/index.cjs.default.js +0 -1
- package/route/index.cjs.js +0 -18
- package/route/index.cjs.mjs +0 -2
- package/test/index.cjs.default.js +0 -1
- package/test/index.cjs.js +0 -381
- package/test/index.cjs.mjs +0 -2
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { type Maybe } from '@dereekb/util';
|
|
2
|
+
import { type GetModelOverHttpResult, type GetMultipleModelsOverHttpResult } from '../api/call-model.client';
|
|
3
|
+
import { type CliContext } from '../context/cli.context';
|
|
4
|
+
import { type CliModelManifest } from '../manifest/types';
|
|
5
|
+
import { type CliFirestoreModels } from './firestore.models';
|
|
6
|
+
/**
|
|
7
|
+
* Transport selection for a read.
|
|
8
|
+
*
|
|
9
|
+
* - `auto` — go direct when the whole chain is present, fall back to the API on a CAPABILITY failure.
|
|
10
|
+
* - `firestore` / `api` — hard selections. They error rather than switching, so a script that means
|
|
11
|
+
* "prove the direct path works" cannot silently pass on the API path instead.
|
|
12
|
+
*/
|
|
13
|
+
export type CliReadVia = 'auto' | 'firestore' | 'api';
|
|
14
|
+
/**
|
|
15
|
+
* Every accepted `--via` value, for yargs `choices`.
|
|
16
|
+
*/
|
|
17
|
+
export declare const CLI_READ_VIA_VALUES: readonly CliReadVia[];
|
|
18
|
+
/**
|
|
19
|
+
* Default `--via` value.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_CLI_READ_VIA: CliReadVia;
|
|
22
|
+
/**
|
|
23
|
+
* Coerces a raw `--via` argv value, rejecting anything outside {@link CLI_READ_VIA_VALUES}.
|
|
24
|
+
*
|
|
25
|
+
* yargs `choices` already rejects a bad value on the command line, but the same helper is reached
|
|
26
|
+
* from programmatic callers (and from `buildPerModelGetCommand`, whose argv is untyped), so the
|
|
27
|
+
* validation lives here rather than only in the builder.
|
|
28
|
+
*
|
|
29
|
+
* @param value - The raw argv value.
|
|
30
|
+
* @returns The coerced via value, defaulting to `auto` when absent.
|
|
31
|
+
* @throws {CliError} When the value is a non-empty string outside the accepted set.
|
|
32
|
+
*
|
|
33
|
+
* @__NO_SIDE_EFFECTS__
|
|
34
|
+
*/
|
|
35
|
+
export declare function coerceCliReadVia(value: unknown): CliReadVia;
|
|
36
|
+
/**
|
|
37
|
+
* Error code used when a read is refused because the model is server-only.
|
|
38
|
+
*/
|
|
39
|
+
export declare const MODEL_IS_SERVER_ONLY_CODE = "MODEL_IS_SERVER_ONLY";
|
|
40
|
+
/**
|
|
41
|
+
* Refuses a read of a `@dbxModelServerOnly` model BEFORE any transport is chosen.
|
|
42
|
+
*
|
|
43
|
+
* The refusal is deliberately transport-independent: the model has no client read grant in
|
|
44
|
+
* `firestore.rules` at all, so the direct path would be rejected by the rules and the API path is
|
|
45
|
+
* refused by `ModelApiGetService`. Answering locally makes the reason legible (and free) instead of
|
|
46
|
+
* surfacing as a permission error from whichever transport happened to run.
|
|
47
|
+
*
|
|
48
|
+
* @param input - The manifest and the model type being read.
|
|
49
|
+
* @param input.manifest - The generated model manifest, when the CLI was wired with one.
|
|
50
|
+
* @param input.modelType - The model type being read.
|
|
51
|
+
* @throws {CliError} `MODEL_IS_SERVER_ONLY` when the manifest marks the model server-only.
|
|
52
|
+
*/
|
|
53
|
+
export declare function assertCliModelIsNotServerOnly(input: {
|
|
54
|
+
readonly manifest: Maybe<CliModelManifest>;
|
|
55
|
+
readonly modelType: string;
|
|
56
|
+
}): void;
|
|
57
|
+
/**
|
|
58
|
+
* Why {@link resolveCliReadSource} chose the source it chose.
|
|
59
|
+
*/
|
|
60
|
+
export type CliReadSourceReason =
|
|
61
|
+
/**
|
|
62
|
+
* `--via` named the source explicitly.
|
|
63
|
+
*/
|
|
64
|
+
'explicit'
|
|
65
|
+
/**
|
|
66
|
+
* Under `auto`: the whole direct chain resolved.
|
|
67
|
+
*/
|
|
68
|
+
| 'session-available'
|
|
69
|
+
/**
|
|
70
|
+
* Under `auto`: the CLI has no `firestore` binding.
|
|
71
|
+
*/
|
|
72
|
+
| 'no-firestore-binding'
|
|
73
|
+
/**
|
|
74
|
+
* Under `auto`: the env carries no complete Firebase client config.
|
|
75
|
+
*/
|
|
76
|
+
| 'firebase-config-incomplete'
|
|
77
|
+
/**
|
|
78
|
+
* Under `auto`: the chain is wired but the session could not be opened.
|
|
79
|
+
*/
|
|
80
|
+
| 'session-unavailable';
|
|
81
|
+
/**
|
|
82
|
+
* The resolved transport for one read.
|
|
83
|
+
*/
|
|
84
|
+
export interface CliReadSource {
|
|
85
|
+
readonly source: 'firestore' | 'api';
|
|
86
|
+
readonly reason: CliReadSourceReason;
|
|
87
|
+
/**
|
|
88
|
+
* The `--via` value that produced this resolution, so `meta.via` can report what was asked for
|
|
89
|
+
* alongside what ran.
|
|
90
|
+
*/
|
|
91
|
+
readonly via: CliReadVia;
|
|
92
|
+
/**
|
|
93
|
+
* The opened session-bound models view. Present only when {@link source} is `firestore`.
|
|
94
|
+
*/
|
|
95
|
+
readonly models?: CliFirestoreModels;
|
|
96
|
+
/**
|
|
97
|
+
* Set when `auto` fell back: why the direct path was not usable, verbatim from the underlying error.
|
|
98
|
+
*/
|
|
99
|
+
readonly fallbackError?: string;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Input for {@link resolveCliReadSource}.
|
|
103
|
+
*/
|
|
104
|
+
export interface ResolveCliReadSourceInput {
|
|
105
|
+
readonly context: CliContext;
|
|
106
|
+
readonly via: CliReadVia;
|
|
107
|
+
/**
|
|
108
|
+
* The model type being read. Checked against the manifest's `serverOnly` flag BEFORE any transport
|
|
109
|
+
* is considered.
|
|
110
|
+
*/
|
|
111
|
+
readonly modelType: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Resolves which transport a read should use, opening the direct-Firestore session when that is the
|
|
115
|
+
* answer.
|
|
116
|
+
*
|
|
117
|
+
* Called from the read command handlers rather than from inside `CliContext.getModel`: `getModel` is
|
|
118
|
+
* a two-arg function with no room for `--via` without changing every call site including
|
|
119
|
+
* `buildTestCliContext`, and hiding a transport fallback inside the context would contradict the
|
|
120
|
+
* deliberate no-fallback doctrine `firestore.session.ts` and `createFirestoreSessionDoctorCheck`
|
|
121
|
+
* were built around — a failure there should be loud.
|
|
122
|
+
*
|
|
123
|
+
* @param input - The live context, the requested `--via`, and the model type.
|
|
124
|
+
* @returns The resolved source, carrying the opened models view when it is `firestore`.
|
|
125
|
+
* @throws {CliError} `MODEL_IS_SERVER_ONLY` for a server-only model, or the session's own error when `--via firestore` was demanded and the session could not open.
|
|
126
|
+
*/
|
|
127
|
+
export declare function resolveCliReadSource(input: ResolveCliReadSourceInput): Promise<CliReadSource>;
|
|
128
|
+
/**
|
|
129
|
+
* Builds the `meta` block every read emits, so which transport ran is always observable.
|
|
130
|
+
*
|
|
131
|
+
* @param source - The resolved source.
|
|
132
|
+
* @returns The meta record for `outputResult`.
|
|
133
|
+
*
|
|
134
|
+
* @__NO_SIDE_EFFECTS__
|
|
135
|
+
*/
|
|
136
|
+
export declare function cliReadResultMeta(source: CliReadSource): Record<string, unknown>;
|
|
137
|
+
/**
|
|
138
|
+
* Reads one document directly from Firestore by model key.
|
|
139
|
+
*
|
|
140
|
+
* Returns the exact `GetModelOverHttpResult` envelope `GET /model/<type>/get` returns, so `--via`
|
|
141
|
+
* never changes the output shape.
|
|
142
|
+
*
|
|
143
|
+
* @param input - The read inputs.
|
|
144
|
+
* @param input.models - The session-bound models view.
|
|
145
|
+
* @param input.modelType - The model type to load through.
|
|
146
|
+
* @param input.key - The document key to read.
|
|
147
|
+
* @returns `{ key, data }`, with `data: null` when the document does not exist.
|
|
148
|
+
* @throws {CliError} When the key does not match the model's path shape.
|
|
149
|
+
*/
|
|
150
|
+
export declare function getModelOverFirestore<T = unknown>(input: {
|
|
151
|
+
readonly models: CliFirestoreModels;
|
|
152
|
+
readonly modelType: string;
|
|
153
|
+
readonly key: string;
|
|
154
|
+
}): Promise<GetModelOverHttpResult<Maybe<T>>>;
|
|
155
|
+
/**
|
|
156
|
+
* Batch-reads documents directly from Firestore by model key.
|
|
157
|
+
*
|
|
158
|
+
* Mirrors the API's `{ results, errors }` partition rather than failing the whole batch on one bad
|
|
159
|
+
* key: a rules refusal or a malformed key for one document lands in `errors` and the rest still come
|
|
160
|
+
* back, which is the behaviour `get-many` callers already handle.
|
|
161
|
+
*
|
|
162
|
+
* Reads are issued concurrently (each is an independent single-document fetch through the same
|
|
163
|
+
* session, so serializing them would make a batch as deep as it is wide) through a SLIDING WINDOW of
|
|
164
|
+
* {@link MAX_MODEL_ACCESS_MULTI_READ_KEYS} in-flight reads — the same width the API path chunks at,
|
|
165
|
+
* but without its barrier between chunks, so a slow document no longer stalls the reads behind it.
|
|
166
|
+
* The cap itself is load-bearing: `get-many -` reads its keys from stdin and is unbounded, so one
|
|
167
|
+
* unbounded `Promise.all` would open thousands of concurrent reads on a large input.
|
|
168
|
+
*
|
|
169
|
+
* @param input - The read inputs.
|
|
170
|
+
* @param input.models - The session-bound models view.
|
|
171
|
+
* @param input.modelType - The model type to load through.
|
|
172
|
+
* @param input.keys - The document keys to read.
|
|
173
|
+
* @returns `{ results, errors }`, key order preserved within each partition.
|
|
174
|
+
* @throws {CliError} `INVALID_ARGUMENT` when `modelType` is not a registered model.
|
|
175
|
+
*/
|
|
176
|
+
export declare function getMultipleModelsOverFirestore<T = unknown>(input: {
|
|
177
|
+
readonly models: CliFirestoreModels;
|
|
178
|
+
readonly modelType: string;
|
|
179
|
+
readonly keys: ReadonlyArray<string>;
|
|
180
|
+
}): Promise<GetMultipleModelsOverHttpResult<Maybe<T>>>;
|
|
@@ -0,0 +1,97 @@
|
|
|
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';
|
|
5
|
+
import { type CliFirestoreSession } from '../api/firestore-session.client';
|
|
6
|
+
import { type CliEnvConfig } from '../config/env';
|
|
7
|
+
import { type CliFirestoreSessionCacheStore } from '../config/firestore-session.cache';
|
|
8
|
+
/**
|
|
9
|
+
* A live direct-Firestore session: the Firebase client objects the CLI signed in with, plus the
|
|
10
|
+
* `FirestoreContext` an app's collections factory consumes.
|
|
11
|
+
*
|
|
12
|
+
* The `firestoreContext` is built by `clientFirebaseFirestoreContextFactory`, the exact analogue of
|
|
13
|
+
* the server's `googleCloudFirestoreContextFactory` — both satisfy `FirestoreContextFactory` — so an
|
|
14
|
+
* app's `make<App>FirestoreCollections(context)` accepts it unchanged, and the CLI runs the SAME
|
|
15
|
+
* queries the Angular app runs, through the SAME security rules.
|
|
16
|
+
*/
|
|
17
|
+
export interface CliFirestoreSessionContext {
|
|
18
|
+
/**
|
|
19
|
+
* The credential bundle the API minted for this session.
|
|
20
|
+
*/
|
|
21
|
+
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
|
+
}
|
|
32
|
+
export interface CreateCliFirestoreSessionContextInput {
|
|
33
|
+
readonly cliName: string;
|
|
34
|
+
readonly envName: string;
|
|
35
|
+
readonly env: CliEnvConfig;
|
|
36
|
+
readonly accessToken: string;
|
|
37
|
+
/**
|
|
38
|
+
* Custom fetch implementation for tests.
|
|
39
|
+
*/
|
|
40
|
+
readonly fetcher?: typeof fetch;
|
|
41
|
+
/**
|
|
42
|
+
* Optional on-disk session cache. When supplied, a live cached envelope for {@link envName} is
|
|
43
|
+
* reused instead of re-minting one, and a freshly minted envelope is written back.
|
|
44
|
+
*/
|
|
45
|
+
readonly sessionCache?: CliFirestoreSessionCacheStore;
|
|
46
|
+
/**
|
|
47
|
+
* Skips the cache read for this call and re-mints, still writing the result back. Used by
|
|
48
|
+
* `doctor` and by a retry after a sign-in failure.
|
|
49
|
+
*/
|
|
50
|
+
readonly refreshSession?: boolean;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Opens a direct Firestore connection as the authenticated CLI user.
|
|
54
|
+
*
|
|
55
|
+
* Steps, in a strict order:
|
|
56
|
+
*
|
|
57
|
+
* 0. When a `sessionCache` is supplied, reuse the env's cached credential envelope if it is still
|
|
58
|
+
* live. Sessions are cached for up to an hour (see `CLI_FIRESTORE_SESSION_MAX_CACHE_MS`), which is
|
|
59
|
+
* the ceiling the Firebase credentials themselves sit under. A hit skips step 1 only — the
|
|
60
|
+
* Firebase app is per-process, so the sign-in in step 5 always runs.
|
|
61
|
+
* 1. `GET <apiBaseUrl>/session/firestore` for a custom token + App Check attestation.
|
|
62
|
+
* 2. `initializeApp` with the env's Firebase client config.
|
|
63
|
+
* 3. `initializeAppCheck` with a `CustomProvider` handing back the server-minted token. **This must
|
|
64
|
+
* happen before any other Firebase call** — `dbx-firebase`'s provider documents the same
|
|
65
|
+
* constraint: "App Check must be initialized before any Firebase request goes out, otherwise
|
|
66
|
+
* requests are sent without an App Check token and are rejected in production." Skipped when the
|
|
67
|
+
* env targets emulators (which do not verify attestations) or when the API minted no token.
|
|
68
|
+
* 4. `getAuth` / `getFirestore`, connecting each to its emulator when configured.
|
|
69
|
+
* 5. `signInWithCustomToken`. The user's stored custom claims land at the top level of the exchanged
|
|
70
|
+
* ID token, so `request.auth.token.<claim>` reads in security rules behave exactly as in the app.
|
|
71
|
+
*
|
|
72
|
+
* There is deliberately NO fallback to the HTTP model API — a failure here throws so the operator
|
|
73
|
+
* sees it. `createFirestoreSessionDoctorCheck` is the diagnostic surface for why.
|
|
74
|
+
*
|
|
75
|
+
* @param input - The CLI name, env, access token, and optional session cache.
|
|
76
|
+
* @returns The live {@link CliFirestoreSessionContext}.
|
|
77
|
+
* @throws {CliError} When the env lacks Firebase client config, or any step of the handshake fails.
|
|
78
|
+
*/
|
|
79
|
+
export declare function createCliFirestoreSessionContext(input: CreateCliFirestoreSessionContextInput): Promise<CliFirestoreSessionContext>;
|
|
80
|
+
/**
|
|
81
|
+
* Tears down a session opened by {@link createCliFirestoreSessionContext}.
|
|
82
|
+
*
|
|
83
|
+
* Required for the CLI to EXIT. A signed-in `Auth` and a live `Firestore` both hold open handles
|
|
84
|
+
* that keep the Node event loop alive indefinitely, so without this a command prints its result and
|
|
85
|
+
* then hangs forever — the process never returns to the shell. Nothing in the CLI is long-lived
|
|
86
|
+
* enough to want that: a session is opened for one invocation and is dead weight afterwards.
|
|
87
|
+
*
|
|
88
|
+
* `deleteApp` is the single call that covers it — it disposes every registered component, which for
|
|
89
|
+
* Firestore runs the same shutdown `terminate()` does, and for Auth stops the token-refresh timer.
|
|
90
|
+
*
|
|
91
|
+
* Deliberately tolerant: teardown runs in a `finally` after the command has already produced its
|
|
92
|
+
* output, so a failure here must not change the exit code or mask the real result. A session that
|
|
93
|
+
* was never opened is a no-op.
|
|
94
|
+
*
|
|
95
|
+
* @param session - The session context to close.
|
|
96
|
+
*/
|
|
97
|
+
export declare function closeCliFirestoreSessionContext(session: CliFirestoreSessionContext): Promise<void>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export * from './firestore-get.command';
|
|
2
|
+
export * from './firestore-queries.command';
|
|
3
|
+
export * from './firestore-query.command';
|
|
4
|
+
export * from './firestore.accessor';
|
|
5
|
+
export * from './firestore.collection';
|
|
6
|
+
export * from './firestore.error';
|
|
7
|
+
export * from './firestore.models';
|
|
8
|
+
export * from './firestore.query';
|
|
9
|
+
export * from './firestore.query-params';
|
|
10
|
+
export * from './firestore.read';
|
|
11
|
+
export * from './firestore.session';
|
|
12
|
+
export * from './query-info-utils';
|
|
13
|
+
export * from './query-registry';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type CliFirestoreQueryManifestEntry } from '../manifest/types';
|
|
2
|
+
import { type CliFirestoreQueryRegistry } from './query-registry';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a `firestore-queries <query>` / `firestore-query <query>` positional against the
|
|
5
|
+
* catalog, failing with the accepted slugs when it misses.
|
|
6
|
+
*
|
|
7
|
+
* @param registry - The query catalog.
|
|
8
|
+
* @param query - The slug or exported identifier supplied on the command line.
|
|
9
|
+
* @returns The matching entry.
|
|
10
|
+
* @throws {CliError} When nothing matches.
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveCliFirestoreQueryEntry(registry: CliFirestoreQueryRegistry, query: string): CliFirestoreQueryManifestEntry;
|
|
13
|
+
/**
|
|
14
|
+
* Filters for {@link renderCliFirestoreQueryList}.
|
|
15
|
+
*/
|
|
16
|
+
export interface CliFirestoreQueryListFilter {
|
|
17
|
+
readonly model?: string;
|
|
18
|
+
readonly category?: string;
|
|
19
|
+
readonly tag?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Applies the `--model` / `--category` / `--tag` filters to the catalog.
|
|
23
|
+
*
|
|
24
|
+
* @param registry - The query catalog.
|
|
25
|
+
* @param filter - The active filters.
|
|
26
|
+
* @returns The matching entries, in slug order.
|
|
27
|
+
*
|
|
28
|
+
* @__NO_SIDE_EFFECTS__
|
|
29
|
+
*/
|
|
30
|
+
export declare function filterCliFirestoreQueries(registry: CliFirestoreQueryRegistry, filter: CliFirestoreQueryListFilter): readonly CliFirestoreQueryManifestEntry[];
|
|
31
|
+
/**
|
|
32
|
+
* Renders the human-readable catalog table, grouped by model.
|
|
33
|
+
*
|
|
34
|
+
* @param entries - The (already filtered) entries to render.
|
|
35
|
+
* @returns The formatted table with a trailing newline.
|
|
36
|
+
*
|
|
37
|
+
* @__NO_SIDE_EFFECTS__
|
|
38
|
+
*/
|
|
39
|
+
export declare function renderCliFirestoreQueryList(entries: readonly CliFirestoreQueryManifestEntry[]): string;
|
|
40
|
+
/**
|
|
41
|
+
* Renders one catalog entry in full — signature, params, governance flags, and related slugs.
|
|
42
|
+
*
|
|
43
|
+
* @param entry - The entry to render.
|
|
44
|
+
* @returns The formatted detail block with a trailing newline.
|
|
45
|
+
*
|
|
46
|
+
* @__NO_SIDE_EFFECTS__
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderCliFirestoreQueryEntry(entry: CliFirestoreQueryManifestEntry): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type CliFirestoreQueryManifest, type CliFirestoreQueryManifestEntry } from '../manifest/types';
|
|
2
|
+
/**
|
|
3
|
+
* A read API over the generated Firestore query catalog.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors `ModelFirebaseIndexRegistry` (the build-time registry over the same tagged factories) so
|
|
6
|
+
* the runtime catalog and the tooling catalog read the same way.
|
|
7
|
+
*/
|
|
8
|
+
export interface CliFirestoreQueryRegistry {
|
|
9
|
+
readonly all: readonly CliFirestoreQueryManifestEntry[];
|
|
10
|
+
readonly collections: readonly string[];
|
|
11
|
+
readonly models: readonly string[];
|
|
12
|
+
readonly categories: readonly string[];
|
|
13
|
+
readonly tags: readonly string[];
|
|
14
|
+
/**
|
|
15
|
+
* Resolves by slug first, then by exported identifier — both spellings are accepted on the
|
|
16
|
+
* command line.
|
|
17
|
+
*/
|
|
18
|
+
findBySlugOrName(query: string): CliFirestoreQueryManifestEntry | undefined;
|
|
19
|
+
findByModel(model: string): readonly CliFirestoreQueryManifestEntry[];
|
|
20
|
+
findByCollection(collection: string): readonly CliFirestoreQueryManifestEntry[];
|
|
21
|
+
findByCategory(category: string): readonly CliFirestoreQueryManifestEntry[];
|
|
22
|
+
findByTag(tag: string): readonly CliFirestoreQueryManifestEntry[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds a {@link CliFirestoreQueryRegistry} over a generated manifest.
|
|
26
|
+
*
|
|
27
|
+
* @param manifest - The generated `<NS>_FIRESTORE_QUERY_MANIFEST`.
|
|
28
|
+
* @returns The read API.
|
|
29
|
+
*
|
|
30
|
+
* @__NO_SIDE_EFFECTS__
|
|
31
|
+
*/
|
|
32
|
+
export declare function createCliFirestoreQueryRegistry(manifest: CliFirestoreQueryManifest): CliFirestoreQueryRegistry;
|
package/src/lib/index.d.ts
CHANGED
|
@@ -5,9 +5,12 @@ export * from './config';
|
|
|
5
5
|
export * from './context';
|
|
6
6
|
export * from './doctor';
|
|
7
7
|
export * from './env';
|
|
8
|
+
export * from './firestore';
|
|
8
9
|
export * from './manifest';
|
|
9
10
|
export * from './mcp-scan';
|
|
10
11
|
export * from './middleware';
|
|
12
|
+
export * from './scan-helpers/emit-generated-ts.js';
|
|
13
|
+
export * from './scan-helpers/exported-from-package.js';
|
|
11
14
|
export * from './scan-helpers/scan-io.js';
|
|
12
15
|
export * from './scan-helpers/scan-extract-utils.js';
|
|
13
16
|
export * from './scan-helpers/firestore-model-extract-utils.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FirestoreQueryConstraint } from '@dereekb/firebase';
|
|
1
2
|
import type { Maybe } from '@dereekb/util';
|
|
2
3
|
import { type Type } from 'arktype';
|
|
3
4
|
/**
|
|
@@ -134,6 +135,14 @@ export interface CliModelManifestEntry {
|
|
|
134
135
|
* `system` / `owner` / `admin-only` / `permissions`. Absent when the model interface omits the tag.
|
|
135
136
|
*/
|
|
136
137
|
readonly read?: 'system' | 'owner' | 'admin-only' | 'permissions';
|
|
138
|
+
/**
|
|
139
|
+
* True when the model declared `@dbxModelServerOnly` — no client may read it, on any path.
|
|
140
|
+
*
|
|
141
|
+
* Mirrors `FirebaseModelServiceConfig.serverOnly` on the runtime side. Carried on the manifest so
|
|
142
|
+
* the CLI can refuse the read locally, before choosing a transport, instead of round-tripping to
|
|
143
|
+
* an API that will refuse it anyway.
|
|
144
|
+
*/
|
|
145
|
+
readonly serverOnly?: boolean;
|
|
137
146
|
/**
|
|
138
147
|
* Resolved `@dbxModelServiceFactory <modelType>`-tagged export that implements this model.
|
|
139
148
|
* Joined by `modelType` during model-manifest assembly. Absent when no factory was found
|
|
@@ -328,6 +337,13 @@ export interface McpManifestModelEntry {
|
|
|
328
337
|
* build-time name validation so both compose the same names.
|
|
329
338
|
*/
|
|
330
339
|
readonly mcpToolNameSegment?: string;
|
|
340
|
+
/**
|
|
341
|
+
* True when the model declared `@dbxModelServerOnly` — no client may read it, on any path.
|
|
342
|
+
*
|
|
343
|
+
* Surfaced in the MCP catalog so a tool consumer sees the refusal is structural (there is no
|
|
344
|
+
* client read grant in `firestore.rules` either) rather than a missing role it could be granted.
|
|
345
|
+
*/
|
|
346
|
+
readonly serverOnly?: boolean;
|
|
331
347
|
}
|
|
332
348
|
/**
|
|
333
349
|
* One auth claim entry in the pre-rendered MCP manifest JSON. Powers the
|
|
@@ -512,3 +528,104 @@ export declare function abbreviateMcpCallType(callType: string): string;
|
|
|
512
528
|
* ```
|
|
513
529
|
*/
|
|
514
530
|
export declare function buildDisambiguatedMcpToolName(modelSegment: string, callType: string, specifier?: Maybe<string>): string;
|
|
531
|
+
/**
|
|
532
|
+
* Firestore query scope a catalog entry runs at, mirroring
|
|
533
|
+
* `@dbxModelFirebaseIndexScope`.
|
|
534
|
+
*/
|
|
535
|
+
export type CliFirestoreQueryScope = 'COLLECTION' | 'COLLECTION_GROUP';
|
|
536
|
+
/**
|
|
537
|
+
* One documented positional parameter of a query factory.
|
|
538
|
+
*
|
|
539
|
+
* `type` is the source type TEXT as written in the factory's signature, not a
|
|
540
|
+
* runtime validator — the manifest is generated by reading the AST, and there
|
|
541
|
+
* is deliberately no validator layer behind it.
|
|
542
|
+
*/
|
|
543
|
+
export interface CliFirestoreQueryParam {
|
|
544
|
+
readonly name: string;
|
|
545
|
+
/**
|
|
546
|
+
* The parameter's source type text, e.g. `string`, `Maybe<Date>`,
|
|
547
|
+
* `PublishedGuestbookEntriesQueryParams`.
|
|
548
|
+
*/
|
|
549
|
+
readonly type: string;
|
|
550
|
+
readonly description?: string;
|
|
551
|
+
/**
|
|
552
|
+
* True for `?` params AND params carrying an initializer — either way the
|
|
553
|
+
* factory can be called without supplying one.
|
|
554
|
+
*/
|
|
555
|
+
readonly optional: boolean;
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* The callable shape a bound query factory exposes.
|
|
559
|
+
*
|
|
560
|
+
* Deliberately untyped in its arguments: the manifest binds factories with
|
|
561
|
+
* every positional shape the workspace's `*.query.ts` files use (zero-arg,
|
|
562
|
+
* single scalar, single params object, two positionals, ...).
|
|
563
|
+
*/
|
|
564
|
+
export type CliFirestoreQueryFactory = (...args: readonly any[]) => readonly FirestoreQueryConstraint[];
|
|
565
|
+
/**
|
|
566
|
+
* One entry in the generated per-model Firestore query catalog.
|
|
567
|
+
*
|
|
568
|
+
* Produced by the `firestore-query-manifest` generator from the same
|
|
569
|
+
* `@dbxModelFirebaseIndex`-tagged factories that drive `firestore.indexes.json`,
|
|
570
|
+
* so the catalog and the emitted indexes can never disagree.
|
|
571
|
+
*/
|
|
572
|
+
export interface CliFirestoreQueryManifestEntry {
|
|
573
|
+
/**
|
|
574
|
+
* Kebab-case identifier used on the command line.
|
|
575
|
+
*/
|
|
576
|
+
readonly slug: string;
|
|
577
|
+
/**
|
|
578
|
+
* The exported identifier of the factory.
|
|
579
|
+
*/
|
|
580
|
+
readonly name: string;
|
|
581
|
+
/**
|
|
582
|
+
* The package the factory is exported from.
|
|
583
|
+
*/
|
|
584
|
+
readonly module: string;
|
|
585
|
+
/**
|
|
586
|
+
* The factory's source file, relative to the source package.
|
|
587
|
+
*/
|
|
588
|
+
readonly subpath: string;
|
|
589
|
+
/**
|
|
590
|
+
* PascalCase model name, from `@dbxModelFirebaseIndexModel`.
|
|
591
|
+
*/
|
|
592
|
+
readonly model: string;
|
|
593
|
+
/**
|
|
594
|
+
* Short collection name — joins {@link CliModelManifestEntry.collectionPrefix}.
|
|
595
|
+
*/
|
|
596
|
+
readonly collection: string;
|
|
597
|
+
readonly isNested: boolean;
|
|
598
|
+
readonly scope: CliFirestoreQueryScope;
|
|
599
|
+
/**
|
|
600
|
+
* The factory's full source signature, quoted back in argument errors.
|
|
601
|
+
*/
|
|
602
|
+
readonly signature: string;
|
|
603
|
+
readonly params: readonly CliFirestoreQueryParam[];
|
|
604
|
+
readonly description?: string;
|
|
605
|
+
readonly category?: string;
|
|
606
|
+
readonly tags?: readonly string[];
|
|
607
|
+
readonly example?: string;
|
|
608
|
+
readonly relatedSlugs?: readonly string[];
|
|
609
|
+
/**
|
|
610
|
+
* Index-emission governance flags carried through from the extractor. None
|
|
611
|
+
* of them affect callability — they govern what lands in
|
|
612
|
+
* `firestore.indexes.json`.
|
|
613
|
+
*/
|
|
614
|
+
readonly manual?: boolean;
|
|
615
|
+
readonly skip?: boolean;
|
|
616
|
+
readonly excluded?: boolean;
|
|
617
|
+
/**
|
|
618
|
+
* True for a factory that only delegates to others; invocable, but its own
|
|
619
|
+
* constraint sequence is empty by design. See {@link relatedSlugs}.
|
|
620
|
+
*/
|
|
621
|
+
readonly dispatcher?: boolean;
|
|
622
|
+
/**
|
|
623
|
+
* Absent when the identifier is not exported from {@link module}'s barrel
|
|
624
|
+
* chain — the entry is listed but cannot be executed.
|
|
625
|
+
*/
|
|
626
|
+
readonly factory?: CliFirestoreQueryFactory;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* The generated per-model Firestore query catalog.
|
|
630
|
+
*/
|
|
631
|
+
export type CliFirestoreQueryManifest = readonly CliFirestoreQueryManifestEntry[];
|
|
@@ -59,7 +59,7 @@ export type DbxDocsUiExampleUseEntry = typeof DbxDocsUiExampleUseEntry.infer;
|
|
|
59
59
|
*/
|
|
60
60
|
export declare const DbxDocsUiExampleEntry: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
61
61
|
slug: string;
|
|
62
|
-
category: "
|
|
62
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
63
63
|
summary: string;
|
|
64
64
|
header: string;
|
|
65
65
|
className: string;
|
|
@@ -103,7 +103,7 @@ export declare const DbxDocsUiExampleManifest: import("arktype/internal/variants
|
|
|
103
103
|
generator: string;
|
|
104
104
|
entries: {
|
|
105
105
|
slug: string;
|
|
106
|
-
category: "
|
|
106
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
107
107
|
summary: string;
|
|
108
108
|
header: string;
|
|
109
109
|
className: string;
|
|
@@ -56,7 +56,7 @@ export type ModelSnapshotFieldParamEntry = typeof ModelSnapshotFieldParamEntry.i
|
|
|
56
56
|
export declare const ModelSnapshotFieldEntry: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
57
57
|
slug: string;
|
|
58
58
|
name: string;
|
|
59
|
-
kind: "
|
|
59
|
+
kind: "factory" | "const";
|
|
60
60
|
category: string;
|
|
61
61
|
module: string;
|
|
62
62
|
subpath: string;
|
|
@@ -99,7 +99,7 @@ export declare const ModelSnapshotFieldManifest: import("arktype/internal/varian
|
|
|
99
99
|
entries: {
|
|
100
100
|
slug: string;
|
|
101
101
|
name: string;
|
|
102
|
-
kind: "
|
|
102
|
+
kind: "factory" | "const";
|
|
103
103
|
category: string;
|
|
104
104
|
module: string;
|
|
105
105
|
subpath: string;
|
|
@@ -57,7 +57,7 @@ export type PipeArgEntry = typeof PipeArgEntry.infer;
|
|
|
57
57
|
*/
|
|
58
58
|
export declare const PipeEntry: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
59
59
|
slug: string;
|
|
60
|
-
category: "
|
|
60
|
+
category: "value" | "date" | "misc" | "async";
|
|
61
61
|
pipeName: string;
|
|
62
62
|
className: string;
|
|
63
63
|
module: string;
|
|
@@ -98,7 +98,7 @@ export declare const PipeManifest: import("arktype/internal/variants/object.ts")
|
|
|
98
98
|
generator: string;
|
|
99
99
|
entries: {
|
|
100
100
|
slug: string;
|
|
101
|
-
category: "
|
|
101
|
+
category: "value" | "date" | "misc" | "async";
|
|
102
102
|
pipeName: string;
|
|
103
103
|
className: string;
|
|
104
104
|
module: string;
|
|
@@ -67,7 +67,7 @@ export type UiComponentOutputEntry = typeof UiComponentOutputEntry.infer;
|
|
|
67
67
|
*/
|
|
68
68
|
export declare const UiComponentEntry: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
69
69
|
slug: string;
|
|
70
|
-
category: "
|
|
70
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
71
71
|
kind: "pipe" | "component" | "directive" | "service";
|
|
72
72
|
selector: string;
|
|
73
73
|
className: string;
|
|
@@ -116,7 +116,7 @@ export declare const UiComponentManifest: import("arktype/internal/variants/obje
|
|
|
116
116
|
generator: string;
|
|
117
117
|
entries: {
|
|
118
118
|
slug: string;
|
|
119
|
-
category: "
|
|
119
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
120
120
|
kind: "pipe" | "component" | "directive" | "service";
|
|
121
121
|
selector: string;
|
|
122
122
|
className: string;
|
|
@@ -51,7 +51,7 @@ export type UtilParamEntry = typeof UtilParamEntry.infer;
|
|
|
51
51
|
export declare const UtilEntry: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
52
52
|
slug: string;
|
|
53
53
|
name: string;
|
|
54
|
-
kind: "function" | "
|
|
54
|
+
kind: "function" | "factory" | "class" | "const";
|
|
55
55
|
category: string;
|
|
56
56
|
module: string;
|
|
57
57
|
subpath: string;
|
|
@@ -93,7 +93,7 @@ export declare const UtilManifest: import("arktype/internal/variants/object.ts")
|
|
|
93
93
|
entries: {
|
|
94
94
|
slug: string;
|
|
95
95
|
name: string;
|
|
96
|
-
kind: "function" | "
|
|
96
|
+
kind: "function" | "factory" | "class" | "const";
|
|
97
97
|
category: string;
|
|
98
98
|
module: string;
|
|
99
99
|
subpath: string;
|
|
@@ -134,7 +134,7 @@ export declare function extractDbxDocsUiExampleEntries(input: ExtractDbxDocsUiEx
|
|
|
134
134
|
*/
|
|
135
135
|
export declare const ExtractedDbxDocsUiExampleEntrySchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
136
136
|
slug: string;
|
|
137
|
-
category: "
|
|
137
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
138
138
|
summary: string;
|
|
139
139
|
header: string;
|
|
140
140
|
className: string;
|
|
@@ -81,6 +81,11 @@ export interface ExtractedInterfaceTags {
|
|
|
81
81
|
readonly dbxModelOrganizationalGroupRoot: boolean;
|
|
82
82
|
readonly dbxModelCompositeKey?: ExtractedCompositeKeyTag;
|
|
83
83
|
readonly dbxModelRead?: DbxModelReadLevel;
|
|
84
|
+
/**
|
|
85
|
+
* True when the interface carries `@dbxModelServerOnly` — no client read grant exists in
|
|
86
|
+
* `firestore.rules`, and the model API must refuse the read too.
|
|
87
|
+
*/
|
|
88
|
+
readonly dbxModelServerOnly?: boolean;
|
|
84
89
|
}
|
|
85
90
|
/**
|
|
86
91
|
* One `export interface` declaration. The `tags` flags drive model
|
|
@@ -95,7 +95,7 @@ export declare function extractUiEntries(input: ExtractUiEntriesInput): ExtractU
|
|
|
95
95
|
*/
|
|
96
96
|
export declare const ExtractedUiEntrySchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
97
97
|
slug: string;
|
|
98
|
-
category: "
|
|
98
|
+
category: "list" | "action" | "screen" | "text" | "layout" | "button" | "card" | "feedback" | "overlay" | "navigation" | "router" | "misc";
|
|
99
99
|
kind: "pipe" | "component" | "directive" | "service";
|
|
100
100
|
selector: string;
|
|
101
101
|
className: string;
|