@dereekb/firebase-server 13.16.0 → 13.18.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.
@@ -0,0 +1,70 @@
1
+ import { type McpManifestEnum } from '../mcp.manifest';
2
+ import { type McpToolDefinition } from '../mcp.tool-generator';
3
+ /**
4
+ * Reserved tool name for the built-in `enum-info` static tool.
5
+ */
6
+ export declare const ENUM_INFO_TOOL_NAME = "enum-info";
7
+ /**
8
+ * Synthetic call type used in the tool's dispatch identity. Mirrors the `info` call shared with
9
+ * `model-info`.
10
+ */
11
+ export declare const ENUM_INFO_DISPATCH_CALL = "info";
12
+ /**
13
+ * Synthetic model type used in the tool's dispatch identity. Apps avoiding collisions should not
14
+ * register a real model literally named "enum".
15
+ */
16
+ export declare const ENUM_INFO_DISPATCH_MODEL_TYPE = "enum";
17
+ /**
18
+ * Constructor dependencies for {@link createEnumInfoTool}.
19
+ */
20
+ export interface CreateEnumInfoToolDeps {
21
+ /**
22
+ * Frozen enum value tables keyed by enum name, sourced from the build-time manifest's `enums`
23
+ * block.
24
+ */
25
+ readonly enums: {
26
+ readonly [name: string]: McpManifestEnum;
27
+ };
28
+ }
29
+ /**
30
+ * Shape of the `enum-info` tool input.
31
+ */
32
+ export interface EnumInfoToolInput {
33
+ /**
34
+ * One enum name (string) or several (string array), each matched exactly by declaration name.
35
+ */
36
+ readonly enum: string | ReadonlyArray<string>;
37
+ }
38
+ /**
39
+ * Output payload for the `enum-info` tool: the resolved value tables, with any unmatched names in
40
+ * `notFound`.
41
+ */
42
+ export interface EnumInfoToolOutput {
43
+ readonly enums: ReadonlyArray<McpManifestEnum>;
44
+ readonly notFound?: ReadonlyArray<string>;
45
+ }
46
+ /**
47
+ * Builds the built-in `enum-info` MCP tool definition — the symmetric counterpart to `model-info`
48
+ * for raw enum decoding.
49
+ *
50
+ * Resolves each requested enum name against the manifest's `enums` block and returns the matching
51
+ * value→label tables; misses land in `notFound`. A bare string is treated as a one-element array.
52
+ *
53
+ * Output is delivered as both stringified JSON in `content[0].text` and `structuredContent` so MCP
54
+ * clients can consume either form.
55
+ *
56
+ * @param deps - The frozen enum value tables loaded at boot from the MCP manifest JSON.
57
+ * @returns A statically-registered {@link McpToolDefinition} ready to be appended to the MCP server
58
+ * factory's tool registry.
59
+ */
60
+ export declare function createEnumInfoTool(deps: CreateEnumInfoToolDeps): McpToolDefinition;
61
+ /**
62
+ * Resolves each requested enum name against the registered value tables.
63
+ *
64
+ * @param names - The requested enum declaration names.
65
+ * @param enums - The registered enum value tables keyed by name.
66
+ * @returns The matched tables, with any unmatched names in `notFound`.
67
+ *
68
+ * @__NO_SIDE_EFFECTS__
69
+ */
70
+ export declare function resolveEnumInfoOutput(names: readonly string[], enums: CreateEnumInfoToolDeps['enums']): EnumInfoToolOutput;
@@ -1,4 +1,4 @@
1
- import { type McpManifestModelEntry } from '../mcp.manifest';
1
+ import { type McpManifestEnum, type McpManifestModelEntry } from '../mcp.manifest';
2
2
  import { type McpToolDefinition } from '../mcp.tool-generator';
3
3
  /**
4
4
  * Reserved tool name for the built-in `model-info` static tool.
@@ -32,6 +32,15 @@ export interface CreateModelInfoToolDeps {
32
32
  * manifest JSON.
33
33
  */
34
34
  readonly manifest: readonly McpManifestModelEntry[];
35
+ /**
36
+ * Optional enum value tables, keyed by enum name, sourced from the build-time manifest's `enums`
37
+ * block. When present, the value→label table for every enum referenced (by `enumRef`) on a
38
+ * returned model's fields is attached as a top-level `enums` section — but only when full field
39
+ * detail is returned, so the default compact modes stay small.
40
+ */
41
+ readonly enums?: {
42
+ readonly [name: string]: McpManifestEnum;
43
+ };
35
44
  }
36
45
  /**
37
46
  * Public shape of the `model-info` tool input. Every field is optional; the combination selects
@@ -112,8 +121,12 @@ export interface ModelInfoNotFound {
112
121
  * - `list`: a summary (or, with `fields: true`, full) list — used by `modelGroup` and `all`.
113
122
  * - `single`: full detail for one `model` string.
114
123
  * - `multiple`: full detail per match for a `model` array, with misses in `notFound`.
124
+ *
125
+ * The orthogonal `enums` section is attached only when full field detail is returned and the
126
+ * returned models reference at least one enum present in the manifest — the default compact modes
127
+ * (`groups`, summary `list`) never carry it.
115
128
  */
116
- export type ModelInfoToolOutput = {
129
+ export type ModelInfoToolOutput = ({
117
130
  readonly mode: 'groups';
118
131
  readonly groups: ReadonlyArray<ModelInfoGroupCount>;
119
132
  readonly totalModels: number;
@@ -129,6 +142,8 @@ export type ModelInfoToolOutput = {
129
142
  readonly mode: 'multiple';
130
143
  readonly models: ReadonlyArray<ModelInfoModelRow>;
131
144
  readonly notFound?: ReadonlyArray<ModelInfoNotFound>;
145
+ }) & {
146
+ readonly enums?: ReadonlyArray<McpManifestEnum>;
132
147
  };
133
148
  /**
134
149
  * Builds the built-in `model-info` MCP tool definition.
@@ -162,3 +177,37 @@ export declare function createModelInfoTool(deps: CreateModelInfoToolDeps): McpT
162
177
  * @__NO_SIDE_EFFECTS__
163
178
  */
164
179
  export declare function findModelEntry(query: string, manifest: ReadonlyArray<McpManifestModelEntry>): McpManifestModelEntry | undefined;
180
+ /**
181
+ * JSON-schema for one enum value→label table. Shared with the `enum-info` tool so both advertise the
182
+ * identical enum shape.
183
+ */
184
+ export declare const ENUM_TABLE_SCHEMA: {
185
+ readonly type: "object";
186
+ readonly required: readonly ["name", "values"];
187
+ readonly properties: {
188
+ readonly name: {
189
+ readonly type: "string";
190
+ };
191
+ readonly description: {
192
+ readonly type: "string";
193
+ };
194
+ readonly values: {
195
+ readonly type: "array";
196
+ readonly items: {
197
+ readonly type: "object";
198
+ readonly required: readonly ["name", "value"];
199
+ readonly properties: {
200
+ readonly name: {
201
+ readonly type: "string";
202
+ };
203
+ readonly value: {
204
+ readonly type: readonly ["string", "number"];
205
+ };
206
+ readonly description: {
207
+ readonly type: "string";
208
+ };
209
+ };
210
+ };
211
+ };
212
+ };
213
+ };
@@ -0,0 +1,101 @@
1
+ import { type FirestoreModelKey } from '@dereekb/firebase';
2
+ import { type ModelAccessMultiReadResult } from '@dereekb/firebase-server';
3
+ import { type McpToolDefinition } from '../mcp.tool-generator';
4
+ import { type RouteManifest, type RouteManifestModelEntry } from '../mcp.route-manifest';
5
+ import { type McpModelGetReadDocuments, type McpModelGetResolveIdentity } from './mcp.tool.model-get';
6
+ /**
7
+ * Reserved tool name for the built-in `url-models` static tool.
8
+ */
9
+ export declare const URL_MODELS_TOOL_NAME = "url-models";
10
+ /**
11
+ * Synthetic call type used in the tool's dispatch identity.
12
+ */
13
+ export declare const URL_MODELS_DISPATCH_CALL = "url-models";
14
+ /**
15
+ * Synthetic model type used in the tool's dispatch identity. The tool isn't
16
+ * bound to a real model (the `url` is its input), so we use the literal "route".
17
+ */
18
+ export declare const URL_MODELS_DISPATCH_MODEL_TYPE = "route";
19
+ /**
20
+ * Why a model binding could not be resolved into a concrete key.
21
+ */
22
+ export type UrlModelUnresolvedReason = 'missing-param' | 'subcollection-requires-key-template' | 'unknown-model-type' | 'auth-required';
23
+ /**
24
+ * One resolved model binding for a matched page.
25
+ */
26
+ export interface ResolvedRouteModel {
27
+ readonly modelType: string;
28
+ readonly kind: RouteManifestModelEntry['kind'];
29
+ readonly keyTemplate?: string;
30
+ readonly description?: string;
31
+ readonly from?: string;
32
+ /**
33
+ * The concrete FirestoreModelKey, when the binding resolved (`id`/`key` kinds).
34
+ */
35
+ readonly key?: FirestoreModelKey;
36
+ /**
37
+ * Present when the binding could not be turned into a key.
38
+ */
39
+ readonly unresolved?: {
40
+ readonly reason: UrlModelUnresolvedReason;
41
+ readonly message: string;
42
+ };
43
+ }
44
+ /**
45
+ * Documents loaded for one model type (when `load` is requested).
46
+ */
47
+ export interface UrlModelLoadedGroup {
48
+ readonly modelType: string;
49
+ readonly results: ModelAccessMultiReadResult['results'];
50
+ readonly errors: ModelAccessMultiReadResult['errors'];
51
+ }
52
+ /**
53
+ * Constructor dependencies for {@link createUrlModelsTool}.
54
+ */
55
+ export interface CreateUrlModelsToolDeps {
56
+ /**
57
+ * The pre-rendered route manifest used to match URLs to states.
58
+ */
59
+ readonly routeManifest: RouteManifest;
60
+ /**
61
+ * Reads a batch of model documents (shared with `model-get`).
62
+ */
63
+ readonly readDocuments: McpModelGetReadDocuments;
64
+ /**
65
+ * Resolves a model type's registered identity so `id` key templates can be
66
+ * promoted to `<collectionName>/<id>` (shared with `model-get`).
67
+ */
68
+ readonly resolveIdentity: McpModelGetResolveIdentity;
69
+ }
70
+ /**
71
+ * Shape of the `url-models` tool input.
72
+ */
73
+ export interface UrlModelsToolInput {
74
+ readonly url: string;
75
+ readonly models?: ReadonlyArray<string>;
76
+ readonly keysOnly?: boolean;
77
+ readonly load?: boolean;
78
+ /**
79
+ * Overrides the uid used to fill `{authUid}` placeholders when resolving model
80
+ * keys (defaults to the authenticated caller). Use to preview the models
81
+ * another user would see on a page. Does not affect the document-load path —
82
+ * `load` still reads via the calling user's permissions.
83
+ */
84
+ readonly currentUserUid?: string;
85
+ }
86
+ /**
87
+ * Builds the built-in `url-models` MCP tool definition.
88
+ *
89
+ * Matches a pasted app URL against the build-time route manifest and returns the
90
+ * Firestore models the page renders — model types plus concrete keys with the
91
+ * route params and `{authUid}` substituted. Optionally filtered to specific
92
+ * `models`, reduced to keys-only, or loaded via the same permission-checked read
93
+ * path as `model-get`.
94
+ *
95
+ * A URL that matches no state returns a structured `{ matched: null, candidates }`
96
+ * (not an error) so the caller can suggest near-misses.
97
+ *
98
+ * @param deps - The route manifest plus the shared read-documents / identity callbacks.
99
+ * @returns A statically-registered {@link McpToolDefinition}.
100
+ */
101
+ export declare function createUrlModelsTool(deps: CreateUrlModelsToolDeps): McpToolDefinition;
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/model",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.16.0",
6
- "@dereekb/date": "13.16.0",
7
- "@dereekb/firebase": "13.16.0",
8
- "@dereekb/firebase-server": "13.16.0",
9
- "@dereekb/model": "13.16.0",
10
- "@dereekb/nestjs": "13.16.0",
11
- "@dereekb/rxjs": "13.16.0",
12
- "@dereekb/util": "13.16.0",
5
+ "@dereekb/analytics": "13.18.0",
6
+ "@dereekb/date": "13.18.0",
7
+ "@dereekb/firebase": "13.18.0",
8
+ "@dereekb/firebase-server": "13.18.0",
9
+ "@dereekb/model": "13.18.0",
10
+ "@dereekb/nestjs": "13.18.0",
11
+ "@dereekb/rxjs": "13.18.0",
12
+ "@dereekb/util": "13.18.0",
13
13
  "@nestjs/common": "^11.1.19",
14
14
  "@nestjs/config": "^4.0.4",
15
15
  "archiver": "^7.0.1",
package/oidc/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/oidc",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.16.0",
6
- "@dereekb/date": "13.16.0",
7
- "@dereekb/firebase": "13.16.0",
8
- "@dereekb/firebase-server": "13.16.0",
9
- "@dereekb/model": "13.16.0",
10
- "@dereekb/nestjs": "13.16.0",
11
- "@dereekb/rxjs": "13.16.0",
12
- "@dereekb/util": "13.16.0",
13
- "@dereekb/zoho": "13.16.0",
5
+ "@dereekb/analytics": "13.18.0",
6
+ "@dereekb/date": "13.18.0",
7
+ "@dereekb/firebase": "13.18.0",
8
+ "@dereekb/firebase-server": "13.18.0",
9
+ "@dereekb/model": "13.18.0",
10
+ "@dereekb/nestjs": "13.18.0",
11
+ "@dereekb/rxjs": "13.18.0",
12
+ "@dereekb/util": "13.18.0",
13
+ "@dereekb/zoho": "13.18.0",
14
14
  "@nestjs/common": "^11.1.19",
15
15
  "@nestjs/config": "^4.0.4",
16
16
  "express": "^5.2.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "sideEffects": false,
5
5
  "exports": {
6
6
  "./test": {
@@ -57,15 +57,15 @@
57
57
  "types": "./src/index.d.ts",
58
58
  "peerDependencies": {
59
59
  "@cantoo/pdf-lib": "^2.6.5",
60
- "@dereekb/analytics": "13.16.0",
61
- "@dereekb/date": "13.16.0",
62
- "@dereekb/dbx-core": "13.16.0",
63
- "@dereekb/firebase": "13.16.0",
64
- "@dereekb/model": "13.16.0",
65
- "@dereekb/nestjs": "13.16.0",
66
- "@dereekb/rxjs": "13.16.0",
67
- "@dereekb/util": "13.16.0",
68
- "@dereekb/zoho": "13.16.0",
60
+ "@dereekb/analytics": "13.18.0",
61
+ "@dereekb/date": "13.18.0",
62
+ "@dereekb/dbx-core": "13.18.0",
63
+ "@dereekb/firebase": "13.18.0",
64
+ "@dereekb/model": "13.18.0",
65
+ "@dereekb/nestjs": "13.18.0",
66
+ "@dereekb/rxjs": "13.18.0",
67
+ "@dereekb/util": "13.18.0",
68
+ "@dereekb/zoho": "13.18.0",
69
69
  "@google-cloud/firestore": "^7.11.6",
70
70
  "@google-cloud/storage": "^7.19.0",
71
71
  "@modelcontextprotocol/sdk": "1.29.0",
@@ -43,6 +43,11 @@ export interface ModelAccessUseMultipleModelsFailureEntry {
43
43
  * permission-denied / not-found errors surface a real message + code instead of the generic
44
44
  * `"Unknown error"` fallback the inline mapping used previously.
45
45
  *
46
+ * When no real message survives, the fallback is derived from the resolved error `code` so the two
47
+ * distinct outcomes stay distinguishable — a not-found read no longer reads as "permission denied"
48
+ * (and vice-versa). Only when neither a message nor a recognizable code is present does it fall back
49
+ * to a generic message.
50
+ *
46
51
  * @param entry - A failed-key entry from the underlying multi-read.
47
52
  * @returns A `{ key, message, code? }` triple safe to return to API/MCP callers.
48
53
  */
package/test/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/test",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.16.0",
6
- "@dereekb/date": "13.16.0",
7
- "@dereekb/firebase": "13.16.0",
8
- "@dereekb/firebase-server": "13.16.0",
9
- "@dereekb/firebase-server/oidc": "13.16.0",
10
- "@dereekb/model": "13.16.0",
11
- "@dereekb/nestjs": "13.16.0",
12
- "@dereekb/rxjs": "13.16.0",
13
- "@dereekb/util": "13.16.0",
5
+ "@dereekb/analytics": "13.18.0",
6
+ "@dereekb/date": "13.18.0",
7
+ "@dereekb/firebase": "13.18.0",
8
+ "@dereekb/firebase-server": "13.18.0",
9
+ "@dereekb/firebase-server/oidc": "13.18.0",
10
+ "@dereekb/model": "13.18.0",
11
+ "@dereekb/nestjs": "13.18.0",
12
+ "@dereekb/rxjs": "13.18.0",
13
+ "@dereekb/util": "13.18.0",
14
14
  "@google-cloud/firestore": "^7.11.6",
15
15
  "@google-cloud/storage": "^7.19.0",
16
16
  "@nestjs/common": "^11.1.19",
@@ -23,7 +23,7 @@
23
23
  "supertest": "^7.2.2"
24
24
  },
25
25
  "devDependencies": {
26
- "@dereekb/nestjs": "13.16.0"
26
+ "@dereekb/nestjs": "13.18.0"
27
27
  },
28
28
  "exports": {
29
29
  "./package.json": "./package.json",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/twilio",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "peerDependencies": {
5
- "@dereekb/date": "13.16.0",
6
- "@dereekb/firebase": "13.16.0",
7
- "@dereekb/firebase-server": "13.16.0",
8
- "@dereekb/model": "13.16.0",
9
- "@dereekb/nestjs": "13.16.0",
10
- "@dereekb/rxjs": "13.16.0",
11
- "@dereekb/util": "13.16.0"
5
+ "@dereekb/date": "13.18.0",
6
+ "@dereekb/firebase": "13.18.0",
7
+ "@dereekb/firebase-server": "13.18.0",
8
+ "@dereekb/model": "13.18.0",
9
+ "@dereekb/nestjs": "13.18.0",
10
+ "@dereekb/rxjs": "13.18.0",
11
+ "@dereekb/util": "13.18.0"
12
12
  },
13
13
  "exports": {
14
14
  "./package.json": "./package.json",
package/zoho/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/zoho",
3
- "version": "13.16.0",
3
+ "version": "13.18.0",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.16.0",
6
- "@dereekb/date": "13.16.0",
7
- "@dereekb/model": "13.16.0",
8
- "@dereekb/nestjs": "13.16.0",
9
- "@dereekb/rxjs": "13.16.0",
10
- "@dereekb/firebase": "13.16.0",
11
- "@dereekb/util": "13.16.0",
12
- "@dereekb/zoho": "13.16.0"
5
+ "@dereekb/analytics": "13.18.0",
6
+ "@dereekb/date": "13.18.0",
7
+ "@dereekb/model": "13.18.0",
8
+ "@dereekb/nestjs": "13.18.0",
9
+ "@dereekb/rxjs": "13.18.0",
10
+ "@dereekb/firebase": "13.18.0",
11
+ "@dereekb/util": "13.18.0",
12
+ "@dereekb/zoho": "13.18.0"
13
13
  },
14
14
  "exports": {
15
15
  "./package.json": "./package.json",