@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.
- package/firebase-api-manifest/package.json +1 -1
- package/index.cjs.js +1330 -191
- package/index.esm.js +1318 -192
- package/manifest-extract/package.json +1 -1
- package/package.json +5 -5
- package/src/lib/api/call-model.client.d.ts +75 -0
- package/src/lib/api/get-args.helper.d.ts +61 -0
- package/src/lib/api/get-many.command.d.ts +11 -0
- package/src/lib/api/get.command.d.ts +12 -0
- package/src/lib/api/index.d.ts +3 -0
- package/src/lib/auth/oidc.client.d.ts +15 -1
- package/src/lib/auth/oidc.flow.d.ts +34 -13
- package/src/lib/config/env.d.ts +8 -0
- package/src/lib/context/cli.context.d.ts +21 -4
- package/src/lib/manifest/build-model-decode-command.d.ts +79 -0
- package/src/lib/manifest/index.d.ts +1 -0
- package/src/lib/middleware/auth.middleware.d.ts +6 -0
- package/src/lib/runner/run.d.ts +25 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/dbx-cli",
|
|
3
|
-
"version": "13.11.
|
|
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.
|
|
28
|
-
"@dereekb/firebase": "13.11.
|
|
29
|
-
"@dereekb/nestjs": "13.11.
|
|
30
|
-
"@dereekb/util": "13.11.
|
|
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;
|
package/src/lib/api/index.d.ts
CHANGED
|
@@ -37,7 +37,8 @@ export interface DiscoverOidcMetadataInput {
|
|
|
37
37
|
readonly fallbackBaseUrl?: string;
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
*
|
|
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
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
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
|
|
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.
|
|
16
|
-
* user-facing URL should
|
|
17
|
-
*
|
|
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
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
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.
|
|
43
|
-
* @param input.
|
|
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}.
|
package/src/lib/config/env.d.ts
CHANGED
|
@@ -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
|
|
7
|
-
*
|
|
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
|
|
32
|
-
* `<env.apiBaseUrl>/model
|
|
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,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
|
package/src/lib/runner/run.d.ts
CHANGED
|
@@ -45,18 +45,30 @@ export interface CreateCliInput {
|
|
|
45
45
|
*/
|
|
46
46
|
readonly disableCallPassthrough?: boolean;
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
48
|
+
* Disable the built-in `get <key>` / `get-many <key...>` commands.
|
|
49
49
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
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
|
|
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.
|