@dereekb/dbx-cli 13.11.6 → 13.11.8

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/manifest-extract",
3
- "version": "13.11.6",
3
+ "version": "13.11.8",
4
4
  "sideEffects": false,
5
5
  "peerDependencies": {
6
6
  "ts-morph": "^21.0.0"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/dbx-cli",
3
- "version": "13.11.6",
3
+ "version": "13.11.8",
4
4
  "sideEffects": false,
5
5
  "bin": {
6
6
  "dbx-cli-generate-firebase-api-manifest": "firebase-api-manifest/main.js"
@@ -24,10 +24,10 @@
24
24
  }
25
25
  },
26
26
  "peerDependencies": {
27
- "@dereekb/date": "13.11.6",
28
- "@dereekb/firebase": "13.11.6",
29
- "@dereekb/nestjs": "13.11.6",
30
- "@dereekb/util": "13.11.6",
27
+ "@dereekb/date": "13.11.8",
28
+ "@dereekb/firebase": "13.11.8",
29
+ "@dereekb/nestjs": "13.11.8",
30
+ "@dereekb/util": "13.11.8",
31
31
  "arktype": "^2.2.0",
32
32
  "yargs": "^18.0.0"
33
33
  },
@@ -1,5 +1,6 @@
1
1
  import type { OnCallTypedModelParams } from '@dereekb/firebase';
2
2
  export declare const CALL_MODEL_API_PATH = "/model/call";
3
+ export declare const MAX_MODEL_ACCESS_MULTI_READ_KEYS = 50;
3
4
  export interface CallModelOverHttpInput<T = unknown> {
4
5
  /**
5
6
  * The API base URL — typically `<host>/<project>/us-central1/api` or `https://<domain>/api`.
@@ -34,4 +35,78 @@ export interface CallModelOverHttpResponse<R = unknown> {
34
35
  * @returns The parsed JSON response body cast to `R`.
35
36
  */
36
37
  export declare function callModelOverHttp<T = unknown, R = unknown>(input: CallModelOverHttpInput<T>): Promise<R>;
38
+ export interface GetModelOverHttpInput {
39
+ /**
40
+ * The API base URL — typically `<host>/<project>/us-central1/api` or `https://<domain>/api`.
41
+ *
42
+ * The `/model/<modelType>/get` path is appended automatically.
43
+ */
44
+ readonly apiBaseUrl: string;
45
+ readonly accessToken: string;
46
+ readonly modelType: string;
47
+ readonly key: string;
48
+ /**
49
+ * Custom fetch implementation for tests.
50
+ */
51
+ readonly fetcher?: typeof fetch;
52
+ }
53
+ export interface GetModelOverHttpResult<T = unknown> {
54
+ readonly key: string;
55
+ readonly data: T;
56
+ }
57
+ /**
58
+ * GETs a single Firestore document by key via the typed model-access endpoint.
59
+ *
60
+ * Calls `<apiBaseUrl>/model/<modelType>/get?key=<encoded key>` with a Bearer access token and
61
+ * returns the parsed `{ key, data }` envelope. Non-2xx responses are mapped to a {@link CliError}
62
+ * with a stable code derived from the status — matching {@link callModelOverHttp}'s error shape.
63
+ *
64
+ * The backend route is implemented by `ModelApiController.getOne` (packages/firebase-server) and
65
+ * enforces `roles: 'read'` via `useModel(...)` so Firestore security rules still apply.
66
+ *
67
+ * @param input - The request envelope describing the API target, access token, model + key, and optional fetch override.
68
+ * @returns The parsed `{ key, data }` envelope.
69
+ */
70
+ export declare function getModelOverHttp<T = unknown>(input: GetModelOverHttpInput): Promise<GetModelOverHttpResult<T>>;
71
+ export interface GetMultipleModelsOverHttpInput {
72
+ /**
73
+ * The API base URL — typically `<host>/<project>/us-central1/api` or `https://<domain>/api`.
74
+ *
75
+ * The `/model/<modelType>/get` path is appended automatically.
76
+ */
77
+ readonly apiBaseUrl: string;
78
+ readonly accessToken: string;
79
+ readonly modelType: string;
80
+ readonly keys: ReadonlyArray<string>;
81
+ /**
82
+ * Custom fetch implementation for tests.
83
+ */
84
+ readonly fetcher?: typeof fetch;
85
+ }
86
+ export interface GetMultipleModelsOverHttpResultEntry<T = unknown> {
87
+ readonly key: string;
88
+ readonly data: T;
89
+ }
90
+ export interface GetMultipleModelsOverHttpErrorEntry {
91
+ readonly key: string;
92
+ readonly error: string;
93
+ readonly code?: string;
94
+ }
95
+ export interface GetMultipleModelsOverHttpResult<T = unknown> {
96
+ readonly results: ReadonlyArray<GetMultipleModelsOverHttpResultEntry<T>>;
97
+ readonly errors: ReadonlyArray<GetMultipleModelsOverHttpErrorEntry>;
98
+ }
99
+ /**
100
+ * Batch-reads up to {@link MAX_MODEL_ACCESS_MULTI_READ_KEYS} Firestore documents in a single request.
101
+ *
102
+ * Calls `POST <apiBaseUrl>/model/<modelType>/get` with body `{ keys }` and returns the
103
+ * `{ results, errors }` envelope. The 50-key cap is enforced client-side so the error surfaces
104
+ * with a clear `INVALID_ARGUMENT` code before the request is made.
105
+ *
106
+ * Backend route: `ModelApiController.getMany` (packages/firebase-server). Same `'read'` role enforcement.
107
+ *
108
+ * @param input - The request envelope describing the API target, access token, model, keys, and optional fetch override.
109
+ * @returns The parsed `{ results, errors }` envelope.
110
+ */
111
+ export declare function getMultipleModelsOverHttp<T = unknown>(input: GetMultipleModelsOverHttpInput): Promise<GetMultipleModelsOverHttpResult<T>>;
37
112
  export { CALL_MODEL_APP_FUNCTION_KEY } from '@dereekb/firebase';
@@ -0,0 +1,61 @@
1
+ import { type CliModelManifest } from '../manifest/types';
2
+ /**
3
+ * Parsed `get` command arguments — the resolved `modelType` + the original key string.
4
+ */
5
+ export interface ParsedGetArgs {
6
+ readonly modelType: string;
7
+ readonly key: string;
8
+ }
9
+ /**
10
+ * Parsed `get-many` command arguments — the resolved `modelType` + the list of keys.
11
+ */
12
+ export interface ParsedGetManyArgs {
13
+ readonly modelType: string;
14
+ readonly keys: ReadonlyArray<string>;
15
+ }
16
+ /**
17
+ * Parses the positionals for the top-level `get <modelOrKey> [key]` command into a
18
+ * `{ modelType, key }` pair, using the supplied {@link CliModelManifest} to resolve
19
+ * collection-name prefixes when the explicit-model form is not used.
20
+ *
21
+ * Rules:
22
+ * 1. Two positionals (`modelOrKey` + `key`) — `modelOrKey` is treated as the explicit
23
+ * `modelType` and `key` is passed through verbatim. No manifest lookup performed.
24
+ * 2. One positional (`modelOrKey` only) — treated as a full Firestore key (`prefix/id`).
25
+ * {@link decodeFirestoreModelKey} resolves the prefix against the manifest. Throws
26
+ * {@link CliError} if the manifest is missing, the prefix is unresolved, or the leaf
27
+ * has no `modelType`.
28
+ *
29
+ * @param input.modelOrKey - The first positional from yargs.
30
+ * @param input.key - The optional second positional from yargs.
31
+ * @param input.manifest - The generated model manifest (for prefix lookup).
32
+ * @returns The parsed `{ modelType, key }` pair.
33
+ * @__NO_SIDE_EFFECTS__
34
+ */
35
+ export declare function parseGetArgs(input: {
36
+ readonly modelOrKey: string | undefined;
37
+ readonly key: string | undefined;
38
+ readonly manifest?: CliModelManifest;
39
+ }): ParsedGetArgs;
40
+ /**
41
+ * Parses the positionals for the top-level `get-many <firstArg> [rest..]` command.
42
+ *
43
+ * Rules:
44
+ * 1. If `firstArg` contains `/` it is treated as a key — all positionals (`firstArg` + `rest`)
45
+ * are decoded via {@link decodeFirestoreModelKey}. All keys must resolve to the same
46
+ * `modelType` or a {@link CliError} is thrown (the backend route is single-modelType per call).
47
+ * 2. Otherwise `firstArg` is treated as the explicit `modelType` and `rest` are the keys.
48
+ *
49
+ * Always rejects empty key lists and lists exceeding 50 keys.
50
+ *
51
+ * @param input.firstArg - The first positional from yargs.
52
+ * @param input.rest - The remaining positionals from yargs.
53
+ * @param input.manifest - The generated model manifest (used only in the inferred-key branch).
54
+ * @returns The parsed `{ modelType, keys }` pair.
55
+ * @__NO_SIDE_EFFECTS__
56
+ */
57
+ export declare function parseGetManyArgs(input: {
58
+ readonly firstArg: string | undefined;
59
+ readonly rest: ReadonlyArray<string>;
60
+ readonly manifest?: CliModelManifest;
61
+ }): ParsedGetManyArgs;
@@ -0,0 +1,11 @@
1
+ import type { CommandModule } from 'yargs';
2
+ /**
3
+ * Top-level `get-many <firstArg> [rest..]` command.
4
+ *
5
+ * Batch-reads up to 50 Firestore documents in a single request. The first positional can either
6
+ * be an explicit modelType (followed by ≥1 keys) or a full key (followed by additional keys whose
7
+ * prefixes must resolve to the same modelType).
8
+ *
9
+ * Backend: `POST <apiBaseUrl>/model/<modelType>/get` with body `{ keys }` (ModelApiController.getMany).
10
+ */
11
+ export declare const getManyCommand: CommandModule;
@@ -0,0 +1,12 @@
1
+ import type { CommandModule } from 'yargs';
2
+ /**
3
+ * Top-level `get <modelOrKey> [key]` command.
4
+ *
5
+ * Reads a single Firestore document via the typed model-access endpoint. The `model` arg is optional:
6
+ * when only one positional is supplied, the CLI resolves the modelType from the key's leading
7
+ * collection-name prefix via {@link decodeFirestoreModelKey}. The two-positional form passes the
8
+ * explicit `modelType` straight through.
9
+ *
10
+ * Backend: `GET <apiBaseUrl>/model/<modelType>/get?key=<key>` (ModelApiController.getOne).
11
+ */
12
+ export declare const getCommand: CommandModule;
@@ -2,3 +2,6 @@ export * from './call-model.client';
2
2
  export * from './call-model.command.factory';
3
3
  export * from './call.passthrough.command';
4
4
  export * from './expand-keys';
5
+ export * from './get-args.helper';
6
+ export * from './get.command';
7
+ export * from './get-many.command';
@@ -37,7 +37,8 @@ export interface DiscoverOidcMetadataInput {
37
37
  readonly fallbackBaseUrl?: string;
38
38
  }
39
39
  /**
40
- * Fetches the OIDC discovery document for the given issuer, trying these candidates in order:
40
+ * Builds the ordered list of `.well-known/openid-configuration` URLs the CLI probes when
41
+ * discovering OIDC metadata.
41
42
  *
42
43
  * 1. `<issuer>/.well-known/openid-configuration` (OpenID Connect Discovery 1.0).
43
44
  * 2. `<issuer-origin>/.well-known/openid-configuration` (host-rooted; matches projects that
@@ -45,6 +46,19 @@ export interface DiscoverOidcMetadataInput {
45
46
  * sub-path — e.g. demo's `OidcWellKnownController`).
46
47
  * 3. `<fallbackBaseUrl>/.well-known/openid-configuration` when supplied and not already covered.
47
48
  *
49
+ * Exported so diagnostic surfaces (e.g. `doctor`) can show the exact URLs the discovery step
50
+ * tried — without re-implementing the candidate ordering.
51
+ *
52
+ * @param input - The discovery request.
53
+ * @param input.issuer - The OIDC issuer URL whose `.well-known/openid-configuration` is fetched first.
54
+ * @param input.fallbackBaseUrl - Optional sibling base URL appended after the issuer-prefixed and origin-rooted candidates.
55
+ * @returns The candidate URL list in probe order, de-duplicated.
56
+ */
57
+ export declare function buildOidcDiscoveryCandidates(input: DiscoverOidcMetadataInput): string[];
58
+ /**
59
+ * Fetches the OIDC discovery document for the given issuer, trying the candidates returned by
60
+ * {@link buildOidcDiscoveryCandidates} in order.
61
+ *
48
62
  * @param input - The discovery request.
49
63
  * @param input.issuer - The OIDC issuer URL whose `.well-known/openid-configuration` is fetched first.
50
64
  * @param input.fallbackBaseUrl - Optional sibling base URL tried after the issuer-prefixed and origin-rooted candidates.
@@ -2,19 +2,30 @@ import { type Maybe } from '@dereekb/util';
2
2
  export interface BuildAuthorizationUrlInput {
3
3
  readonly authorizationEndpoint: string;
4
4
  /**
5
- * Optional API base URL. When set and `appClientUrl` is not provided, the CLI sends the user
6
- * to `<apiBaseUrl>/oidc/login/client?<params>` instead of the raw authorization endpoint. The
7
- * API redirects to the configured app login URL with the OAuth query string preserved, so the
8
- * CLI does not need to know the client origin directly.
5
+ * Optional OIDC issuer URL (e.g. `https://api.example.com/oidc`). Used as a fallback rebase
6
+ * origin when `appClientUrl` is not provided — the origin of `oidcIssuer` is applied to the
7
+ * discovered `authorizationEndpoint`. In typical OIDC deployments the issuer and authorization
8
+ * endpoint share an origin, so this fallback is a no-op rebase that ends up at the discovered
9
+ * `/oidc/auth` URL. Use `appClientUrl` to send the user to a different origin (e.g. a frontend
10
+ * dev server that proxies `/oidc/**` back to the API).
11
+ */
12
+ readonly oidcIssuer?: Maybe<string>;
13
+ /**
14
+ * Optional API base URL. Used as a fallback rebase origin when neither `appClientUrl` nor
15
+ * `oidcIssuer` is provided — only the origin is read, so prefix paths like `/api` are ignored.
16
+ * Prefer `oidcIssuer` for new deployments; `apiBaseUrl` is kept for backwards compatibility
17
+ * with envs that only declare an API base URL.
9
18
  */
10
19
  readonly apiBaseUrl?: Maybe<string>;
11
20
  /**
12
- * Optional client (frontend) origin to rebase the authorization endpoint onto.
21
+ * Optional client origin to rebase the authorization endpoint onto.
13
22
  *
14
23
  * When set, the path + search of `authorizationEndpoint` are kept and the origin is replaced
15
- * with this URL. Useful when the frontend dev server proxies `/oidc/**` to the API and the
16
- * user-facing URL should target the app, not the API directly. Takes precedence over
17
- * `apiBaseUrl` when both are provided.
24
+ * with this URL. Takes precedence over both `oidcIssuer` and `apiBaseUrl`. Recommended for any
25
+ * env where the user-facing URL should differ from the discovered authorization endpoint
26
+ * e.g. a frontend dev server that proxies `/oidc/**` to the API on another port. When omitted,
27
+ * the URL is derived from `oidcIssuer`/`apiBaseUrl` origin (or used verbatim if neither is set),
28
+ * so the CLI always opens the actual authorization endpoint (typically `/oidc/auth`).
18
29
  */
19
30
  readonly appClientUrl?: Maybe<string>;
20
31
  readonly clientId: string;
@@ -33,14 +44,24 @@ export interface BuildAuthorizationUrlInput {
33
44
  /**
34
45
  * Builds the authorization URL the user opens in a browser to start the PKCE flow.
35
46
  *
36
- * Resolves the user-facing endpoint by preferring `appClientUrl` (rebases the discovered
37
- * authorization endpoint onto that origin) over `apiBaseUrl` (`/oidc/login/client` shortcut),
38
- * and finally falls back to the discovered `authorizationEndpoint` itself.
47
+ * The user-facing endpoint is the discovered `authorizationEndpoint` (typically `/oidc/auth`)
48
+ * with its origin optionally rebased. The rebase origin is the first non-empty value among
49
+ * `appClientUrl` `oidcIssuer` origin `apiBaseUrl` origin. In a typical single-host
50
+ * deployment all three resolve to the same origin and the rebase is a no-op; in a split-host
51
+ * setup (frontend dev server proxying `/oidc/**` to the API) `appClientUrl` redirects the user
52
+ * through the frontend. When none of the three is provided, the discovered endpoint is used
53
+ * unchanged.
54
+ *
55
+ * Always lands at the actual authorization endpoint so oidc-provider can create an interaction
56
+ * and redirect to the app login page with a `uid`. (Earlier versions targeted a convenience
57
+ * `/oidc/login/client` redirect that forwarded query params to the app without creating an
58
+ * interaction — that branch is gone.)
39
59
  *
40
60
  * @param input - The authorization URL inputs.
41
61
  * @param input.authorizationEndpoint - The authorization endpoint discovered from OIDC metadata.
42
- * @param input.apiBaseUrl - Optional API base URL; when set without `appClientUrl`, the URL is built against `<apiBaseUrl>/oidc/login/client`.
43
- * @param input.appClientUrl - Optional frontend origin to rebase the authorization endpoint onto. Takes precedence over `apiBaseUrl`.
62
+ * @param input.appClientUrl - Optional client origin to rebase the authorization endpoint onto. Takes precedence over `oidcIssuer` and `apiBaseUrl`.
63
+ * @param input.oidcIssuer - Optional OIDC issuer URL; falls back to its origin as the rebase target when `appClientUrl` is missing.
64
+ * @param input.apiBaseUrl - Optional API base URL; falls back to its origin as the rebase target when neither `appClientUrl` nor `oidcIssuer` is set.
44
65
  * @param input.clientId - The OAuth client ID.
45
66
  * @param input.redirectUri - The redirect URI registered with the OAuth client.
46
67
  * @param input.scopes - Space-separated scope list. Defaults to {@link DEFAULT_CLI_OIDC_SCOPES}.
@@ -11,6 +11,12 @@ export declare const DEFAULT_CLI_OIDC_SCOPES = "openid profile email";
11
11
  * CLI doesn't take a server-side dependency just to know the names.
12
12
  */
13
13
  export declare const MODEL_WRITE_OIDC_SCOPES: readonly ["model.create", "model.update", "model.delete"];
14
+ /**
15
+ * The default redirect URI used by the CLI.
16
+ *
17
+ * Opens up to nothing in the browser so the user can copy/paste the resulting token url back into the CLI.
18
+ */
19
+ export declare const DEFAULT_CLI_REDIRECT_URI = "http://127.0.0.1:0/callback";
14
20
  /**
15
21
  * Returns the input scope string with the `model.create`, `model.update`, and `model.delete`
16
22
  * scopes removed, preserving every other scope (including `model.read` and `model.query`).
@@ -119,6 +125,8 @@ export interface CliEnvConfig {
119
125
  * The redirect URI registered with the OAuth client. The CLI does not bind a server — it parses
120
126
  * the URL the user pastes back, so this can be any value the OIDC provider accepts as a
121
127
  * registered redirect URI (e.g. `http://127.0.0.1:0/callback` or another loopback/placeholder URL).
128
+ *
129
+ * Defaults to {@link DEFAULT_CLI_REDIRECT_URI}.
122
130
  */
123
131
  readonly redirectUri?: string;
124
132
  /**
@@ -1,10 +1,18 @@
1
1
  import type { OnCallTypedModelParams } from '@dereekb/firebase';
2
2
  import { type CliEnvConfig } from '../config/env';
3
+ import { type GetModelOverHttpResult, type GetMultipleModelsOverHttpResult } from '../api/call-model.client';
4
+ import { type CliModelManifest } from '../manifest/types';
3
5
  /**
4
6
  * The CLI context attached to argv by the auth middleware.
5
7
  *
6
- * Holds the active env, the current access token, and a `callModel` helper that performs
7
- * the HTTP call against `<env.apiBaseUrl>/model/call`.
8
+ * Holds the active env, the current access token, and helpers that perform HTTP calls against
9
+ * `<env.apiBaseUrl>/model/*`:
10
+ * - {@link CliContext.callModel} → `POST /model/call` (typed model dispatch)
11
+ * - {@link CliContext.getModel} → `GET /model/<modelType>/get?key=<key>`
12
+ * - {@link CliContext.getMultipleModels} → `POST /model/<modelType>/get` with `{ keys }`
13
+ *
14
+ * When provided by the runner, {@link CliContext.modelManifest} carries the generated
15
+ * `CliModelManifest` so commands can resolve `prefix/id` keys to a `modelType`.
8
16
  */
9
17
  export interface CliContext {
10
18
  readonly cliName: string;
@@ -12,6 +20,9 @@ export interface CliContext {
12
20
  readonly env: CliEnvConfig;
13
21
  readonly accessToken: string;
14
22
  readonly callModel: <TParams = unknown, TResult = unknown>(params: OnCallTypedModelParams<TParams>) => Promise<TResult>;
23
+ readonly getModel: <TResult = unknown>(modelType: string, key: string) => Promise<GetModelOverHttpResult<TResult>>;
24
+ readonly getMultipleModels: <TResult = unknown>(modelType: string, keys: ReadonlyArray<string>) => Promise<GetMultipleModelsOverHttpResult<TResult>>;
25
+ readonly modelManifest?: CliModelManifest;
15
26
  }
16
27
  export declare const setCliContext: (value: import("@dereekb/util").Maybe<CliContext>) => void;
17
28
  export declare const getCliContext: () => import("@dereekb/util").Maybe<CliContext>;
@@ -24,18 +35,24 @@ export interface CreateCliContextInput {
24
35
  readonly envName: string;
25
36
  readonly env: CliEnvConfig;
26
37
  readonly accessToken: string;
38
+ /**
39
+ * Optional generated model manifest. When supplied, surfaced on the context so commands
40
+ * (e.g. `get <key>`) can resolve `prefix/id` keys to a `modelType` via `decodeFirestoreModelKey`.
41
+ */
42
+ readonly modelManifest?: CliModelManifest;
27
43
  }
28
44
  /**
29
45
  * Builds a {@link CliContext} for the current invocation.
30
46
  *
31
- * Bundles the env config and access token alongside a `callModel` helper that POSTs to
32
- * `<env.apiBaseUrl>/model/call` with the cached Bearer token.
47
+ * Bundles the env config and access token alongside helpers that POST/GET against
48
+ * `<env.apiBaseUrl>/model/*` with the cached Bearer token.
33
49
  *
34
50
  * @param input - The context inputs.
35
51
  * @param input.cliName - The CLI's binary name.
36
52
  * @param input.envName - The active env name.
37
53
  * @param input.env - The resolved {@link CliEnvConfig} for the active env.
38
54
  * @param input.accessToken - The Bearer access token to include on outgoing API calls.
55
+ * @param input.modelManifest - Optional generated {@link CliModelManifest} for key→modelType resolution.
39
56
  * @returns The constructed {@link CliContext}.
40
57
  * @__NO_SIDE_EFFECTS__
41
58
  */
@@ -0,0 +1,79 @@
1
+ import type { CommandModule } from 'yargs';
2
+ import type { CliModelManifest } from './types';
3
+ /**
4
+ * Default command name for the model-decode command. Top-level so it stays
5
+ * out of the API-call namespace owned by `model <model> <action>`.
6
+ */
7
+ export declare const DEFAULT_MODEL_DECODE_COMMAND_NAME = "model-decode";
8
+ /**
9
+ * Options accepted by {@link buildModelDecodeCommand}.
10
+ */
11
+ export interface BuildModelDecodeCommandOptions {
12
+ /**
13
+ * Override the parent command name. Defaults to
14
+ * {@link DEFAULT_MODEL_DECODE_COMMAND_NAME}.
15
+ */
16
+ readonly commandName?: string;
17
+ }
18
+ /**
19
+ * One segment of a decoded Firestore key. `model*` fields are absent when the
20
+ * segment's `prefix` isn't in the manifest.
21
+ */
22
+ export interface DecodedKeySegment {
23
+ readonly prefix: string;
24
+ readonly id: string;
25
+ readonly modelName?: string;
26
+ readonly modelType?: string;
27
+ readonly modelGroup?: string;
28
+ readonly identityConst?: string;
29
+ readonly parentIdentityConst?: string;
30
+ readonly sourcePackage?: string;
31
+ readonly sourceFile?: string;
32
+ }
33
+ /**
34
+ * Result of decoding a Firestore model key into its model + id components.
35
+ */
36
+ export interface DecodedKey {
37
+ readonly key: string;
38
+ readonly leaf: DecodedKeySegment;
39
+ readonly ancestors: readonly DecodedKeySegment[];
40
+ readonly unresolvedPrefixes: readonly string[];
41
+ }
42
+ /**
43
+ * Builds the top-level `model-decode <key>` command.
44
+ *
45
+ * Splits the supplied Firestore key on `/`, walks `[prefix, id]` pairs, and
46
+ * resolves each prefix against the manifest. Supports subcollection paths
47
+ * (`nb/abc/nbn/def` → leaf `Notification` + parent `NotificationBox`).
48
+ *
49
+ * Flags:
50
+ * - `--json` emits a structured `{ ok, data }` envelope instead of the
51
+ * human-readable block (useful for scripting or LLM agents).
52
+ *
53
+ * @param manifest - The generated model manifest (e.g. `DEMO_CLI_MODEL_MANIFEST`).
54
+ * @param options - Optional overrides; see {@link BuildModelDecodeCommandOptions}.
55
+ * @returns A yargs `CommandModule` ready to be passed to `runCli({ configCommands })`.
56
+ * @__NO_SIDE_EFFECTS__
57
+ */
58
+ export declare function buildModelDecodeCommand(manifest: CliModelManifest, options?: BuildModelDecodeCommandOptions): CommandModule;
59
+ /**
60
+ * Splits `rawKey` on `/`, resolves each `[prefix, id]` pair against the
61
+ * manifest, and returns the leaf segment + ancestor chain. Throws
62
+ * {@link CliError} for malformed inputs.
63
+ *
64
+ * @param rawKey - The Firestore key string.
65
+ * @param manifest - The generated model manifest.
66
+ * @returns The decoded key with leaf, ancestors, and any unresolved prefixes.
67
+ * @__NO_SIDE_EFFECTS__
68
+ */
69
+ export declare function decodeFirestoreModelKey(rawKey: string, manifest: CliModelManifest): DecodedKey;
70
+ /**
71
+ * Renders a {@link DecodedKey} as a human-readable text block. Mirrors the
72
+ * MCP `dbx_model_decode` key-mode output for consistency between agent and
73
+ * shell consumers.
74
+ *
75
+ * @param decoded - the decoded key returned by {@link decodeFirestoreModelKey}.
76
+ * @returns the formatted block with a trailing newline.
77
+ * @__NO_SIDE_EFFECTS__
78
+ */
79
+ export declare function renderDecodedKey(decoded: DecodedKey): string;
@@ -1,4 +1,5 @@
1
1
  export * from './build-manifest-commands';
2
+ export * from './build-model-decode-command';
2
3
  export * from './build-model-info-command';
3
4
  export * from './model-info-utils';
4
5
  export * from './types';
@@ -1,5 +1,6 @@
1
1
  import type { MiddlewareFunction } from 'yargs';
2
2
  import { type CliEnvDefault } from '../config/env';
3
+ import { type CliModelManifest } from '../manifest/types';
3
4
  export interface CreateAuthMiddlewareInput {
4
5
  readonly cliName: string;
5
6
  /**
@@ -12,6 +13,11 @@ export interface CreateAuthMiddlewareInput {
12
13
  * Built-in env presets. Merged underneath the user's stored env when the env name matches.
13
14
  */
14
15
  readonly defaultEnvs?: readonly CliEnvDefault[];
16
+ /**
17
+ * Optional generated model manifest. When supplied, attached to the `CliContext` so commands
18
+ * can resolve `prefix/id` keys to a `modelType` via `decodeFirestoreModelKey`.
19
+ */
20
+ readonly modelManifest?: CliModelManifest;
15
21
  }
16
22
  /**
17
23
  * Yargs middleware that resolves the active env, loads/refreshes its access token, and attaches
@@ -45,18 +45,30 @@ export interface CreateCliInput {
45
45
  */
46
46
  readonly disableCallPassthrough?: boolean;
47
47
  /**
48
- * Generated Firestore model manifest used to drive the built-in `model-info` command.
48
+ * Disable the built-in `get <key>` / `get-many <key...>` commands.
49
49
  *
50
- * Opt-in: when provided, a top-level `model-info [model]` command is auto-wired into the built-in
51
- * config commands so users can browse the model catalog and per-model field documentation. When
52
- * omitted, no `model-info` command is registered. Apps that pass the manifest but want to suppress
53
- * the command can additionally set {@link disableModelInfo} to `true`.
50
+ * These hit the generic model-access endpoints (`GET /model/<modelType>/get` and
51
+ * `POST /model/<modelType>/get`) which already exist on every {@link ModelApiController}.
52
+ * Inferred-model resolution (`get jws/abc` `modelType: jobWorkerSchedule`) requires the
53
+ * generated {@link CreateCliInput.modelManifest} to be supplied; the explicit-model form
54
+ * (`get <model> <key>`) works without it.
55
+ */
56
+ readonly disableModelGet?: boolean;
57
+ /**
58
+ * Generated Firestore model manifest used to drive the built-in `model-info` and `model-decode`
59
+ * commands.
60
+ *
61
+ * Opt-in: when provided, top-level `model-info [model]` and `model-decode <key>` commands are
62
+ * auto-wired into the built-in config commands so users can browse the model catalog and turn
63
+ * raw Firestore keys (`sf/abc123`, `nb/abc/nbn/def`) into model + id info. When omitted, neither
64
+ * command is registered. Apps that pass the manifest but want to suppress one or both commands
65
+ * can set {@link disableModelInfo} and/or {@link disableModelDecode} to `true`.
54
66
  *
55
67
  * The manifest itself is also opt-in at build time. The `dbx-cli-firebase-api-manifest` generator
56
68
  * only emits `<NAMESPACE>_MODEL_MANIFEST` when invoked with `--emit-models`, so apps that never
57
69
  * enable this option won't bundle model metadata into their final binary.
58
70
  *
59
- * Note: this option only controls the `model-info` command. Manifest-driven typed model commands
71
+ * Note: this option only controls the inspection commands. Manifest-driven typed model commands
60
72
  * are still wired explicitly via {@link apiCommands} (see `buildManifestCommands`), and the
61
73
  * `--expand-keys` flag still requires passing the manifest to `buildManifestCommands`.
62
74
  */
@@ -68,6 +80,13 @@ export interface CreateCliInput {
68
80
  * but does not want to surface the `model-info` command itself.
69
81
  */
70
82
  readonly disableModelInfo?: boolean;
83
+ /**
84
+ * Disable the built-in `model-decode` command even when {@link modelManifest} is provided.
85
+ *
86
+ * Useful when an app wants the manifest available for `--expand-keys` or `model-info` but does
87
+ * not want to surface the key-decode command itself.
88
+ */
89
+ readonly disableModelDecode?: boolean;
71
90
  }
72
91
  /**
73
92
  * Top-level CLI builder.