@dereekb/firebase-server 13.6.17 → 13.7.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/index.cjs.js +2615 -951
- package/index.esm.js +2598 -932
- package/mailgun/package.json +9 -9
- package/model/package.json +9 -9
- package/model/src/lib/storagefile/storagefile.action.server.d.ts +1 -1
- package/oidc/index.cjs.js +245 -180
- package/oidc/index.esm.js +242 -178
- package/oidc/package.json +10 -10
- package/oidc/src/lib/middleware/oauth-auth.module.d.ts +18 -25
- package/package.json +11 -10
- package/src/lib/function/error.d.ts +11 -28
- package/src/lib/nest/app.d.ts +4 -45
- package/src/lib/nest/app.module.d.ts +4 -2
- package/src/lib/nest/auth/auth.util.d.ts +71 -5
- package/src/lib/nest/controller/index.d.ts +1 -0
- package/src/lib/nest/controller/model/index.d.ts +4 -0
- package/src/lib/nest/controller/model/model.api.controller.d.ts +93 -0
- package/src/lib/nest/controller/model/model.api.dispatch.d.ts +73 -0
- package/src/lib/nest/controller/model/model.api.get.service.d.ts +73 -0
- package/src/lib/nest/controller/model/model.api.module.d.ts +32 -0
- package/src/lib/nest/model/analytics.handler.d.ts +2 -0
- package/src/lib/nest/model/api.details.d.ts +53 -1
- package/src/lib/nest/model/call.model.function.d.ts +8 -5
- package/src/lib/nest/model/create.model.function.d.ts +1 -1
- package/src/lib/nest/model/crud.assert.function.d.ts +1 -1
- package/src/lib/nest/model/delete.model.function.d.ts +1 -1
- package/src/lib/nest/model/index.d.ts +1 -0
- package/src/lib/nest/model/query.model.function.d.ts +207 -0
- package/src/lib/nest/model/read.model.function.d.ts +1 -1
- package/src/lib/nest/model/update.model.function.d.ts +1 -1
- package/src/lib/nest/nest.provider.d.ts +19 -0
- package/test/index.cjs.js +1358 -398
- package/test/index.esm.js +1355 -400
- package/test/package.json +13 -11
- package/test/src/lib/firebase/firebase.test.d.ts +1 -1
- package/test/src/lib/index.d.ts +1 -0
- package/test/src/lib/oidc/index.d.ts +2 -0
- package/test/src/lib/oidc/oidc.test.fixture.d.ts +126 -0
- package/test/src/lib/oidc/oidc.test.flow.d.ts +43 -0
- package/zoho/package.json +9 -9
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type Maybe } from '@dereekb/util';
|
|
2
|
+
import { type FirestoreModelKey, type FirestoreModelType } from '@dereekb/firebase';
|
|
3
|
+
import { type INestApplicationContext } from '@nestjs/common';
|
|
4
|
+
import { ModelApiDispatchConfig } from './model.api.dispatch';
|
|
5
|
+
import { type FirebaseServerAuthData } from '../auth.context.server';
|
|
6
|
+
/**
|
|
7
|
+
* Maximum number of keys allowed in a multi-read request.
|
|
8
|
+
*/
|
|
9
|
+
export declare const MAX_MODEL_ACCESS_MULTI_READ_KEYS = 50;
|
|
10
|
+
/**
|
|
11
|
+
* Result of a single document access read.
|
|
12
|
+
*/
|
|
13
|
+
export interface ModelAccessReadResult {
|
|
14
|
+
readonly key: FirestoreModelKey;
|
|
15
|
+
readonly data: unknown;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Result of a multi-document access read.
|
|
19
|
+
*/
|
|
20
|
+
export interface ModelAccessMultiReadResult {
|
|
21
|
+
readonly results: ModelAccessReadResult[];
|
|
22
|
+
readonly errors: ModelAccessReadError[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Error for a single document in a multi-read request.
|
|
26
|
+
*/
|
|
27
|
+
export interface ModelAccessReadError {
|
|
28
|
+
readonly key: FirestoreModelKey;
|
|
29
|
+
readonly message: string;
|
|
30
|
+
readonly code?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Service for direct document reads using the `useModel()` permission-checking pattern.
|
|
34
|
+
*
|
|
35
|
+
* Unlike the dispatch service (which goes through callModel handlers), this service
|
|
36
|
+
* reads documents directly from Firestore via {@link AbstractFirebaseNestContext.useModel},
|
|
37
|
+
* enforcing `'read'` role permissions per document.
|
|
38
|
+
*/
|
|
39
|
+
export declare class ModelApiGetService {
|
|
40
|
+
private readonly _nestContext;
|
|
41
|
+
constructor(config: ModelApiDispatchConfig, nestApplication: INestApplicationContext);
|
|
42
|
+
/**
|
|
43
|
+
* Reads a single document by model type and key with permission checking.
|
|
44
|
+
*
|
|
45
|
+
* @param modelType - The Firestore model type string (e.g., 'profile', 'guestbook').
|
|
46
|
+
* @param key - The full Firestore model key (e.g., 'pr/abc123').
|
|
47
|
+
* @param auth - The authenticated user's auth data from the request.
|
|
48
|
+
* @returns The document key and data.
|
|
49
|
+
* @throws Permission or not-found errors from useModel.
|
|
50
|
+
*/
|
|
51
|
+
readDocument(modelType: FirestoreModelType, key: FirestoreModelKey, auth: Maybe<FirebaseServerAuthData>): Promise<ModelAccessReadResult>;
|
|
52
|
+
/**
|
|
53
|
+
* Reads multiple documents of the same model type with permission checking.
|
|
54
|
+
*
|
|
55
|
+
* Individual document errors (not-found, forbidden) are captured per-key
|
|
56
|
+
* and returned in the errors array rather than throwing.
|
|
57
|
+
*
|
|
58
|
+
* @param modelType - The Firestore model type string.
|
|
59
|
+
* @param keys - Array of Firestore model keys (max {@link MAX_MODEL_ACCESS_MULTI_READ_KEYS}).
|
|
60
|
+
* @param auth - The authenticated user's auth data from the request.
|
|
61
|
+
* @returns Results and errors for each requested key.
|
|
62
|
+
*/
|
|
63
|
+
readDocuments(modelType: FirestoreModelType, keys: FirestoreModelKey[], auth: Maybe<FirebaseServerAuthData>): Promise<ModelAccessMultiReadResult>;
|
|
64
|
+
/**
|
|
65
|
+
* Builds an {@link AuthDataRef} compatible with `useModel()` from the HTTP request auth.
|
|
66
|
+
*
|
|
67
|
+
* Uses the same synthetic auth pattern as {@link ModelApiDispatchService.dispatch}.
|
|
68
|
+
*
|
|
69
|
+
* @param auth - The Firebase server auth data from the HTTP request, or undefined for unauthenticated requests.
|
|
70
|
+
* @returns An object containing a synthetic {@link AuthData} for use with `useModel()`, or undefined auth.
|
|
71
|
+
*/
|
|
72
|
+
private _makeAuthRef;
|
|
73
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ModuleMetadata } from '@nestjs/common';
|
|
2
|
+
import { type ClassType } from '@dereekb/util';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for {@link modelApiModuleMetadata}.
|
|
5
|
+
*/
|
|
6
|
+
export interface ModelApiModuleMetadataConfig extends Pick<ModuleMetadata, 'imports' | 'exports' | 'providers'> {
|
|
7
|
+
/**
|
|
8
|
+
* Module that exports the required dependencies.
|
|
9
|
+
*
|
|
10
|
+
* Must provide {@link ModelApiDispatchConfig} so the dispatch service
|
|
11
|
+
* can access the callModel function and nest context factory.
|
|
12
|
+
*/
|
|
13
|
+
readonly dependencyModule: ClassType;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generates NestJS module metadata for the Model API controller.
|
|
17
|
+
*
|
|
18
|
+
* Follows the same pattern as {@link oidcModuleMetadata} — takes a dependency module
|
|
19
|
+
* that provides the required tokens, and returns a complete module metadata object.
|
|
20
|
+
*
|
|
21
|
+
* @param metadataConfig - Configuration including the dependency module.
|
|
22
|
+
* @returns NestJS module metadata with the Model API controller, dispatch service, and app context provider.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* @Module(modelApiModuleMetadata({
|
|
27
|
+
* dependencyModule: DemoModelApiDependencyModule
|
|
28
|
+
* }))
|
|
29
|
+
* export class DemoModelApiModule {}
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function modelApiModuleMetadata(metadataConfig: ModelApiModuleMetadataConfig): ModuleMetadata;
|
|
@@ -71,6 +71,8 @@ export declare const ON_CALL_MODEL_ANALYTICS_SERVICE: InjectionToken<OnCallModel
|
|
|
71
71
|
*
|
|
72
72
|
* Used as the default fallback by {@link OnCallModelAnalyticsResolver} when no analytics
|
|
73
73
|
* service is registered.
|
|
74
|
+
*
|
|
75
|
+
* @returns An {@link OnCallModelAnalyticsService} that discards all analytics events.
|
|
74
76
|
*/
|
|
75
77
|
export declare function noopOnCallModelAnalyticsService(): OnCallModelAnalyticsService;
|
|
76
78
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
-
import { type OnCallFunctionType, type FirestoreModelType, type ModelFirebaseCrudFunctionSpecifier } from '@dereekb/firebase';
|
|
2
|
+
import { type OnCallFunctionType, type OnCallTypedModelParams, type FirestoreModelType, type ModelFirebaseCrudFunctionSpecifier } from '@dereekb/firebase';
|
|
3
3
|
import { type OnCallModelFunctionAnalyticsDetails } from './analytics.details';
|
|
4
4
|
/**
|
|
5
5
|
* Reference to a type that can produce a JSON Schema representation.
|
|
@@ -11,10 +11,41 @@ import { type OnCallModelFunctionAnalyticsDetails } from './analytics.details';
|
|
|
11
11
|
export interface JsonSchemaRef {
|
|
12
12
|
toJsonSchema(options?: object): object;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* A natural language summary of an MCP tool operation result.
|
|
16
|
+
*/
|
|
17
|
+
export type McpToolResponseSummary = string;
|
|
18
|
+
/**
|
|
19
|
+
* Minimal structural type for MCP tool response content.
|
|
20
|
+
*
|
|
21
|
+
* Mirrors the shape of MCP SDK's CallToolResult without importing the SDK directly,
|
|
22
|
+
* so api.details.ts remains dependency-free.
|
|
23
|
+
*/
|
|
24
|
+
export interface McpToolResponseContent {
|
|
25
|
+
readonly content: ReadonlyArray<McpToolResponseContentBlock>;
|
|
26
|
+
readonly structuredContent?: unknown;
|
|
27
|
+
readonly isError?: boolean;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A single content block in an MCP tool response.
|
|
31
|
+
*/
|
|
32
|
+
export interface McpToolResponseContentBlock {
|
|
33
|
+
readonly type: string;
|
|
34
|
+
readonly text?: string;
|
|
35
|
+
readonly mimeType?: string;
|
|
36
|
+
readonly data?: string;
|
|
37
|
+
}
|
|
14
38
|
/**
|
|
15
39
|
* MCP-specific customization for a model function.
|
|
16
40
|
*
|
|
17
41
|
* When omitted, defaults are auto-generated from the handler's position in the call model tree.
|
|
42
|
+
*
|
|
43
|
+
* Response formatting uses a tiered system:
|
|
44
|
+
* - **Tier 1 (default)**: Auto-generated summary from the result shape. No config needed.
|
|
45
|
+
* - **Tier 2**: Provide {@link summarizeResponse} to return a natural language string. The framework wraps it into MCP content + structuredContent automatically.
|
|
46
|
+
* - **Tier 3**: Provide {@link formatResponse} for complete control over the MCP response content blocks.
|
|
47
|
+
*
|
|
48
|
+
* Resolution order: formatResponse > summarizeResponse > auto-generated default.
|
|
18
49
|
*/
|
|
19
50
|
export interface OnCallModelFunctionMcpDetails {
|
|
20
51
|
/**
|
|
@@ -25,6 +56,27 @@ export interface OnCallModelFunctionMcpDetails {
|
|
|
25
56
|
* Custom tool name override.
|
|
26
57
|
*/
|
|
27
58
|
readonly name?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Tier 2 response formatter: returns a natural language summary string.
|
|
61
|
+
*
|
|
62
|
+
* The framework wraps the string into a text content block and attaches the raw result
|
|
63
|
+
* as structuredContent automatically.
|
|
64
|
+
*
|
|
65
|
+
* @param result - The handler's return value.
|
|
66
|
+
* @param params - The OnCallTypedModelParams that were dispatched.
|
|
67
|
+
* @returns A human-readable summary of the operation result.
|
|
68
|
+
*/
|
|
69
|
+
readonly summarizeResponse?: (result: unknown, params: OnCallTypedModelParams) => McpToolResponseSummary;
|
|
70
|
+
/**
|
|
71
|
+
* Tier 3 response formatter: complete control over the MCP tool response.
|
|
72
|
+
*
|
|
73
|
+
* When provided, takes precedence over {@link summarizeResponse} and the auto-generated default.
|
|
74
|
+
*
|
|
75
|
+
* @param result - The handler's return value.
|
|
76
|
+
* @param params - The OnCallTypedModelParams that were dispatched.
|
|
77
|
+
* @returns The full MCP tool response content.
|
|
78
|
+
*/
|
|
79
|
+
readonly formatResponse?: (result: unknown, params: OnCallTypedModelParams) => McpToolResponseContent;
|
|
28
80
|
}
|
|
29
81
|
/**
|
|
30
82
|
* API details metadata for a single model call handler function.
|
|
@@ -5,13 +5,13 @@ import { type AssertModelCrudRequestFunctionContextCrudType, type AssertModelCru
|
|
|
5
5
|
import { type NestContextCallableRequest } from '../function/nest';
|
|
6
6
|
import { type OnCallApiDetailsRef } from './api.details';
|
|
7
7
|
/**
|
|
8
|
-
* Maps
|
|
8
|
+
* Maps call type strings (e.g., 'create', 'read', 'update', 'delete', 'query') to their
|
|
9
9
|
* corresponding handler functions.
|
|
10
10
|
*
|
|
11
|
-
* Used by {@link onCallModel} to dispatch incoming requests to the correct
|
|
11
|
+
* Used by {@link onCallModel} to dispatch incoming requests to the correct handler.
|
|
12
12
|
*/
|
|
13
13
|
export type OnCallModelMap = {
|
|
14
|
-
readonly [call: OnCallFunctionType]: OnCallWithNestContext<any, OnCallTypedModelParams
|
|
14
|
+
readonly [call: OnCallFunctionType]: OnCallWithNestContext<any, OnCallTypedModelParams<any>>;
|
|
15
15
|
};
|
|
16
16
|
/**
|
|
17
17
|
* Configuration for {@link onCallModel}.
|
|
@@ -51,7 +51,8 @@ export interface OnCallModelConfig {
|
|
|
51
51
|
* create: onCallCreateModel({ profile: createProfile, guestbook: createGuestbook }),
|
|
52
52
|
* read: onCallReadModel({ profile: readProfile }),
|
|
53
53
|
* update: onCallUpdateModel({ profile: updateProfile }),
|
|
54
|
-
* delete: onCallDeleteModel({ guestbook: deleteGuestbook })
|
|
54
|
+
* delete: onCallDeleteModel({ guestbook: deleteGuestbook }),
|
|
55
|
+
* query: onCallQueryModel({ profile: queryProfiles })
|
|
55
56
|
* });
|
|
56
57
|
* ```
|
|
57
58
|
*/
|
|
@@ -95,7 +96,9 @@ export interface OnCallWithCallTypeModelConfig<N> {
|
|
|
95
96
|
*/
|
|
96
97
|
readonly callType: string;
|
|
97
98
|
/**
|
|
98
|
-
* The
|
|
99
|
+
* The operation category used by {@link AssertModelCrudRequestFunction}.
|
|
100
|
+
*
|
|
101
|
+
* One of: 'call', 'create', 'read', 'update', 'delete', 'query'.
|
|
99
102
|
*/
|
|
100
103
|
readonly crudType: AssertModelCrudRequestFunctionContextCrudType;
|
|
101
104
|
/**
|
|
@@ -89,6 +89,6 @@ export declare function onCallCreateModel<N>(map: OnCallCreateModelMap<N>, confi
|
|
|
89
89
|
* Creates a bad-request error indicating the requested model type is not valid for creation.
|
|
90
90
|
*
|
|
91
91
|
* @param modelType - The unrecognized model type string.
|
|
92
|
-
* @returns A bad-request error with
|
|
92
|
+
* @returns A bad-request error with {@link UNKNOWN_MODEL_TYPE_ERROR_CODE} code.
|
|
93
93
|
*/
|
|
94
94
|
export declare function createModelUnknownModelTypeError(modelType: FirestoreModelType): import("firebase-functions/https").HttpsError;
|
|
@@ -7,7 +7,7 @@ import { type OnCallFunctionType, type FirestoreModelType } from '@dereekb/fireb
|
|
|
7
7
|
* Used by {@link AssertModelCrudRequestFunction} to let assertions branch on operation type,
|
|
8
8
|
* enabling cross-cutting rules like "block all deletes for archived models."
|
|
9
9
|
*/
|
|
10
|
-
export type AssertModelCrudRequestFunctionContextCrudType = 'call' | 'create' | 'read' | 'update' | 'delete';
|
|
10
|
+
export type AssertModelCrudRequestFunctionContextCrudType = 'call' | 'create' | 'read' | 'update' | 'delete' | 'query';
|
|
11
11
|
/**
|
|
12
12
|
* Context passed to a {@link AssertModelCrudRequestFunction} before a CRUD handler executes.
|
|
13
13
|
*
|
|
@@ -78,6 +78,6 @@ export declare function onCallDeleteModel<N>(map: OnCallDeleteModelMap<N>, confi
|
|
|
78
78
|
* Creates a bad-request error indicating the requested model type is not valid for deletion.
|
|
79
79
|
*
|
|
80
80
|
* @param modelType - The unrecognized model type string.
|
|
81
|
-
* @returns A bad-request error with
|
|
81
|
+
* @returns A bad-request error with {@link UNKNOWN_MODEL_TYPE_ERROR_CODE} code.
|
|
82
82
|
*/
|
|
83
83
|
export declare function deleteModelUnknownModelTypeError(modelType: FirestoreModelType): import("firebase-functions/https").HttpsError;
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { type Maybe, type PromiseOrValue } from '@dereekb/util';
|
|
2
|
+
import { type FirestoreModelType, type FirestoreModelIdentity, type FirestoreModelTypes, type OnCallQueryModelParams, type OnCallQueryModelRequestParams, type OnCallQueryModelResult, type ModelFirebaseCrudFunctionSpecifierRef, type FirestoreModelKey, type FirestoreCollectionLike, type FirestoreQueryConstraint, type DocumentSnapshot, type QueryDocumentSnapshot } from '@dereekb/firebase';
|
|
3
|
+
import { type OnCallWithAuthAwareNestRequireAuthRef, type OnCallWithNestContext } from '../function/call';
|
|
4
|
+
import { type NestContextCallableRequestWithAuth, type NestContextCallableRequestWithOptionalAuth } from '../function/nest';
|
|
5
|
+
import { type AssertModelCrudRequestFunction } from './crud.assert.function';
|
|
6
|
+
/**
|
|
7
|
+
* Request type for model query handlers that require authentication.
|
|
8
|
+
*
|
|
9
|
+
* @typeParam N - The NestJS context type.
|
|
10
|
+
* @typeParam I - The input data type for the query operation. Must extend {@link OnCallQueryModelRequestParams}.
|
|
11
|
+
*/
|
|
12
|
+
export type OnCallQueryModelRequest<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams> = NestContextCallableRequestWithAuth<N, I> & ModelFirebaseCrudFunctionSpecifierRef;
|
|
13
|
+
/**
|
|
14
|
+
* A model query handler function that requires an authenticated caller.
|
|
15
|
+
*/
|
|
16
|
+
export type OnCallQueryModelFunctionWithAuth<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams, O = unknown> = ((request: OnCallQueryModelRequest<N, I>) => PromiseOrValue<O>) & {
|
|
17
|
+
readonly _requiresAuth?: true;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Request type for model query handlers that allow unauthenticated callers.
|
|
21
|
+
*/
|
|
22
|
+
export type OnCallQueryModelRequestWithOptionalAuth<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams> = NestContextCallableRequestWithOptionalAuth<N, I> & ModelFirebaseCrudFunctionSpecifierRef;
|
|
23
|
+
/**
|
|
24
|
+
* A model query handler function that does not require authentication.
|
|
25
|
+
*
|
|
26
|
+
* Useful for public-facing query endpoints such as listing public content.
|
|
27
|
+
*/
|
|
28
|
+
export type OnCallQueryModelFunctionWithOptionalAuth<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams, O = unknown> = ((request: OnCallQueryModelRequestWithOptionalAuth<N, I>) => PromiseOrValue<O>) & {
|
|
29
|
+
readonly _requireAuth: false;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Standard model query handler requiring auth (the common case).
|
|
33
|
+
*/
|
|
34
|
+
export type OnCallQueryModelFunction<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams, O = unknown> = OnCallQueryModelFunctionWithAuth<N, I, O> & OnCallWithAuthAwareNestRequireAuthRef;
|
|
35
|
+
/**
|
|
36
|
+
* Union of auth-required and optional-auth query handlers.
|
|
37
|
+
*/
|
|
38
|
+
export type OnCallQueryModelFunctionAuthAware<N, I extends OnCallQueryModelRequestParams = OnCallQueryModelRequestParams, O = unknown> = OnCallQueryModelFunction<N, I, O> | OnCallQueryModelFunctionWithOptionalAuth<N, I, O>;
|
|
39
|
+
/**
|
|
40
|
+
* Maps Firestore model type strings to their query handler functions.
|
|
41
|
+
*
|
|
42
|
+
* Pass this map to {@link onCallQueryModel} to register all model types
|
|
43
|
+
* that support querying through the call model system.
|
|
44
|
+
*
|
|
45
|
+
* @typeParam N - The NestJS context type.
|
|
46
|
+
* @typeParam T - The Firestore model identity constraining valid model type keys.
|
|
47
|
+
*/
|
|
48
|
+
export type OnCallQueryModelMap<N, T extends FirestoreModelIdentity = FirestoreModelIdentity> = {
|
|
49
|
+
readonly [K in FirestoreModelTypes<T>]?: OnCallQueryModelFunctionAuthAware<N, any, any>;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Configuration for {@link onCallQueryModel}.
|
|
53
|
+
*/
|
|
54
|
+
export interface OnCallQueryModelConfig<N> {
|
|
55
|
+
/**
|
|
56
|
+
* Optional assertion run before the query handler; throw to reject.
|
|
57
|
+
*/
|
|
58
|
+
readonly preAssert?: AssertModelCrudRequestFunction<N, OnCallQueryModelParams>;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Factory that creates a callable function handling model queries for multiple model types.
|
|
62
|
+
*
|
|
63
|
+
* Dispatches to the correct handler based on the `modelType` field in the request,
|
|
64
|
+
* enforces auth requirements per handler, and aggregates API details for MCP introspection.
|
|
65
|
+
*
|
|
66
|
+
* Query handlers receive filter/pagination params in the request data and should return
|
|
67
|
+
* an {@link OnCallQueryModelResult} with paginated results. Use {@link executeOnCallQuery}
|
|
68
|
+
* within handlers to handle cursor pagination automatically.
|
|
69
|
+
*
|
|
70
|
+
* @param map - Maps model type strings to their query handler functions.
|
|
71
|
+
* @param config - Optional configuration including a pre-assertion hook.
|
|
72
|
+
* @returns A callable function for the 'query' call type.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* const queryHandler = onCallQueryModel<DemoNestContext>({
|
|
77
|
+
* profile: queryProfiles,
|
|
78
|
+
* guestbook: queryGuestbooks
|
|
79
|
+
* });
|
|
80
|
+
*
|
|
81
|
+
* // Register as the 5th call type in onCallModel:
|
|
82
|
+
* const callModel = onCallModel({
|
|
83
|
+
* create: onCallCreateModel({ ... }),
|
|
84
|
+
* read: onCallReadModel({ ... }),
|
|
85
|
+
* update: onCallUpdateModel({ ... }),
|
|
86
|
+
* delete: onCallDeleteModel({ ... }),
|
|
87
|
+
* query: queryHandler
|
|
88
|
+
* });
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function onCallQueryModel<N>(map: OnCallQueryModelMap<N>, config?: OnCallQueryModelConfig<N>): OnCallWithNestContext<N, OnCallQueryModelParams, unknown>;
|
|
92
|
+
/**
|
|
93
|
+
* Creates a bad-request error indicating the requested model type is not valid for querying.
|
|
94
|
+
*
|
|
95
|
+
* @param modelType - The unrecognized model type string.
|
|
96
|
+
* @returns A bad-request error with {@link UNKNOWN_MODEL_TYPE_ERROR_CODE} code.
|
|
97
|
+
*/
|
|
98
|
+
export declare function queryModelUnknownModelTypeError(modelType: FirestoreModelType): import("firebase-functions/https").HttpsError;
|
|
99
|
+
/**
|
|
100
|
+
* Creates a bad-request error indicating the cursor document key is invalid or inaccessible.
|
|
101
|
+
*
|
|
102
|
+
* @param cursorDocumentKey - The cursor document key that failed to resolve.
|
|
103
|
+
* @returns A bad-request error with {@link BAD_DOCUMENT_QUERY_CURSOR_ERROR_CODE} code.
|
|
104
|
+
*/
|
|
105
|
+
export declare function queryModelBadCursorError(cursorDocumentKey: Maybe<FirestoreModelKey>): import("firebase-functions/https").HttpsError;
|
|
106
|
+
/**
|
|
107
|
+
* Configuration for {@link executeOnCallQuery}.
|
|
108
|
+
*
|
|
109
|
+
* @typeParam T - The Firestore document data type.
|
|
110
|
+
* @typeParam R - The mapped result type for each document. Defaults to T.
|
|
111
|
+
*/
|
|
112
|
+
export interface ExecuteOnCallQueryConfig<T, R = T> {
|
|
113
|
+
/**
|
|
114
|
+
* The query request params containing limit and cursorDocumentKey.
|
|
115
|
+
*/
|
|
116
|
+
readonly params: OnCallQueryModelRequestParams;
|
|
117
|
+
/**
|
|
118
|
+
* The Firestore collection to query against.
|
|
119
|
+
*
|
|
120
|
+
* Used for building queries (via {@link FirestoreQueryFactory}).
|
|
121
|
+
*/
|
|
122
|
+
readonly collection: FirestoreCollectionLike<T>;
|
|
123
|
+
/**
|
|
124
|
+
* Loads and permission-checks the cursor document when {@link OnCallQueryModelRequestParams.cursorDocumentKey} is provided.
|
|
125
|
+
*
|
|
126
|
+
* This function must verify that the caller has read access to the cursor document.
|
|
127
|
+
* Typically implemented using `nest.useModel()` which enforces permission checking.
|
|
128
|
+
* Must return the document's snapshot for use with `startAfter`.
|
|
129
|
+
*
|
|
130
|
+
* If the cursor document does not exist or the caller lacks permission, this function
|
|
131
|
+
* should throw an appropriate error (e.g., forbidden or not-found).
|
|
132
|
+
*
|
|
133
|
+
* @param cursorDocumentKey - The Firestore model key of the cursor document.
|
|
134
|
+
* @returns A promise resolving to the cursor document's snapshot.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* loadCursorDocument: async (key) => {
|
|
139
|
+
* const doc = await nest.useModel('guestbook', {
|
|
140
|
+
* request,
|
|
141
|
+
* key,
|
|
142
|
+
* roles: 'read',
|
|
143
|
+
* use: (x) => x.document
|
|
144
|
+
* });
|
|
145
|
+
* return doc.accessor.get();
|
|
146
|
+
* }
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
readonly loadCursorDocument: (cursorDocumentKey: FirestoreModelKey) => PromiseOrValue<DocumentSnapshot<T>>;
|
|
150
|
+
/**
|
|
151
|
+
* Builds query constraints to apply to the query.
|
|
152
|
+
*
|
|
153
|
+
* Return where/orderBy constraints here. Do NOT add limit or startAfter —
|
|
154
|
+
* those are managed by {@link executeOnCallQuery} automatically.
|
|
155
|
+
*
|
|
156
|
+
* @returns Array of query constraints to apply. May be async if constraints depend on external data.
|
|
157
|
+
*/
|
|
158
|
+
readonly buildConstraints: () => PromiseOrValue<FirestoreQueryConstraint[]>;
|
|
159
|
+
/**
|
|
160
|
+
* Optional maximum items per page override. Defaults to {@link MAX_ON_CALL_QUERY_MODEL_LIMIT}.
|
|
161
|
+
*
|
|
162
|
+
* The effective limit is: `min(params.limit ?? DEFAULT, maxLimit)`.
|
|
163
|
+
*/
|
|
164
|
+
readonly maxLimit?: number;
|
|
165
|
+
/**
|
|
166
|
+
* Optional transform applied to each document snapshot's data before returning.
|
|
167
|
+
*
|
|
168
|
+
* Defaults to `snapshot.data()`.
|
|
169
|
+
*/
|
|
170
|
+
readonly mapResult?: (snapshot: QueryDocumentSnapshot<T>) => R;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Executes a paginated query using cursor-based pagination.
|
|
174
|
+
*
|
|
175
|
+
* Handles the mechanics of:
|
|
176
|
+
* - Clamping the page limit to the configured maximum
|
|
177
|
+
* - Resolving the cursor document key to a snapshot for `startAfter`
|
|
178
|
+
* - Fetching one extra document to detect whether more results exist
|
|
179
|
+
* - Building the {@link OnCallQueryModelResult} with cursorDocumentKey and hasMore
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```typescript
|
|
183
|
+
* export const queryGuestbooks: DemoQueryModelFunction<QueryGuestbooksParams, OnCallQueryModelResult<Guestbook>> = async (request) => {
|
|
184
|
+
* const { nest, data } = request;
|
|
185
|
+
* return executeOnCallQuery({
|
|
186
|
+
* params: data,
|
|
187
|
+
* collection: nest.demoFirestoreCollections.guestbookCollection,
|
|
188
|
+
* loadCursorDocument: async (key) => {
|
|
189
|
+
* const doc = await nest.useModel('guestbook', { request, key, roles: 'read', use: (x) => x.document });
|
|
190
|
+
* return doc.accessor.get();
|
|
191
|
+
* },
|
|
192
|
+
* buildConstraints: () => {
|
|
193
|
+
* const constraints: FirestoreQueryConstraint[] = [];
|
|
194
|
+
* if (data.published != null) {
|
|
195
|
+
* constraints.push(where('published', '==', data.published));
|
|
196
|
+
* }
|
|
197
|
+
* constraints.push(orderBy('name', 'asc'));
|
|
198
|
+
* return constraints;
|
|
199
|
+
* }
|
|
200
|
+
* });
|
|
201
|
+
* };
|
|
202
|
+
* ```
|
|
203
|
+
*
|
|
204
|
+
* @param config - Query configuration including collection, constraints, and pagination params.
|
|
205
|
+
* @returns Paginated query result with cursor for the next page.
|
|
206
|
+
*/
|
|
207
|
+
export declare function executeOnCallQuery<T, R = T>(config: ExecuteOnCallQueryConfig<T, R>): Promise<OnCallQueryModelResult<R>>;
|
|
@@ -80,6 +80,6 @@ export declare function onCallReadModel<N>(map: OnCallReadModelMap<N>, config?:
|
|
|
80
80
|
* Creates a bad-request error indicating the requested model type is not valid for reading.
|
|
81
81
|
*
|
|
82
82
|
* @param modelType - The unrecognized model type string.
|
|
83
|
-
* @returns A bad-request error with
|
|
83
|
+
* @returns A bad-request error with {@link UNKNOWN_MODEL_TYPE_ERROR_CODE} code.
|
|
84
84
|
*/
|
|
85
85
|
export declare function readModelUnknownModelTypeError(modelType: FirestoreModelType): import("firebase-functions/https").HttpsError;
|
|
@@ -81,6 +81,6 @@ export declare function onCallUpdateModel<N>(map: OnCallUpdateModelMap<N>, confi
|
|
|
81
81
|
* Creates a bad-request error indicating the requested model type is not valid for updating.
|
|
82
82
|
*
|
|
83
83
|
* @param modelType - The unrecognized model type string.
|
|
84
|
-
* @returns A bad-request error with
|
|
84
|
+
* @returns A bad-request error with {@link UNKNOWN_MODEL_TYPE_ERROR_CODE} code.
|
|
85
85
|
*/
|
|
86
86
|
export declare function updateModelUnknownModelTypeError(modelType: FirestoreModelType): import("firebase-functions/https").HttpsError;
|
|
@@ -87,6 +87,20 @@ export declare abstract class AbstractFirebaseNestContext<A, Y extends FirebaseM
|
|
|
87
87
|
* @returns An in-context models service scoped to the given auth context.
|
|
88
88
|
*/
|
|
89
89
|
model(context: AuthDataRef, buildFn?: BuildFunction<FirebaseAppModelContext<A>>): InContextFirebaseModelsService<Y>;
|
|
90
|
+
/**
|
|
91
|
+
* Loads a model document by key, checks permissions against the requested roles,
|
|
92
|
+
* and optionally transforms the result via a `use` function.
|
|
93
|
+
*
|
|
94
|
+
* When called without a `use` function, returns the {@link ContextGrantedModelRolesReader}
|
|
95
|
+
* which provides access to the document and its granted roles.
|
|
96
|
+
*
|
|
97
|
+
* @throws Throws {@link nestFirebaseDoesNotExistError} if the document does not exist.
|
|
98
|
+
* @throws Throws {@link nestFirebaseForbiddenPermissionError} if the caller lacks the requested roles.
|
|
99
|
+
*
|
|
100
|
+
* @param type - The model type string (e.g., 'profile', 'guestbook').
|
|
101
|
+
* @param select - Selection params including key, roles, and optional use function.
|
|
102
|
+
* @returns The result of the `use` function, or the roles reader if no `use` function is provided.
|
|
103
|
+
*/
|
|
90
104
|
useModel<T extends FirebaseModelsServiceTypes<Y>, O>(type: T, select: UseModelInput<FirebaseAppModelContext<A>, Y, T, O>): Promise<O>;
|
|
91
105
|
useModel<T extends FirebaseModelsServiceTypes<Y>>(type: T, select: UseModelInputForRolesReader<FirebaseAppModelContext<A>, Y, T>): Promise<FirebaseModelsServiceSelectionResultRolesReader<Y, T>>;
|
|
92
106
|
/**
|
|
@@ -95,6 +109,11 @@ export declare abstract class AbstractFirebaseNestContext<A, Y extends FirebaseM
|
|
|
95
109
|
* Uses {@link performAsyncTasks} internally. The `use` function receives the array of
|
|
96
110
|
* successful {@link ContextGrantedModelRolesReader} values and an array of failed items.
|
|
97
111
|
*
|
|
112
|
+
* Individual documents that do not exist throw {@link nestFirebaseDoesNotExistError},
|
|
113
|
+
* and documents where the caller lacks the requested roles throw
|
|
114
|
+
* {@link nestFirebaseForbiddenPermissionError}. These errors are captured per-key
|
|
115
|
+
* and passed to the `use` function via the failure array (unless `throwOnFirstError` is true).
|
|
116
|
+
*
|
|
98
117
|
* @param type - the model type to load
|
|
99
118
|
* @param select - selection params including keys array, roles, and use function
|
|
100
119
|
* @returns the result of the use function
|