@dereekb/firebase-server 13.1.0 → 13.2.1
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 +477 -24
- package/index.cjs.js.map +1 -1
- package/index.esm.js +468 -26
- package/index.esm.js.map +1 -1
- package/mailgun/package.json +8 -8
- package/model/package.json +8 -8
- package/package.json +9 -9
- package/src/lib/auth/auth.service.d.ts +370 -85
- package/src/lib/firestore/index.d.ts +1 -0
- package/src/lib/firestore/snapshot/index.d.ts +1 -0
- package/src/lib/firestore/snapshot/snapshot.field.d.ts +80 -0
- package/src/lib/nest/model/api.details.d.ts +249 -0
- package/src/lib/nest/model/call.model.function.d.ts +3 -2
- package/src/lib/nest/model/index.d.ts +1 -0
- package/src/lib/nest/model/specifier.function.d.ts +2 -1
- package/test/package.json +8 -8
- package/zoho/package.json +8 -8
package/index.esm.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE, FIREBASE_AUTH_USER_NOT_FOUND_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY, FirestoreDocumentContextType, streamFromOnSnapshot, makeFirestoreQueryConstraintFunctionsDriver, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, firestoreContextFactory, setIdAndKeyFromKeyIdRefOnDocumentData, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER, MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT, storageListFilesResultFactory, assertStorageUploadOptionsStringFormat, firebaseStorageContextFactory, inContextFirebaseModelsServiceFactory, useFirebaseModelsService } from '@dereekb/firebase';
|
|
1
|
+
import { DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE, FIREBASE_AUTH_USER_NOT_FOUND_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY, FirestoreDocumentContextType, streamFromOnSnapshot, makeFirestoreQueryConstraintFunctionsDriver, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, firestoreContextFactory, firestoreField, optionalFirestoreField, setIdAndKeyFromKeyIdRefOnDocumentData, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER, MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT, storageListFilesResultFactory, assertStorageUploadOptionsStringFormat, firebaseStorageContextFactory, inContextFirebaseModelsServiceFactory, useFirebaseModelsService } from '@dereekb/firebase';
|
|
2
2
|
import { partialServerError, isServerError, randomNumberFactory, cachedGetter, AUTH_ADMIN_ROLE, AUTH_TOS_SIGNED_ROLE, forEachKeyValue, KeyValueTypleValueFilter, filterNullAndUndefinedValues, asSet, filterUndefinedValues, isThrottled, mapObjectMap, batch, asArray, containsAllValues, serverError, mergeObjects, cronExpressionRepeatingEveryNMinutes, mapIdentityFunction, objectToMap, slashPathName, SLASH_PATH_SEPARATOR, toRelativeSlashPathStartType, fixMultiSlashesInSlashPath, objectHasNoKeys, makeGetter, asGetter, pushItemOrArrayItemsIntoArray, build } from '@dereekb/util';
|
|
3
3
|
import { HttpsError } from 'firebase-functions/https';
|
|
4
4
|
import { hoursToMs, toISODateString } from '@dereekb/date';
|
|
5
5
|
import { BaseError } from 'make-error';
|
|
6
6
|
import { from } from 'rxjs';
|
|
7
7
|
import { FieldValue, FieldPath } from '@google-cloud/firestore';
|
|
8
|
+
import { randomBytes, createCipheriv, createDecipheriv } from 'crypto';
|
|
8
9
|
import { Module, Injectable, Optional, Inject, Logger, ForbiddenException, createParamDecorator } from '@nestjs/common';
|
|
9
10
|
import { mergeModuleMetadata, ServerEnvironmentService, DEFAULT_BASE_WEBHOOK_PATH, DEFAULT_WEBHOOK_MIDDLEWARE_ROUTE_INFO, isTestNodeEnv, injectionTokensFromProviders, serverEnvTokenProvider } from '@dereekb/nestjs';
|
|
10
11
|
import { https, scheduler } from 'firebase-functions/v2';
|
|
@@ -269,7 +270,34 @@ class FirebaseServerAuthNewUserSendSetupDetailsSendOnceError extends BaseError {
|
|
|
269
270
|
}
|
|
270
271
|
}
|
|
271
272
|
|
|
272
|
-
|
|
273
|
+
/**
|
|
274
|
+
* Generates a random 6-digit number for use as a temporary password or reset token.
|
|
275
|
+
*
|
|
276
|
+
* Used internally by {@link AbstractFirebaseServerAuthUserContext.beginResetPassword} and
|
|
277
|
+
* {@link AbstractFirebaseServerNewUserService.generateRandomSetupPassword} for one-time codes.
|
|
278
|
+
*
|
|
279
|
+
* @example
|
|
280
|
+
* ```typescript
|
|
281
|
+
* const pin = DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR(); // e.g. 482910
|
|
282
|
+
* ```
|
|
283
|
+
*/
|
|
284
|
+
const DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR = randomNumberFactory({ min: 100000, max: 1000000, round: 'floor' });
|
|
285
|
+
/**
|
|
286
|
+
* Base implementation of {@link FirebaseServerAuthUserContext} that manages a single user's
|
|
287
|
+
* auth state (record, claims, roles, password) through the Firebase Admin Auth API.
|
|
288
|
+
*
|
|
289
|
+
* Caches the user record on first load and resets the cache automatically when claims are modified
|
|
290
|
+
* via {@link setClaims}. Subclass this to bind it to a specific {@link FirebaseServerAuthService} type.
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```typescript
|
|
294
|
+
* export class MyAuthUserContext extends AbstractFirebaseServerAuthUserContext<MyAuthService> {}
|
|
295
|
+
*
|
|
296
|
+
* const ctx = new MyAuthUserContext(authService, 'some-uid');
|
|
297
|
+
* const roles = await ctx.loadRoles();
|
|
298
|
+
* await ctx.addRoles(AUTH_ADMIN_ROLE);
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
273
301
|
class AbstractFirebaseServerAuthUserContext {
|
|
274
302
|
_service;
|
|
275
303
|
_uid;
|
|
@@ -293,6 +321,9 @@ class AbstractFirebaseServerAuthUserContext {
|
|
|
293
321
|
loadDetails() {
|
|
294
322
|
return this.loadRecord().then((record) => this.service.authDetailsForRecord(record));
|
|
295
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Generates a random numeric string for use as a temporary reset password.
|
|
326
|
+
*/
|
|
296
327
|
_generateResetPasswordKey() {
|
|
297
328
|
return String(DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR());
|
|
298
329
|
}
|
|
@@ -317,9 +348,6 @@ class AbstractFirebaseServerAuthUserContext {
|
|
|
317
348
|
return undefined;
|
|
318
349
|
}
|
|
319
350
|
}
|
|
320
|
-
/**
|
|
321
|
-
* Sets the user's password.
|
|
322
|
-
*/
|
|
323
351
|
async setPassword(password) {
|
|
324
352
|
const record = await this.updateUser({ password });
|
|
325
353
|
// clear password reset claims
|
|
@@ -352,15 +380,19 @@ class AbstractFirebaseServerAuthUserContext {
|
|
|
352
380
|
return this.updateClaims(claims);
|
|
353
381
|
}
|
|
354
382
|
/**
|
|
355
|
-
*
|
|
383
|
+
* Replaces all role-based claims with those derived from the given roles.
|
|
356
384
|
*
|
|
357
|
-
* All
|
|
385
|
+
* All existing claims are cleared first. Use `claimsToRetain` to preserve non-role claims
|
|
386
|
+
* (e.g., setup or application-specific claims) through the replacement.
|
|
358
387
|
*
|
|
359
|
-
*
|
|
388
|
+
* @param roles - The complete set of roles to assign.
|
|
389
|
+
* @param claimsToRetain - Additional claims to merge in alongside the role-derived claims.
|
|
360
390
|
*
|
|
361
|
-
* @
|
|
362
|
-
*
|
|
363
|
-
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```typescript
|
|
393
|
+
* // Set roles while preserving a custom claim
|
|
394
|
+
* await userCtx.setRoles([AUTH_ADMIN_ROLE], { customFlag: 1 });
|
|
395
|
+
* ```
|
|
364
396
|
*/
|
|
365
397
|
async setRoles(roles, claimsToRetain) {
|
|
366
398
|
const claims = {
|
|
@@ -369,8 +401,11 @@ class AbstractFirebaseServerAuthUserContext {
|
|
|
369
401
|
};
|
|
370
402
|
return this.setClaims(claims);
|
|
371
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Converts roles to their corresponding claim keys, filtering out null/undefined entries
|
|
406
|
+
* that represent unrelated claims in the service's {@link FirebaseServerAuthService.claimsForRoles} output.
|
|
407
|
+
*/
|
|
372
408
|
_claimsForRolesChange(roles) {
|
|
373
|
-
// filter null/undefined since the claims will contain null values for claims that are not related.
|
|
374
409
|
return filterNullAndUndefinedValues(this.service.claimsForRoles(asSet(roles)));
|
|
375
410
|
}
|
|
376
411
|
loadClaims() {
|
|
@@ -400,6 +435,15 @@ class AbstractFirebaseServerAuthUserContext {
|
|
|
400
435
|
});
|
|
401
436
|
}
|
|
402
437
|
}
|
|
438
|
+
/**
|
|
439
|
+
* Base implementation of {@link FirebaseServerAuthContext} with cached getters for roles, admin status,
|
|
440
|
+
* and ToS status to avoid redundant computation within a single request.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* export class MyAuthContext extends AbstractFirebaseServerAuthContext<MyAuthContext, MyUserContext, MyAuthService> {}
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
403
447
|
class AbstractFirebaseServerAuthContext {
|
|
404
448
|
_service;
|
|
405
449
|
_context;
|
|
@@ -441,15 +485,52 @@ class AbstractFirebaseServerAuthContext {
|
|
|
441
485
|
}
|
|
442
486
|
}
|
|
443
487
|
/**
|
|
444
|
-
* 1 hour
|
|
488
|
+
* Default throttle duration (1 hour) between setup content sends to prevent spam.
|
|
489
|
+
*
|
|
490
|
+
* Used by {@link AbstractFirebaseServerNewUserService.sendSetupContent} to rate-limit delivery.
|
|
445
491
|
*/
|
|
446
492
|
const DEFAULT_SETUP_COM_THROTTLE_TIME = hoursToMs(1);
|
|
493
|
+
/**
|
|
494
|
+
* Resolves a {@link UserContextOrUid} to a concrete user context instance.
|
|
495
|
+
*
|
|
496
|
+
* If a string UID is provided, creates a new user context via the auth service.
|
|
497
|
+
* If an existing context is provided, returns it as-is.
|
|
498
|
+
*
|
|
499
|
+
* @param authService - The auth service to create a context from if needed.
|
|
500
|
+
* @param userContextOrUid - A user context or UID string.
|
|
501
|
+
*
|
|
502
|
+
* @example
|
|
503
|
+
* ```typescript
|
|
504
|
+
* const ctx = userContextFromUid(authService, 'some-uid');
|
|
505
|
+
* const sameCtx = userContextFromUid(authService, ctx); // returns ctx unchanged
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
447
508
|
function userContextFromUid(authService, userContextOrUid) {
|
|
448
509
|
const userContext = typeof userContextOrUid === 'string' ? authService.userContext(userContextOrUid) : userContextOrUid;
|
|
449
510
|
return userContext;
|
|
450
511
|
}
|
|
512
|
+
/**
|
|
513
|
+
* Base implementation of {@link FirebaseServerNewUserService} that handles user creation,
|
|
514
|
+
* setup claims management, throttled setup content delivery, and setup completion.
|
|
515
|
+
*
|
|
516
|
+
* Subclasses must implement {@link sendSetupContentToUser} to define how setup content
|
|
517
|
+
* (e.g., invitation email, SMS) is delivered to the user.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* ```typescript
|
|
521
|
+
* export class MyNewUserService extends AbstractFirebaseServerNewUserService<MyUserContext> {
|
|
522
|
+
* protected async sendSetupContentToUser(details: FirebaseServerAuthNewUserSetupDetails<MyUserContext>): Promise<void> {
|
|
523
|
+
* await this.emailService.sendInvite(details.userContext.uid, details.claims.setupPassword);
|
|
524
|
+
* }
|
|
525
|
+
* }
|
|
526
|
+
* ```
|
|
527
|
+
*/
|
|
451
528
|
class AbstractFirebaseServerNewUserService {
|
|
452
529
|
_authService;
|
|
530
|
+
/**
|
|
531
|
+
* Minimum time between setup content sends. Defaults to {@link DEFAULT_SETUP_COM_THROTTLE_TIME} (1 hour).
|
|
532
|
+
* Override in subclasses to customize the throttle window.
|
|
533
|
+
*/
|
|
453
534
|
setupThrottleTime = DEFAULT_SETUP_COM_THROTTLE_TIME;
|
|
454
535
|
constructor(authService) {
|
|
455
536
|
this._authService = authService;
|
|
@@ -561,19 +642,15 @@ class AbstractFirebaseServerNewUserService {
|
|
|
561
642
|
}
|
|
562
643
|
return details;
|
|
563
644
|
}
|
|
645
|
+
/**
|
|
646
|
+
* Records the current timestamp as the last setup content communication date in the user's claims.
|
|
647
|
+
*/
|
|
564
648
|
async updateSetupContentSentTime(details) {
|
|
565
649
|
const setupCommunicationAt = toISODateString(new Date());
|
|
566
650
|
await details.userContext.updateClaims({
|
|
567
651
|
setupCommunicationAt
|
|
568
652
|
});
|
|
569
653
|
}
|
|
570
|
-
/**
|
|
571
|
-
* Update a user's claims to clear any setup-related content.
|
|
572
|
-
*
|
|
573
|
-
* Returns true if a user was updated.
|
|
574
|
-
*
|
|
575
|
-
* @param uid
|
|
576
|
-
*/
|
|
577
654
|
async markUserSetupAsComplete(uid) {
|
|
578
655
|
const userContext = this.authService.userContext(uid);
|
|
579
656
|
const userExists = await userContext.exists();
|
|
@@ -582,6 +659,13 @@ class AbstractFirebaseServerNewUserService {
|
|
|
582
659
|
}
|
|
583
660
|
return userExists;
|
|
584
661
|
}
|
|
662
|
+
/**
|
|
663
|
+
* Creates a new Firebase Auth user from the initialization input.
|
|
664
|
+
*
|
|
665
|
+
* Generates a random setup password if none is provided. Override to customize user creation behavior.
|
|
666
|
+
*
|
|
667
|
+
* @throws Throws if the Firebase Admin SDK rejects the user creation.
|
|
668
|
+
*/
|
|
585
669
|
async createNewUser(input) {
|
|
586
670
|
const { uid, displayName, email, phone: phoneNumber, setupPassword: inputPassword } = input;
|
|
587
671
|
const password = inputPassword ?? this.generateRandomSetupPassword();
|
|
@@ -600,6 +684,9 @@ class AbstractFirebaseServerNewUserService {
|
|
|
600
684
|
generateRandomSetupPassword() {
|
|
601
685
|
return `${DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR()}`;
|
|
602
686
|
}
|
|
687
|
+
/**
|
|
688
|
+
* Clears setup-related claims (setup password and last communication date) from the user.
|
|
689
|
+
*/
|
|
603
690
|
async updateClaimsToClearUser(userContext) {
|
|
604
691
|
await userContext.updateClaims({
|
|
605
692
|
[FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY]: null,
|
|
@@ -607,18 +694,65 @@ class AbstractFirebaseServerNewUserService {
|
|
|
607
694
|
});
|
|
608
695
|
}
|
|
609
696
|
}
|
|
697
|
+
/**
|
|
698
|
+
* No-op implementation of {@link AbstractFirebaseServerNewUserService} that skips sending setup content.
|
|
699
|
+
*
|
|
700
|
+
* Used as the default {@link FirebaseServerNewUserService} when no custom delivery mechanism is configured.
|
|
701
|
+
*/
|
|
610
702
|
class NoSetupContentFirebaseServerNewUserService extends AbstractFirebaseServerNewUserService {
|
|
611
|
-
async sendSetupContentToUser(
|
|
703
|
+
async sendSetupContentToUser(_details) {
|
|
612
704
|
// send nothing.
|
|
613
705
|
}
|
|
614
706
|
}
|
|
615
707
|
/**
|
|
616
|
-
*
|
|
708
|
+
* Abstract contract for a Firebase Server authentication service.
|
|
709
|
+
*
|
|
710
|
+
* Provides the core API for creating auth contexts from callable requests, managing user contexts,
|
|
711
|
+
* checking admin/ToS status, converting between roles and claims, and creating new users.
|
|
712
|
+
*
|
|
713
|
+
* Implement this by extending {@link AbstractFirebaseServerAuthService}, which provides default
|
|
714
|
+
* implementations for most methods and only requires `readRoles`, `claimsForRoles`,
|
|
715
|
+
* `userContext`, and `_context` to be defined.
|
|
716
|
+
*
|
|
717
|
+
* @example
|
|
718
|
+
* ```typescript
|
|
719
|
+
* class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
|
|
720
|
+
* readRoles(claims: AuthClaims): AuthRoleSet { ... }
|
|
721
|
+
* claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate { ... }
|
|
722
|
+
* userContext(uid: string): MyUserContext { ... }
|
|
723
|
+
* protected _context(ctx: CallableContextWithAuthData): MyAuthContext { ... }
|
|
724
|
+
* }
|
|
725
|
+
* ```
|
|
617
726
|
*/
|
|
618
727
|
class FirebaseServerAuthService {
|
|
619
728
|
}
|
|
620
729
|
/**
|
|
621
|
-
*
|
|
730
|
+
* Base implementation of {@link FirebaseServerAuthService} providing standard admin/ToS checks,
|
|
731
|
+
* auth context creation with assertion, and a default no-op new user service.
|
|
732
|
+
*
|
|
733
|
+
* Subclasses must implement:
|
|
734
|
+
* - {@link _context} - to create the concrete auth context type.
|
|
735
|
+
* - {@link userContext} - to create the concrete user context type.
|
|
736
|
+
* - {@link readRoles} - to define the claims-to-roles mapping.
|
|
737
|
+
* - {@link claimsForRoles} - to define the roles-to-claims mapping.
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```typescript
|
|
741
|
+
* export class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
|
|
742
|
+
* protected _context(context: CallableContextWithAuthData): MyAuthContext {
|
|
743
|
+
* return new MyAuthContext(this, context);
|
|
744
|
+
* }
|
|
745
|
+
* userContext(uid: string): MyUserContext {
|
|
746
|
+
* return new MyUserContext(this, uid);
|
|
747
|
+
* }
|
|
748
|
+
* readRoles(claims: AuthClaims): AuthRoleSet {
|
|
749
|
+
* return MY_CLAIMS_SERVICE.toRoles(claims);
|
|
750
|
+
* }
|
|
751
|
+
* claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate {
|
|
752
|
+
* return MY_CLAIMS_SERVICE.toClaims(roles);
|
|
753
|
+
* }
|
|
754
|
+
* }
|
|
755
|
+
* ```
|
|
622
756
|
*/
|
|
623
757
|
class AbstractFirebaseServerAuthService {
|
|
624
758
|
_auth;
|
|
@@ -1046,6 +1180,140 @@ function googleCloudFirestoreDrivers() {
|
|
|
1046
1180
|
*/
|
|
1047
1181
|
const googleCloudFirestoreContextFactory = firestoreContextFactory(googleCloudFirestoreDrivers());
|
|
1048
1182
|
|
|
1183
|
+
// MARK: Encrypted Field
|
|
1184
|
+
/**
|
|
1185
|
+
* AES-256-GCM encryption constants.
|
|
1186
|
+
*/
|
|
1187
|
+
const ENCRYPTED_FIELD_ALGORITHM = 'aes-256-gcm';
|
|
1188
|
+
const ENCRYPTED_FIELD_IV_LENGTH = 12;
|
|
1189
|
+
const ENCRYPTED_FIELD_AUTH_TAG_LENGTH = 16;
|
|
1190
|
+
const ENCRYPTED_FIELD_KEY_LENGTH = 32;
|
|
1191
|
+
/**
|
|
1192
|
+
* Resolves the encryption key Buffer from a secret source.
|
|
1193
|
+
*
|
|
1194
|
+
* @param source - The secret source configuration.
|
|
1195
|
+
* @returns A 32-byte Buffer for AES-256 encryption.
|
|
1196
|
+
* @throws Error if the resolved key is not 64 hex characters.
|
|
1197
|
+
*/
|
|
1198
|
+
function resolveEncryptionKey(source) {
|
|
1199
|
+
let hex;
|
|
1200
|
+
if (typeof source === 'string') {
|
|
1201
|
+
hex = source;
|
|
1202
|
+
}
|
|
1203
|
+
else if (typeof source === 'function') {
|
|
1204
|
+
hex = source();
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
const envValue = process.env[source.env];
|
|
1208
|
+
if (!envValue) {
|
|
1209
|
+
throw new Error(`firestoreEncryptedField: environment variable "${source.env}" is not set.`);
|
|
1210
|
+
}
|
|
1211
|
+
hex = envValue;
|
|
1212
|
+
}
|
|
1213
|
+
if (hex.length !== ENCRYPTED_FIELD_KEY_LENGTH * 2) {
|
|
1214
|
+
throw new Error(`firestoreEncryptedField: expected a ${ENCRYPTED_FIELD_KEY_LENGTH * 2}-character hex key, got ${hex.length} characters.`);
|
|
1215
|
+
}
|
|
1216
|
+
return Buffer.from(hex, 'hex');
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Encrypts a JSON-serializable value to a base64-encoded string.
|
|
1220
|
+
*
|
|
1221
|
+
* Format: base64(IV (12 bytes) + ciphertext + authTag (16 bytes))
|
|
1222
|
+
*
|
|
1223
|
+
* @param value - The value to encrypt.
|
|
1224
|
+
* @param key - The 32-byte encryption key.
|
|
1225
|
+
* @returns The encrypted value as a base64 string.
|
|
1226
|
+
*/
|
|
1227
|
+
function encryptValue(value, key) {
|
|
1228
|
+
const iv = randomBytes(ENCRYPTED_FIELD_IV_LENGTH);
|
|
1229
|
+
const cipher = createCipheriv(ENCRYPTED_FIELD_ALGORITHM, key, iv);
|
|
1230
|
+
const plaintext = JSON.stringify(value);
|
|
1231
|
+
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()]);
|
|
1232
|
+
const authTag = cipher.getAuthTag();
|
|
1233
|
+
const combined = Buffer.concat([iv, encrypted, authTag]);
|
|
1234
|
+
return combined.toString('base64');
|
|
1235
|
+
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Decrypts a base64-encoded string back to the original value.
|
|
1238
|
+
*
|
|
1239
|
+
* @param encoded - The base64-encoded encrypted string (IV + ciphertext + authTag).
|
|
1240
|
+
* @param key - The 32-byte encryption key.
|
|
1241
|
+
* @returns The decrypted value.
|
|
1242
|
+
*/
|
|
1243
|
+
function decryptValue(encoded, key) {
|
|
1244
|
+
const combined = Buffer.from(encoded, 'base64');
|
|
1245
|
+
const iv = combined.subarray(0, ENCRYPTED_FIELD_IV_LENGTH);
|
|
1246
|
+
const authTag = combined.subarray(combined.length - ENCRYPTED_FIELD_AUTH_TAG_LENGTH);
|
|
1247
|
+
const ciphertext = combined.subarray(ENCRYPTED_FIELD_IV_LENGTH, combined.length - ENCRYPTED_FIELD_AUTH_TAG_LENGTH);
|
|
1248
|
+
const decipher = createDecipheriv(ENCRYPTED_FIELD_ALGORITHM, key, iv);
|
|
1249
|
+
decipher.setAuthTag(authTag);
|
|
1250
|
+
const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
|
|
1251
|
+
return JSON.parse(decrypted.toString('utf8'));
|
|
1252
|
+
}
|
|
1253
|
+
/**
|
|
1254
|
+
* Creates a Firestore field mapping that encrypts/decrypts a JSON-serializable value
|
|
1255
|
+
* using AES-256-GCM. The value is stored in Firestore as a base64-encoded string.
|
|
1256
|
+
*
|
|
1257
|
+
* The encryption key is resolved from the configured secret source on each read/write,
|
|
1258
|
+
* allowing for key rotation via environment variable changes.
|
|
1259
|
+
*
|
|
1260
|
+
* @example
|
|
1261
|
+
* ```typescript
|
|
1262
|
+
* const jwksField = firestoreEncryptedField<JWKSet>({
|
|
1263
|
+
* secret: { env: 'FIRESTORE_ENCRYPTION_KEY' },
|
|
1264
|
+
* default: () => ({ keys: [] })
|
|
1265
|
+
* });
|
|
1266
|
+
* ```
|
|
1267
|
+
*
|
|
1268
|
+
* @template T - The JSON-serializable value type.
|
|
1269
|
+
* @param config - Encryption field configuration.
|
|
1270
|
+
* @returns A field mapping configuration for encrypted values.
|
|
1271
|
+
*/
|
|
1272
|
+
function firestoreEncryptedField(config) {
|
|
1273
|
+
const { secret, default: defaultValue } = config;
|
|
1274
|
+
return firestoreField({
|
|
1275
|
+
default: defaultValue,
|
|
1276
|
+
fromData: (data) => {
|
|
1277
|
+
const key = resolveEncryptionKey(secret);
|
|
1278
|
+
return decryptValue(data, key);
|
|
1279
|
+
},
|
|
1280
|
+
toData: (value) => {
|
|
1281
|
+
const key = resolveEncryptionKey(secret);
|
|
1282
|
+
return encryptValue(value, key);
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Creates a Firestore field mapping for an optional encrypted field.
|
|
1288
|
+
*
|
|
1289
|
+
* When the value is null/undefined, it is stored/read as null. When present, it is
|
|
1290
|
+
* encrypted/decrypted using AES-256-GCM.
|
|
1291
|
+
*
|
|
1292
|
+
* @example
|
|
1293
|
+
* ```typescript
|
|
1294
|
+
* const optionalSecretField = optionalFirestoreEncryptedField<OAuthClientSecret>({
|
|
1295
|
+
* secret: { env: 'FIRESTORE_ENCRYPTION_KEY' }
|
|
1296
|
+
* });
|
|
1297
|
+
* ```
|
|
1298
|
+
*
|
|
1299
|
+
* @template T - The JSON-serializable value type.
|
|
1300
|
+
* @param config - Encryption field configuration.
|
|
1301
|
+
* @returns A field mapping configuration for optional encrypted values.
|
|
1302
|
+
*/
|
|
1303
|
+
function optionalFirestoreEncryptedField(config) {
|
|
1304
|
+
const { secret } = config;
|
|
1305
|
+
return optionalFirestoreField({
|
|
1306
|
+
transformFromData: (data) => {
|
|
1307
|
+
const key = resolveEncryptionKey(secret);
|
|
1308
|
+
return decryptValue(data, key);
|
|
1309
|
+
},
|
|
1310
|
+
transformToData: (value) => {
|
|
1311
|
+
const key = resolveEncryptionKey(secret);
|
|
1312
|
+
return encryptValue(value, key);
|
|
1313
|
+
}
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1049
1317
|
function assertContextHasAuth(context) {
|
|
1050
1318
|
if (!isContextWithAuthData(context)) {
|
|
1051
1319
|
throw unauthenticatedContextHasNoUidError();
|
|
@@ -1890,6 +2158,163 @@ ConfigureFirebaseWebhookMiddlewareModule = __decorate([
|
|
|
1890
2158
|
Module({})
|
|
1891
2159
|
], ConfigureFirebaseWebhookMiddlewareModule);
|
|
1892
2160
|
|
|
2161
|
+
// MARK: Type Guards
|
|
2162
|
+
/**
|
|
2163
|
+
* Whether the details are specifier-level (has specifiers map).
|
|
2164
|
+
*/
|
|
2165
|
+
function isOnCallSpecifierApiDetails(details) {
|
|
2166
|
+
return details != null && 'specifiers' in details;
|
|
2167
|
+
}
|
|
2168
|
+
/**
|
|
2169
|
+
* Whether the details are CRUD-model-level (has modelTypes map).
|
|
2170
|
+
*/
|
|
2171
|
+
function isOnCallCrudModelApiDetails(details) {
|
|
2172
|
+
return details != null && 'modelTypes' in details;
|
|
2173
|
+
}
|
|
2174
|
+
/**
|
|
2175
|
+
* Whether the details are handler-level (leaf node — no specifiers or modelTypes).
|
|
2176
|
+
*/
|
|
2177
|
+
function isOnCallHandlerApiDetails(details) {
|
|
2178
|
+
return details != null && !('specifiers' in details) && !('modelTypes' in details);
|
|
2179
|
+
}
|
|
2180
|
+
/**
|
|
2181
|
+
* Attaches API details metadata to a handler function.
|
|
2182
|
+
*
|
|
2183
|
+
* The handler function is provided in the config object alongside its metadata.
|
|
2184
|
+
* The function is returned unchanged but with the _apiDetails property set.
|
|
2185
|
+
* Compatible with all handler types (create, read, update, delete, specifier).
|
|
2186
|
+
*
|
|
2187
|
+
* When `optionalAuth: true` is set, also marks the function as not requiring auth
|
|
2188
|
+
* (same effect as optionalAuthContext). This avoids the composition issue where
|
|
2189
|
+
* optionalAuthContext(withApiDetails(...)) would lose the _apiDetails.
|
|
2190
|
+
*
|
|
2191
|
+
* @example
|
|
2192
|
+
* ```typescript
|
|
2193
|
+
* // Handler with api details (auth required by default)
|
|
2194
|
+
* export const createGuestbook: DemoCreateModelFunction<CreateGuestbookParams> = withApiDetails({
|
|
2195
|
+
* inputType: createGuestbookParamsType,
|
|
2196
|
+
* fn: async (request) => {
|
|
2197
|
+
* const { nest, auth, data } = request;
|
|
2198
|
+
* const result = await nest.guestbookActions.createGuestbook(data);
|
|
2199
|
+
* return onCallCreateModelResultWithDocs(await result());
|
|
2200
|
+
* }
|
|
2201
|
+
* });
|
|
2202
|
+
*
|
|
2203
|
+
* // Handler with optional auth
|
|
2204
|
+
* export const profileCreate: DemoCreateModelFunction<{}> = withApiDetails({
|
|
2205
|
+
* optionalAuth: true,
|
|
2206
|
+
* fn: async (request) => { ... }
|
|
2207
|
+
* });
|
|
2208
|
+
* ```
|
|
2209
|
+
*/
|
|
2210
|
+
function withApiDetails(config) {
|
|
2211
|
+
const { optionalAuth, fn, ...apiDetails } = config;
|
|
2212
|
+
fn._apiDetails = apiDetails;
|
|
2213
|
+
if (optionalAuth) {
|
|
2214
|
+
fn._requireAuth = false;
|
|
2215
|
+
}
|
|
2216
|
+
return fn;
|
|
2217
|
+
}
|
|
2218
|
+
// MARK: Aggregation Utilities
|
|
2219
|
+
/**
|
|
2220
|
+
* Reads _apiDetails from a function if present.
|
|
2221
|
+
*/
|
|
2222
|
+
function readApiDetails(fn) {
|
|
2223
|
+
return fn?._apiDetails;
|
|
2224
|
+
}
|
|
2225
|
+
/**
|
|
2226
|
+
* Aggregates _apiDetails from a specifier handler config object.
|
|
2227
|
+
*
|
|
2228
|
+
* Returns OnCallSpecifierApiDetails if any handlers have _apiDetails, otherwise undefined.
|
|
2229
|
+
*/
|
|
2230
|
+
function aggregateSpecifierApiDetails(config) {
|
|
2231
|
+
const specifiers = {};
|
|
2232
|
+
let hasAny = false;
|
|
2233
|
+
for (const [key, handler] of Object.entries(config)) {
|
|
2234
|
+
const details = readApiDetails(handler);
|
|
2235
|
+
if (details != null) {
|
|
2236
|
+
// At the specifier level, details should be handler-level (OnCallModelFunctionApiDetails)
|
|
2237
|
+
specifiers[key] = details;
|
|
2238
|
+
hasAny = true;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
return hasAny ? { specifiers } : undefined;
|
|
2242
|
+
}
|
|
2243
|
+
/**
|
|
2244
|
+
* Aggregates _apiDetails from a model type map (used by onCallCreateModel, etc.).
|
|
2245
|
+
*
|
|
2246
|
+
* Returns OnCallCrudModelApiDetails if any handlers have _apiDetails, otherwise undefined.
|
|
2247
|
+
*/
|
|
2248
|
+
function aggregateCrudModelApiDetails(map) {
|
|
2249
|
+
const modelTypes = {};
|
|
2250
|
+
let hasAny = false;
|
|
2251
|
+
for (const [key, handler] of Object.entries(map)) {
|
|
2252
|
+
const details = readApiDetails(handler);
|
|
2253
|
+
if (details != null) {
|
|
2254
|
+
modelTypes[key] = details;
|
|
2255
|
+
hasAny = true;
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
return hasAny ? { modelTypes } : undefined;
|
|
2259
|
+
}
|
|
2260
|
+
/**
|
|
2261
|
+
* Aggregates _apiDetails from the top-level call model map.
|
|
2262
|
+
*
|
|
2263
|
+
* Returns OnCallModelApiDetails if any CRUD handlers have _apiDetails, otherwise undefined.
|
|
2264
|
+
*/
|
|
2265
|
+
function aggregateModelApiDetails(map) {
|
|
2266
|
+
const result = {};
|
|
2267
|
+
let hasAny = false;
|
|
2268
|
+
for (const [call, handler] of Object.entries(map)) {
|
|
2269
|
+
const details = readApiDetails(handler);
|
|
2270
|
+
if (details != null) {
|
|
2271
|
+
result[call] = details;
|
|
2272
|
+
hasAny = true;
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2275
|
+
return hasAny ? result : undefined;
|
|
2276
|
+
}
|
|
2277
|
+
/**
|
|
2278
|
+
* Extracts and pivots API details from a call model function into a model-first view.
|
|
2279
|
+
*
|
|
2280
|
+
* The internal aggregation tree is organized as CRUD → modelType. This function
|
|
2281
|
+
* pivots it to modelType → CRUD, which is the natural shape for MCP tool generation
|
|
2282
|
+
* and schema introspection.
|
|
2283
|
+
*
|
|
2284
|
+
* @param callModelFn The function returned by onCallModel(), or any object with _apiDetails.
|
|
2285
|
+
* @returns Model-first API details, or undefined if no _apiDetails are present.
|
|
2286
|
+
*
|
|
2287
|
+
* @example
|
|
2288
|
+
* ```typescript
|
|
2289
|
+
* const details = getModelApiDetails(demoCallModel);
|
|
2290
|
+
* // details.models['guestbook'].calls.create => { inputType: createGuestbookParamsType }
|
|
2291
|
+
* // details.models['profile'].calls.update => { specifiers: { _: {...}, username: {...} } }
|
|
2292
|
+
* ```
|
|
2293
|
+
*/
|
|
2294
|
+
function getModelApiDetails(callModelFn) {
|
|
2295
|
+
const topDetails = readApiDetails(callModelFn);
|
|
2296
|
+
if (topDetails == null) {
|
|
2297
|
+
return undefined;
|
|
2298
|
+
}
|
|
2299
|
+
const models = {};
|
|
2300
|
+
// Pivot: iterate CRUD types, then model types within each
|
|
2301
|
+
for (const [callType, crudDetails] of Object.entries(topDetails)) {
|
|
2302
|
+
if (crudDetails == null) {
|
|
2303
|
+
continue;
|
|
2304
|
+
}
|
|
2305
|
+
for (const [modelType, modelDetails] of Object.entries(crudDetails.modelTypes)) {
|
|
2306
|
+
if (modelDetails == null) {
|
|
2307
|
+
continue;
|
|
2308
|
+
}
|
|
2309
|
+
if (!models[modelType]) {
|
|
2310
|
+
models[modelType] = { calls: {} };
|
|
2311
|
+
}
|
|
2312
|
+
models[modelType].calls[callType] = modelDetails;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
return Object.keys(models).length > 0 ? { models } : undefined;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
1893
2318
|
const nestFirebaseDoesNotExistError = (firebaseContextGrantedModelRoles) => {
|
|
1894
2319
|
return modelNotAvailableError({
|
|
1895
2320
|
data: {
|
|
@@ -1922,6 +2347,11 @@ function onCallSpecifierHandler(config) {
|
|
|
1922
2347
|
}
|
|
1923
2348
|
};
|
|
1924
2349
|
fn._requireAuth = false;
|
|
2350
|
+
// Aggregate _apiDetails from handler functions in the config
|
|
2351
|
+
const specifierApiDetails = aggregateSpecifierApiDetails(config);
|
|
2352
|
+
if (specifierApiDetails != null) {
|
|
2353
|
+
fn._apiDetails = specifierApiDetails;
|
|
2354
|
+
}
|
|
1925
2355
|
return fn;
|
|
1926
2356
|
}
|
|
1927
2357
|
function unknownModelCrudFunctionSpecifierError(specifier) {
|
|
@@ -1943,7 +2373,7 @@ function unknownModelCrudFunctionSpecifierError(specifier) {
|
|
|
1943
2373
|
*/
|
|
1944
2374
|
function onCallModel(map, config = {}) {
|
|
1945
2375
|
const { preAssert = () => undefined } = config;
|
|
1946
|
-
|
|
2376
|
+
const fn = (request) => {
|
|
1947
2377
|
const call = request.data?.call;
|
|
1948
2378
|
if (call) {
|
|
1949
2379
|
const callFn = map[call];
|
|
@@ -1960,6 +2390,12 @@ function onCallModel(map, config = {}) {
|
|
|
1960
2390
|
throw onCallModelMissingCallTypeError();
|
|
1961
2391
|
}
|
|
1962
2392
|
};
|
|
2393
|
+
// Aggregate _apiDetails from CRUD handlers in the map
|
|
2394
|
+
const modelApiDetails = aggregateModelApiDetails(map);
|
|
2395
|
+
if (modelApiDetails != null) {
|
|
2396
|
+
fn._apiDetails = modelApiDetails;
|
|
2397
|
+
}
|
|
2398
|
+
return fn;
|
|
1963
2399
|
}
|
|
1964
2400
|
function onCallModelMissingCallTypeError() {
|
|
1965
2401
|
return badRequestError(serverError({
|
|
@@ -1980,7 +2416,7 @@ function onCallModelUnknownCallTypeError(call) {
|
|
|
1980
2416
|
}
|
|
1981
2417
|
function _onCallWithCallTypeFunction(map, config) {
|
|
1982
2418
|
const { callType, crudType, preAssert = () => undefined, throwOnUnknownModelType } = config;
|
|
1983
|
-
|
|
2419
|
+
const fn = (request) => {
|
|
1984
2420
|
const modelType = request.data?.modelType;
|
|
1985
2421
|
const crudFn = map[modelType];
|
|
1986
2422
|
if (crudFn) {
|
|
@@ -1997,6 +2433,12 @@ function _onCallWithCallTypeFunction(map, config) {
|
|
|
1997
2433
|
throw throwOnUnknownModelType(modelType);
|
|
1998
2434
|
}
|
|
1999
2435
|
};
|
|
2436
|
+
// Aggregate _apiDetails from model type handlers in the map
|
|
2437
|
+
const crudModelApiDetails = aggregateCrudModelApiDetails(map);
|
|
2438
|
+
if (crudModelApiDetails != null) {
|
|
2439
|
+
fn._apiDetails = crudModelApiDetails;
|
|
2440
|
+
}
|
|
2441
|
+
return fn;
|
|
2000
2442
|
}
|
|
2001
2443
|
|
|
2002
2444
|
function onCallCreateModel(map, config = {}) {
|
|
@@ -2682,5 +3124,5 @@ class AbstractFirebaseNestContext extends AbstractNestContext {
|
|
|
2682
3124
|
}
|
|
2683
3125
|
}
|
|
2684
3126
|
|
|
2685
|
-
export { ALREADY_EXISTS_ERROR_CODE, AbstractFirebaseNestContext, AbstractFirebaseServerActionsContext, AbstractFirebaseServerAuthContext, AbstractFirebaseServerAuthService, AbstractFirebaseServerAuthUserContext, AbstractFirebaseServerNewUserService, AbstractNestContext, BAD_REQUEST_ERROR_CODE, CONFLICT_ERROR_CODE, ConfigureFirebaseAppCheckMiddlewareModule, ConfigureFirebaseWebhookMiddlewareModule, DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR, DEFAULT_SETUP_COM_THROTTLE_TIME, DefaultFirebaseServerEnvService, FIREBASE_APP_TOKEN, FIREBASE_AUTH_TOKEN, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FIREBASE_FIRESTORE_TOKEN, FIREBASE_SERVER_VALIDATION_ERROR_CODE, FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN, FIREBASE_STORAGE_CONTEXT_TOKEN, FIREBASE_STORAGE_TOKEN, FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING, FORBIDDEN_ERROR_CODE, FirebaseAppCheckMiddleware, FirebaseNestServerRootModule, FirebaseRawBodyMiddleware, FirebaseServerAuthModule, FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError, FirebaseServerAuthNewUserSendSetupDetailsSendOnceError, FirebaseServerAuthNewUserSendSetupDetailsThrottleError, FirebaseServerAuthService, FirebaseServerEnvService, FirebaseServerFirestoreContextModule, FirebaseServerFirestoreModule, FirebaseServerStorageContextModule, FirebaseServerStorageModule, FirebaseServerStorageService, INTERNAL_SERVER_ERROR_CODE, MODEL_NOT_AVAILABLE_ERROR_CODE, NOT_FOUND_ERROR_CODE, NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, NoSetupContentFirebaseServerNewUserService, PERMISSION_DENIED_ERROR_CODE, PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE, SkipAppCheck, UNAUTHENTICATED_ERROR_CODE, UNAVAILABLE_ERROR_CODE, UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, _onCallWithCallTypeFunction, alreadyExistsError, appFirestoreModuleMetadata, assertContextHasAuth, assertDocumentExists, assertHasRolesInRequest, assertHasSignedTosInRequest, assertIsAdminInRequest, assertIsAdminOrTargetUserInRequestData, assertIsContextWithAuthData, assertRequestRequiresAuthForFunction, assertSnapshotData, assertSnapshotDataWithKey, badRequestError, blockingFunctionHandlerWithNestContextFactory, cloudEventHandlerWithNestContextFactory, collectionRefForPath, createModelUnknownModelTypeError, defaultFirebaseServerActionsTransformFactoryLogErrorFunction, defaultProvideFirebaseServerStorageServiceSimple, deleteModelUnknownModelTypeError, developmentUnknownSpecifierError, docRefForPath, documentModelNotAvailableError, firebaseAuthTokenFromDecodedIdToken, firebaseServerActionsContext, firebaseServerActionsTransformContext, firebaseServerActionsTransformFactory, firebaseServerAppTokenProvider, firebaseServerAuthModuleMetadata, firebaseServerDevFunctions, firebaseServerErrorInfo, firebaseServerErrorInfoCodePair, firebaseServerErrorInfoServerErrorCodePair, firebaseServerErrorInfoServerErrorPair, firebaseServerStorageDefaultBucketIdTokenProvider, firebaseServerStorageModuleMetadata, firebaseServerValidationError, firebaseServerValidationServerError, firestoreClientQueryConstraintFunctionsDriver, firestoreServerIncrementUpdateToUpdateData, forbiddenError, getAuthUserOrUndefined, googleCloudFileMetadataToStorageMetadata, googleCloudFirebaseStorageContextFactory, googleCloudFirebaseStorageDrivers, googleCloudFirestoreAccessorDriver, googleCloudFirestoreContextFactory, googleCloudFirestoreDrivers, googleCloudFirestoreQueryDriver, googleCloudStorageAccessorFile, googleCloudStorageAccessorFolder, googleCloudStorageBucketForStorageFilePath, googleCloudStorageFileForStorageFilePath, googleCloudStorageFirebaseStorageAccessorDriver, googleCloudStorageFromFirebaseAdminStorage, googleCloudStorageListFilesResultFactory, handleFirebaseAuthError, handleFirebaseError, hasAuthRolesInRequest, hasNewUserSetupPasswordInRequest, hasSignedTosInRequest, inAuthContext, injectNestApplicationContextIntoRequest, injectNestIntoRequest, internalServerError, isAdminInRequest, isAdminOrTargetUserInRequestData, isContextWithAuthData, isFirebaseError, isFirebaseHttpsError, makeBlockingFunctionWithHandler, makeOnScheduleHandlerWithNestApplicationRequest, makeScheduledFunctionDevelopmentFunction, modelNotAvailableError, nestAppHasDevelopmentSchedulerEnabled, nestAppIsProductionEnvironment, nestFirebaseDoesNotExistError, nestFirebaseForbiddenPermissionError, nestServerInstance, noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, notFoundError, onCallCreateModel, onCallDeleteModel, onCallDevelopmentFunction, onCallHandlerWithNestApplicationFactory, onCallHandlerWithNestContextFactory, onCallModel, onCallModelMissingCallTypeError, onCallModelUnknownCallTypeError, onCallReadModel, onCallSpecifierHandler, onCallUpdateModel, onScheduleHandlerWithNestApplicationFactory, onScheduleHandlerWithNestContextFactory, optionalAuthContext, permissionDeniedError, phoneNumberAlreadyExistsError, preconditionConflictError, provideAppFirestoreCollections, provideFirebaseServerAuthService, provideFirebaseServerStorageService, readModelUnknownModelTypeError, setNestContextOnRequest, setNestContextOnScheduleRequest, taskQueueFunctionHandlerWithNestContextFactory, unauthenticatedContextHasNoAuthData, unauthenticatedContextHasNoUidError, unauthenticatedError, unavailableError, unavailableOrDeactivatedFunctionError, unknownModelCrudFunctionSpecifierError, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType, updateModelUnknownModelTypeError, userContextFromUid, verifyAppCheckInRequest };
|
|
3127
|
+
export { ALREADY_EXISTS_ERROR_CODE, AbstractFirebaseNestContext, AbstractFirebaseServerActionsContext, AbstractFirebaseServerAuthContext, AbstractFirebaseServerAuthService, AbstractFirebaseServerAuthUserContext, AbstractFirebaseServerNewUserService, AbstractNestContext, BAD_REQUEST_ERROR_CODE, CONFLICT_ERROR_CODE, ConfigureFirebaseAppCheckMiddlewareModule, ConfigureFirebaseWebhookMiddlewareModule, DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR, DEFAULT_SETUP_COM_THROTTLE_TIME, DefaultFirebaseServerEnvService, FIREBASE_APP_TOKEN, FIREBASE_AUTH_TOKEN, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FIREBASE_FIRESTORE_TOKEN, FIREBASE_SERVER_VALIDATION_ERROR_CODE, FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN, FIREBASE_STORAGE_CONTEXT_TOKEN, FIREBASE_STORAGE_TOKEN, FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING, FORBIDDEN_ERROR_CODE, FirebaseAppCheckMiddleware, FirebaseNestServerRootModule, FirebaseRawBodyMiddleware, FirebaseServerAuthModule, FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError, FirebaseServerAuthNewUserSendSetupDetailsSendOnceError, FirebaseServerAuthNewUserSendSetupDetailsThrottleError, FirebaseServerAuthService, FirebaseServerEnvService, FirebaseServerFirestoreContextModule, FirebaseServerFirestoreModule, FirebaseServerStorageContextModule, FirebaseServerStorageModule, FirebaseServerStorageService, INTERNAL_SERVER_ERROR_CODE, MODEL_NOT_AVAILABLE_ERROR_CODE, NOT_FOUND_ERROR_CODE, NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, NoSetupContentFirebaseServerNewUserService, PERMISSION_DENIED_ERROR_CODE, PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE, SkipAppCheck, UNAUTHENTICATED_ERROR_CODE, UNAVAILABLE_ERROR_CODE, UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, _onCallWithCallTypeFunction, aggregateCrudModelApiDetails, aggregateModelApiDetails, aggregateSpecifierApiDetails, alreadyExistsError, appFirestoreModuleMetadata, assertContextHasAuth, assertDocumentExists, assertHasRolesInRequest, assertHasSignedTosInRequest, assertIsAdminInRequest, assertIsAdminOrTargetUserInRequestData, assertIsContextWithAuthData, assertRequestRequiresAuthForFunction, assertSnapshotData, assertSnapshotDataWithKey, badRequestError, blockingFunctionHandlerWithNestContextFactory, cloudEventHandlerWithNestContextFactory, collectionRefForPath, createModelUnknownModelTypeError, defaultFirebaseServerActionsTransformFactoryLogErrorFunction, defaultProvideFirebaseServerStorageServiceSimple, deleteModelUnknownModelTypeError, developmentUnknownSpecifierError, docRefForPath, documentModelNotAvailableError, firebaseAuthTokenFromDecodedIdToken, firebaseServerActionsContext, firebaseServerActionsTransformContext, firebaseServerActionsTransformFactory, firebaseServerAppTokenProvider, firebaseServerAuthModuleMetadata, firebaseServerDevFunctions, firebaseServerErrorInfo, firebaseServerErrorInfoCodePair, firebaseServerErrorInfoServerErrorCodePair, firebaseServerErrorInfoServerErrorPair, firebaseServerStorageDefaultBucketIdTokenProvider, firebaseServerStorageModuleMetadata, firebaseServerValidationError, firebaseServerValidationServerError, firestoreClientQueryConstraintFunctionsDriver, firestoreEncryptedField, firestoreServerIncrementUpdateToUpdateData, forbiddenError, getAuthUserOrUndefined, getModelApiDetails, googleCloudFileMetadataToStorageMetadata, googleCloudFirebaseStorageContextFactory, googleCloudFirebaseStorageDrivers, googleCloudFirestoreAccessorDriver, googleCloudFirestoreContextFactory, googleCloudFirestoreDrivers, googleCloudFirestoreQueryDriver, googleCloudStorageAccessorFile, googleCloudStorageAccessorFolder, googleCloudStorageBucketForStorageFilePath, googleCloudStorageFileForStorageFilePath, googleCloudStorageFirebaseStorageAccessorDriver, googleCloudStorageFromFirebaseAdminStorage, googleCloudStorageListFilesResultFactory, handleFirebaseAuthError, handleFirebaseError, hasAuthRolesInRequest, hasNewUserSetupPasswordInRequest, hasSignedTosInRequest, inAuthContext, injectNestApplicationContextIntoRequest, injectNestIntoRequest, internalServerError, isAdminInRequest, isAdminOrTargetUserInRequestData, isContextWithAuthData, isFirebaseError, isFirebaseHttpsError, isOnCallCrudModelApiDetails, isOnCallHandlerApiDetails, isOnCallSpecifierApiDetails, makeBlockingFunctionWithHandler, makeOnScheduleHandlerWithNestApplicationRequest, makeScheduledFunctionDevelopmentFunction, modelNotAvailableError, nestAppHasDevelopmentSchedulerEnabled, nestAppIsProductionEnvironment, nestFirebaseDoesNotExistError, nestFirebaseForbiddenPermissionError, nestServerInstance, noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, notFoundError, onCallCreateModel, onCallDeleteModel, onCallDevelopmentFunction, onCallHandlerWithNestApplicationFactory, onCallHandlerWithNestContextFactory, onCallModel, onCallModelMissingCallTypeError, onCallModelUnknownCallTypeError, onCallReadModel, onCallSpecifierHandler, onCallUpdateModel, onScheduleHandlerWithNestApplicationFactory, onScheduleHandlerWithNestContextFactory, optionalAuthContext, optionalFirestoreEncryptedField, permissionDeniedError, phoneNumberAlreadyExistsError, preconditionConflictError, provideAppFirestoreCollections, provideFirebaseServerAuthService, provideFirebaseServerStorageService, readApiDetails, readModelUnknownModelTypeError, setNestContextOnRequest, setNestContextOnScheduleRequest, taskQueueFunctionHandlerWithNestContextFactory, unauthenticatedContextHasNoAuthData, unauthenticatedContextHasNoUidError, unauthenticatedError, unavailableError, unavailableOrDeactivatedFunctionError, unknownModelCrudFunctionSpecifierError, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType, updateModelUnknownModelTypeError, userContextFromUid, verifyAppCheckInRequest, withApiDetails };
|
|
2686
3128
|
//# sourceMappingURL=index.esm.js.map
|