@dereekb/firebase-server 14.2.0 → 14.4.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/calcom/package.json +10 -10
- package/discord/package.json +10 -10
- package/mailgun/package.json +9 -9
- package/mcp/package.json +12 -11
- package/model/package.json +10 -10
- package/oidc/index.esm.js +2063 -943
- package/oidc/package.json +12 -10
- package/oidc/src/lib/controller/oidc.interaction.controller.d.ts +3 -1
- package/oidc/src/lib/index.d.ts +1 -0
- package/oidc/src/lib/middleware/oauth-auth.module.d.ts +3 -0
- package/oidc/src/lib/oidc.module.d.ts +1 -38
- package/oidc/src/lib/oidc.resource-server.d.ts +170 -0
- package/oidc/src/lib/service/index.d.ts +2 -0
- package/oidc/src/lib/service/oidc.grant.d.ts +103 -0
- package/oidc/src/lib/service/oidc.jwt-signing.service.d.ts +77 -0
- package/oidc/src/lib/service/oidc.jwt-verify.d.ts +37 -0
- package/oidc/src/lib/service/oidc.service.d.ts +35 -4
- package/package.json +15 -13
- package/test/index.esm.js +244 -63
- package/test/package.json +12 -11
- package/test/src/lib/oidc/oidc.test.flow.d.ts +206 -6
- package/twilio/package.json +8 -8
- package/zoho/package.json +10 -10
package/test/index.esm.js
CHANGED
|
@@ -13,7 +13,7 @@ import { HttpsError } from 'firebase-functions/https';
|
|
|
13
13
|
import { BaseError } from 'make-error';
|
|
14
14
|
import request from 'supertest';
|
|
15
15
|
import { randomBytes, createHash } from 'node:crypto';
|
|
16
|
-
import { OidcClientService, JwksService, OidcAccountService } from '@dereekb/firebase-server/oidc';
|
|
16
|
+
import { OidcProviderConfigService, OidcClientService, JwksService, OidcAccountService } from '@dereekb/firebase-server/oidc';
|
|
17
17
|
|
|
18
18
|
function _assert_this_initialized$9(self) {
|
|
19
19
|
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
@@ -118,7 +118,7 @@ function _object_spread$6(target) {
|
|
|
118
118
|
}
|
|
119
119
|
return target;
|
|
120
120
|
}
|
|
121
|
-
function ownKeys$
|
|
121
|
+
function ownKeys$4(object, enumerableOnly) {
|
|
122
122
|
var keys = Object.keys(object);
|
|
123
123
|
if (Object.getOwnPropertySymbols) {
|
|
124
124
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -126,11 +126,11 @@ function ownKeys$3(object, enumerableOnly) {
|
|
|
126
126
|
}
|
|
127
127
|
return keys;
|
|
128
128
|
}
|
|
129
|
-
function _object_spread_props$
|
|
129
|
+
function _object_spread_props$4(target, source) {
|
|
130
130
|
source = source != null ? source : {};
|
|
131
131
|
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
132
132
|
else {
|
|
133
|
-
ownKeys$
|
|
133
|
+
ownKeys$4(Object(source)).forEach(function(key) {
|
|
134
134
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
135
135
|
});
|
|
136
136
|
}
|
|
@@ -482,7 +482,7 @@ function _type_of$9(obj) {
|
|
|
482
482
|
value: function callAuthBlockingFunction(input) {
|
|
483
483
|
var fn = input.fn, userRecord = input.userRecord, eventType = input.eventType, eventOverride = input.eventOverride, _input_skipJsonConversion = input.skipJsonConversion, skipJsonConversion = _input_skipJsonConversion === void 0 ? false : _input_skipJsonConversion;
|
|
484
484
|
var timestamp = new Date().toISOString();
|
|
485
|
-
var event = _object_spread_props$
|
|
485
|
+
var event = _object_spread_props$4(_object_spread$6({
|
|
486
486
|
ipAddress: '127.0.0.1',
|
|
487
487
|
userAgent: 'testing',
|
|
488
488
|
eventId: '0',
|
|
@@ -583,7 +583,7 @@ function _type_of$9(obj) {
|
|
|
583
583
|
}
|
|
584
584
|
return [
|
|
585
585
|
4,
|
|
586
|
-
auth.createUser(_object_spread$6(_object_spread_props$
|
|
586
|
+
auth.createUser(_object_spread$6(_object_spread_props$4(_object_spread$6({
|
|
587
587
|
uid: uid,
|
|
588
588
|
displayName: 'Test Person'
|
|
589
589
|
}, details), {
|
|
@@ -787,7 +787,7 @@ function _type_of$9(obj) {
|
|
|
787
787
|
var _ref;
|
|
788
788
|
var _decoded_claims;
|
|
789
789
|
var decoded = decode(token);
|
|
790
|
-
var decodedToken = _object_spread_props$
|
|
790
|
+
var decodedToken = _object_spread_props$4(_object_spread$6({}, decoded, decoded.claims), {
|
|
791
791
|
auth_time: decoded.iat,
|
|
792
792
|
firebase: (_ref = (_decoded_claims = decoded.claims) === null || _decoded_claims === void 0 ? void 0 : _decoded_claims.firebase) !== null && _ref !== void 0 ? _ref : {}
|
|
793
793
|
});
|
|
@@ -2498,7 +2498,7 @@ function _object_spread$4(target) {
|
|
|
2498
2498
|
}
|
|
2499
2499
|
return target;
|
|
2500
2500
|
}
|
|
2501
|
-
function ownKeys$
|
|
2501
|
+
function ownKeys$3(object, enumerableOnly) {
|
|
2502
2502
|
var keys = Object.keys(object);
|
|
2503
2503
|
if (Object.getOwnPropertySymbols) {
|
|
2504
2504
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -2506,11 +2506,11 @@ function ownKeys$2(object, enumerableOnly) {
|
|
|
2506
2506
|
}
|
|
2507
2507
|
return keys;
|
|
2508
2508
|
}
|
|
2509
|
-
function _object_spread_props$
|
|
2509
|
+
function _object_spread_props$3(target, source) {
|
|
2510
2510
|
source = source != null ? source : {};
|
|
2511
2511
|
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
2512
2512
|
else {
|
|
2513
|
-
ownKeys$
|
|
2513
|
+
ownKeys$3(Object(source)).forEach(function(key) {
|
|
2514
2514
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
2515
2515
|
});
|
|
2516
2516
|
}
|
|
@@ -2640,7 +2640,7 @@ function _ts_generator$5(thisArg, body) {
|
|
|
2640
2640
|
return _async_to_generator$5(function() {
|
|
2641
2641
|
var _ref, request;
|
|
2642
2642
|
return _ts_generator$5(this, function(_state) {
|
|
2643
|
-
request = _object_spread_props$
|
|
2643
|
+
request = _object_spread_props$3(_object_spread$4({}, context), {
|
|
2644
2644
|
data: data,
|
|
2645
2645
|
// NOTE: These will typically not be used/available as they are express.js properties that are not available or useful to the handlers
|
|
2646
2646
|
rawRequest: (_ref = context === null || context === void 0 ? void 0 : context.rawRequest) !== null && _ref !== void 0 ? _ref : {},
|
|
@@ -2823,7 +2823,7 @@ function _object_spread$3(target) {
|
|
|
2823
2823
|
}
|
|
2824
2824
|
return target;
|
|
2825
2825
|
}
|
|
2826
|
-
function ownKeys$
|
|
2826
|
+
function ownKeys$2(object, enumerableOnly) {
|
|
2827
2827
|
var keys = Object.keys(object);
|
|
2828
2828
|
if (Object.getOwnPropertySymbols) {
|
|
2829
2829
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -2831,11 +2831,11 @@ function ownKeys$1(object, enumerableOnly) {
|
|
|
2831
2831
|
}
|
|
2832
2832
|
return keys;
|
|
2833
2833
|
}
|
|
2834
|
-
function _object_spread_props$
|
|
2834
|
+
function _object_spread_props$2(target, source) {
|
|
2835
2835
|
source = source != null ? source : {};
|
|
2836
2836
|
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
2837
2837
|
else {
|
|
2838
|
-
ownKeys$
|
|
2838
|
+
ownKeys$2(Object(source)).forEach(function(key) {
|
|
2839
2839
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
2840
2840
|
});
|
|
2841
2841
|
}
|
|
@@ -3129,7 +3129,7 @@ var functionsInitialized = false;
|
|
|
3129
3129
|
*/ var firebaseAdminFunctionTestBuilder = testContextBuilder({
|
|
3130
3130
|
buildConfig: function buildConfig(input) {
|
|
3131
3131
|
var _ref;
|
|
3132
|
-
var config = _object_spread_props$
|
|
3132
|
+
var config = _object_spread_props$2(_object_spread$3({}, input), {
|
|
3133
3133
|
useFunctionSingletonContext: (_ref = input === null || input === void 0 ? void 0 : input.useFunctionSingletonContext) !== null && _ref !== void 0 ? _ref : DEFAULT_FIREBASE_ADMIN_FUNCTION_TEST_USE_FUNCTION_SINGLETON_CONTEXT
|
|
3134
3134
|
});
|
|
3135
3135
|
return config;
|
|
@@ -3390,7 +3390,7 @@ function _object_spread$2(target) {
|
|
|
3390
3390
|
}
|
|
3391
3391
|
return target;
|
|
3392
3392
|
}
|
|
3393
|
-
function ownKeys(object, enumerableOnly) {
|
|
3393
|
+
function ownKeys$1(object, enumerableOnly) {
|
|
3394
3394
|
var keys = Object.keys(object);
|
|
3395
3395
|
if (Object.getOwnPropertySymbols) {
|
|
3396
3396
|
var symbols = Object.getOwnPropertySymbols(object);
|
|
@@ -3398,11 +3398,11 @@ function ownKeys(object, enumerableOnly) {
|
|
|
3398
3398
|
}
|
|
3399
3399
|
return keys;
|
|
3400
3400
|
}
|
|
3401
|
-
function _object_spread_props(target, source) {
|
|
3401
|
+
function _object_spread_props$1(target, source) {
|
|
3402
3402
|
source = source != null ? source : {};
|
|
3403
3403
|
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
3404
3404
|
else {
|
|
3405
|
-
ownKeys(Object(source)).forEach(function(key) {
|
|
3405
|
+
ownKeys$1(Object(source)).forEach(function(key) {
|
|
3406
3406
|
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
3407
3407
|
});
|
|
3408
3408
|
}
|
|
@@ -3716,7 +3716,7 @@ function _unsupported_iterable_to_array$1(o, minLen) {
|
|
|
3716
3716
|
switch(_state.label){
|
|
3717
3717
|
case 0:
|
|
3718
3718
|
additionalProviders = (_makeProviders = makeProviders(f.instance)) !== null && _makeProviders !== void 0 ? _makeProviders : [];
|
|
3719
|
-
rootModule = buildNestServerRootModule(_object_spread_props(_object_spread$2({}, serverInstanceConfig), {
|
|
3719
|
+
rootModule = buildNestServerRootModule(_object_spread_props$1(_object_spread$2({}, serverInstanceConfig), {
|
|
3720
3720
|
modules: _to_consumable_array$1(asArray(nestModules)).concat(_to_consumable_array$1(asArray(serverInstanceConfig === null || serverInstanceConfig === void 0 ? void 0 : serverInstanceConfig.modules))),
|
|
3721
3721
|
firebaseAppGetter: config.injectFirebaseServerAppTokenProvider ? asGetter(f.instance.app) : undefined,
|
|
3722
3722
|
providers: additionalProviders,
|
|
@@ -4602,6 +4602,24 @@ function _object_spread(target) {
|
|
|
4602
4602
|
}
|
|
4603
4603
|
return target;
|
|
4604
4604
|
}
|
|
4605
|
+
function ownKeys(object, enumerableOnly) {
|
|
4606
|
+
var keys = Object.keys(object);
|
|
4607
|
+
if (Object.getOwnPropertySymbols) {
|
|
4608
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
4609
|
+
keys.push.apply(keys, symbols);
|
|
4610
|
+
}
|
|
4611
|
+
return keys;
|
|
4612
|
+
}
|
|
4613
|
+
function _object_spread_props(target, source) {
|
|
4614
|
+
source = source != null ? source : {};
|
|
4615
|
+
if (Object.getOwnPropertyDescriptors) Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
4616
|
+
else {
|
|
4617
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
4618
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
4619
|
+
});
|
|
4620
|
+
}
|
|
4621
|
+
return target;
|
|
4622
|
+
}
|
|
4605
4623
|
function _sliced_to_array(arr, i) {
|
|
4606
4624
|
return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
|
|
4607
4625
|
}
|
|
@@ -4767,6 +4785,16 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4767
4785
|
var url = location.startsWith('/') ? new URL(location, 'http://localhost') : new URL(location);
|
|
4768
4786
|
return url.searchParams.get('uid');
|
|
4769
4787
|
}
|
|
4788
|
+
/**
|
|
4789
|
+
* Whether a redirect response points at the given interaction frontend URL (the login or consent screen).
|
|
4790
|
+
*
|
|
4791
|
+
* @param res - Supertest response to inspect.
|
|
4792
|
+
* @param frontendUrl - The frontend URL to match, without its query string.
|
|
4793
|
+
* @returns True when the response's `Location` header starts with `frontendUrl`.
|
|
4794
|
+
*/ function isRedirectTo(res, frontendUrl) {
|
|
4795
|
+
var location = res.headers['location'];
|
|
4796
|
+
return location != null && location.startsWith(frontendUrl);
|
|
4797
|
+
}
|
|
4770
4798
|
/**
|
|
4771
4799
|
* Cookie jar helpers for the OAuth flow.
|
|
4772
4800
|
*
|
|
@@ -4859,29 +4887,39 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4859
4887
|
})();
|
|
4860
4888
|
}
|
|
4861
4889
|
/**
|
|
4862
|
-
* Performs the
|
|
4890
|
+
* Performs the OAuth authorization code flow with PKCE, up to the configured
|
|
4891
|
+
* {@link OAuthTestFlowConfig.stopAtStage}.
|
|
4863
4892
|
*
|
|
4864
4893
|
* Steps: create client → PKCE → auth redirect → login → consent → code exchange → token
|
|
4865
4894
|
*
|
|
4866
|
-
*
|
|
4895
|
+
* Stopping early is how a test asserts on an intermediate the completed flow discards — the raw
|
|
4896
|
+
* `/oidc/auth` response, the consent screen's offered `scopes`, or a callback that came back carrying
|
|
4897
|
+
* an `error` instead of a `code`. A stage before `'token'` never exchanges the code, so it never
|
|
4898
|
+
* throws on such a callback; the caller asserts on {@link OAuthTestFlowResult.callbackUrl} instead,
|
|
4899
|
+
* and can run its own `/oidc/token` request with {@link OAuthTestFlowResult.codeVerifier} and the
|
|
4900
|
+
* session's cookie header.
|
|
4901
|
+
*
|
|
4902
|
+
* @param input - Bag of services and overrides needed to drive the flow.
|
|
4867
4903
|
* @param input.server - HTTP server returned by `nestApp.getHttpServer()` against which all supertest requests are issued.
|
|
4868
4904
|
* @param input.oidcClientService - Service used to create the OAuth client whose credentials drive the flow.
|
|
4869
4905
|
* @param input.nestApp - Initialized NestJS application; used to resolve {@link OidcAccountService} for project-id-derived ID tokens and default scopes.
|
|
4870
|
-
* @param input.uid - Firebase user ID for whom the test ID token is minted
|
|
4871
|
-
* @param input.config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles).
|
|
4872
|
-
* @returns The
|
|
4873
|
-
* @throws {Error} When the token exchange step fails (the response body and status are included in the message).
|
|
4874
|
-
*/ function
|
|
4906
|
+
* @param input.uid - Firebase user ID for whom the test ID token is minted; required for any stage past `'auth'`.
|
|
4907
|
+
* @param input.config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles, stop stage).
|
|
4908
|
+
* @returns The intermediates the flow produced, plus the tokens when it ran to the `'token'` stage.
|
|
4909
|
+
* @throws {Error} When a stage past `'auth'` is requested without a `uid`, or when the token exchange step fails (the response body and status are included in the message).
|
|
4910
|
+
*/ function performOAuthFlow(input) {
|
|
4875
4911
|
return _async_to_generator$1(function() {
|
|
4876
|
-
var _ref, _ref1, _ref2, server, oidcClientService, nestApp, uid, config,
|
|
4912
|
+
var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _config_session, _config_session1, server, oidcClientService, nestApp, uid, config, cookieJar, collectCookies, cookieHeader, stage, redirectUri, clientName, tokenEndpointAuthMethod, providerProfiles, scopes, client, _ref6, client_id, client_secret, client_id1, client_secret1, codeVerifier, codeChallenge, authRes, consentRedirectUrl, callbackUrl, tokenBody, idToken, providerConfigService, interactionRes, loginUid, loginRes, resumeAfterLoginPath, callbackRedirectRes, consentUid, consentRes, resumeAfterConsentPath, authorizationCode, tokenRes;
|
|
4877
4913
|
return _ts_generator$1(this, function(_state) {
|
|
4878
4914
|
switch(_state.label){
|
|
4879
4915
|
case 0:
|
|
4880
4916
|
server = input.server, oidcClientService = input.oidcClientService, nestApp = input.nestApp, uid = input.uid, config = input.config;
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4917
|
+
cookieJar = (_ref = config === null || config === void 0 ? void 0 : (_config_session = config.session) === null || _config_session === void 0 ? void 0 : _config_session.cookieJar) !== null && _ref !== void 0 ? _ref : createCookieJar();
|
|
4918
|
+
collectCookies = cookieJar.collectCookies, cookieHeader = cookieJar.cookieHeader;
|
|
4919
|
+
stage = (_ref1 = config === null || config === void 0 ? void 0 : config.stopAtStage) !== null && _ref1 !== void 0 ? _ref1 : 'token';
|
|
4920
|
+
redirectUri = (_ref2 = (_ref3 = config === null || config === void 0 ? void 0 : (_config_session1 = config.session) === null || _config_session1 === void 0 ? void 0 : _config_session1.client.redirectUri) !== null && _ref3 !== void 0 ? _ref3 : config === null || config === void 0 ? void 0 : config.redirectUri) !== null && _ref2 !== void 0 ? _ref2 : 'https://example.com/callback';
|
|
4921
|
+
clientName = (_ref4 = config === null || config === void 0 ? void 0 : config.clientName) !== null && _ref4 !== void 0 ? _ref4 : 'test-oauth-context';
|
|
4922
|
+
tokenEndpointAuthMethod = (_ref5 = config === null || config === void 0 ? void 0 : config.tokenEndpointAuthMethod) !== null && _ref5 !== void 0 ? _ref5 : 'client_secret_post';
|
|
4885
4923
|
providerProfiles = config === null || config === void 0 ? void 0 : config.providerProfiles;
|
|
4886
4924
|
return [
|
|
4887
4925
|
4,
|
|
@@ -4889,6 +4927,16 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4889
4927
|
];
|
|
4890
4928
|
case 1:
|
|
4891
4929
|
scopes = _state.sent();
|
|
4930
|
+
if (!(config === null || config === void 0 ? void 0 : config.session)) return [
|
|
4931
|
+
3,
|
|
4932
|
+
2
|
|
4933
|
+
];
|
|
4934
|
+
client = config.session.client;
|
|
4935
|
+
return [
|
|
4936
|
+
3,
|
|
4937
|
+
4
|
|
4938
|
+
];
|
|
4939
|
+
case 2:
|
|
4892
4940
|
return [
|
|
4893
4941
|
4,
|
|
4894
4942
|
oidcClientService.createClient(_object_spread({
|
|
@@ -4901,15 +4949,23 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4901
4949
|
dbx_provider_profiles: _to_consumable_array(providerProfiles)
|
|
4902
4950
|
}))
|
|
4903
4951
|
];
|
|
4904
|
-
case
|
|
4905
|
-
|
|
4952
|
+
case 3:
|
|
4953
|
+
_ref6 = _state.sent(), client_id = _ref6.client_id, client_secret = _ref6.client_secret;
|
|
4954
|
+
client = {
|
|
4955
|
+
client_id: client_id,
|
|
4956
|
+
client_secret: client_secret,
|
|
4957
|
+
redirectUri: redirectUri
|
|
4958
|
+
};
|
|
4959
|
+
_state.label = 4;
|
|
4960
|
+
case 4:
|
|
4961
|
+
client_id1 = client.client_id, client_secret1 = client.client_secret;
|
|
4906
4962
|
// 2. Generate PKCE code_verifier and code_challenge
|
|
4907
4963
|
codeVerifier = randomBytes(32).toString('base64url');
|
|
4908
4964
|
codeChallenge = createHash('sha256').update(codeVerifier).digest('base64url');
|
|
4909
4965
|
return [
|
|
4910
4966
|
4,
|
|
4911
|
-
request(server).get('/oidc/auth').query({
|
|
4912
|
-
client_id:
|
|
4967
|
+
request(server).get('/oidc/auth').query(_object_spread({
|
|
4968
|
+
client_id: client_id1,
|
|
4913
4969
|
redirect_uri: redirectUri,
|
|
4914
4970
|
response_type: 'code',
|
|
4915
4971
|
scope: scopes,
|
|
@@ -4917,25 +4973,42 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4917
4973
|
code_challenge_method: 'S256',
|
|
4918
4974
|
state: 'test-state',
|
|
4919
4975
|
nonce: 'test-nonce'
|
|
4920
|
-
}
|
|
4976
|
+
}, (config === null || config === void 0 ? void 0 : config.prompt) == null ? {} : {
|
|
4977
|
+
prompt: config.prompt
|
|
4978
|
+
}, (config === null || config === void 0 ? void 0 : config.resource) == null ? {} : {
|
|
4979
|
+
resource: config.resource
|
|
4980
|
+
}, config === null || config === void 0 ? void 0 : config.extraAuthParams)).redirects(0)
|
|
4921
4981
|
];
|
|
4922
|
-
case
|
|
4982
|
+
case 5:
|
|
4923
4983
|
authRes = _state.sent();
|
|
4924
4984
|
collectCookies(authRes);
|
|
4925
|
-
|
|
4985
|
+
if (!(stage !== 'auth')) return [
|
|
4986
|
+
3,
|
|
4987
|
+
14
|
|
4988
|
+
];
|
|
4989
|
+
if (uid == null) {
|
|
4990
|
+
throw new Error('performOAuthFlow requires a uid to reach the "'.concat(stage, '" stage (only the "auth" stage skips the login interaction).'));
|
|
4991
|
+
}
|
|
4926
4992
|
return [
|
|
4927
4993
|
4,
|
|
4928
4994
|
createTestIdToken(nestApp, uid)
|
|
4929
4995
|
];
|
|
4930
|
-
case
|
|
4996
|
+
case 6:
|
|
4931
4997
|
idToken = _state.sent();
|
|
4998
|
+
providerConfigService = nestApp.get(OidcProviderConfigService);
|
|
4999
|
+
interactionRes = authRes;
|
|
5000
|
+
if (!isRedirectTo(authRes, providerConfigService.appLoginUrl)) return [
|
|
5001
|
+
3,
|
|
5002
|
+
9
|
|
5003
|
+
];
|
|
5004
|
+
loginUid = extractInteractionUid(authRes);
|
|
4932
5005
|
return [
|
|
4933
5006
|
4,
|
|
4934
5007
|
request(server).post("/interaction/".concat(loginUid, "/login")).set('Cookie', cookieHeader()).send({
|
|
4935
5008
|
idToken: idToken
|
|
4936
5009
|
})
|
|
4937
5010
|
];
|
|
4938
|
-
case
|
|
5011
|
+
case 7:
|
|
4939
5012
|
loginRes = _state.sent();
|
|
4940
5013
|
// 5. Resume after login → consent redirect
|
|
4941
5014
|
resumeAfterLoginPath = new URL(loginRes.body.redirectTo).pathname + new URL(loginRes.body.redirectTo).search;
|
|
@@ -4943,18 +5016,29 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4943
5016
|
4,
|
|
4944
5017
|
request(server).get(resumeAfterLoginPath).set('Cookie', cookieHeader()).redirects(0)
|
|
4945
5018
|
];
|
|
4946
|
-
case
|
|
4947
|
-
|
|
4948
|
-
collectCookies(
|
|
4949
|
-
|
|
5019
|
+
case 8:
|
|
5020
|
+
interactionRes = _state.sent();
|
|
5021
|
+
collectCookies(interactionRes);
|
|
5022
|
+
_state.label = 9;
|
|
5023
|
+
case 9:
|
|
5024
|
+
// 6. Approve consent — unless nothing needed consenting and the provider went straight to the callback
|
|
5025
|
+
callbackRedirectRes = interactionRes;
|
|
5026
|
+
if (!isRedirectTo(interactionRes, providerConfigService.appConsentUrl)) return [
|
|
5027
|
+
3,
|
|
5028
|
+
12
|
|
5029
|
+
];
|
|
5030
|
+
consentRedirectUrl = new URL(interactionRes.headers['location'], 'http://localhost');
|
|
5031
|
+
consentUid = extractInteractionUid(interactionRes);
|
|
4950
5032
|
return [
|
|
4951
5033
|
4,
|
|
4952
|
-
request(server).post("/interaction/".concat(consentUid, "/consent")).set('Cookie', cookieHeader()).send({
|
|
5034
|
+
request(server).post("/interaction/".concat(consentUid, "/consent")).set('Cookie', cookieHeader()).send(_object_spread({
|
|
4953
5035
|
idToken: idToken,
|
|
4954
5036
|
approved: true
|
|
4955
|
-
})
|
|
5037
|
+
}, (config === null || config === void 0 ? void 0 : config.grantedOIDCScopes) == null ? {} : {
|
|
5038
|
+
grantedOIDCScopes: _to_consumable_array(config.grantedOIDCScopes)
|
|
5039
|
+
}))
|
|
4956
5040
|
];
|
|
4957
|
-
case
|
|
5041
|
+
case 10:
|
|
4958
5042
|
consentRes = _state.sent();
|
|
4959
5043
|
// 7. Follow resume redirect → callback with authorization code
|
|
4960
5044
|
resumeAfterConsentPath = new URL(consentRes.body.redirectTo).pathname + new URL(consentRes.body.redirectTo).search;
|
|
@@ -4962,49 +5046,112 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
4962
5046
|
4,
|
|
4963
5047
|
request(server).get(resumeAfterConsentPath).set('Cookie', cookieHeader()).redirects(0)
|
|
4964
5048
|
];
|
|
4965
|
-
case
|
|
5049
|
+
case 11:
|
|
4966
5050
|
callbackRedirectRes = _state.sent();
|
|
4967
5051
|
collectCookies(callbackRedirectRes);
|
|
5052
|
+
_state.label = 12;
|
|
5053
|
+
case 12:
|
|
4968
5054
|
callbackUrl = new URL(callbackRedirectRes.headers['location']);
|
|
5055
|
+
if (!(stage !== 'callback')) return [
|
|
5056
|
+
3,
|
|
5057
|
+
14
|
|
5058
|
+
];
|
|
5059
|
+
// 8. Exchange authorization code for tokens
|
|
4969
5060
|
authorizationCode = callbackUrl.searchParams.get('code');
|
|
4970
5061
|
return [
|
|
4971
5062
|
4,
|
|
4972
|
-
request(server).post('/oidc/token').set('Cookie', cookieHeader()).type('form').send({
|
|
5063
|
+
request(server).post('/oidc/token').set('Cookie', cookieHeader()).type('form').send(_object_spread({
|
|
4973
5064
|
grant_type: 'authorization_code',
|
|
4974
5065
|
code: authorizationCode,
|
|
4975
5066
|
redirect_uri: redirectUri,
|
|
4976
|
-
client_id:
|
|
4977
|
-
client_secret:
|
|
5067
|
+
client_id: client_id1,
|
|
5068
|
+
client_secret: client_secret1,
|
|
4978
5069
|
code_verifier: codeVerifier
|
|
4979
|
-
})
|
|
5070
|
+
}, (config === null || config === void 0 ? void 0 : config.resource) == null ? {} : {
|
|
5071
|
+
resource: config.resource
|
|
5072
|
+
}))
|
|
4980
5073
|
];
|
|
4981
|
-
case
|
|
5074
|
+
case 13:
|
|
4982
5075
|
tokenRes = _state.sent();
|
|
4983
5076
|
if (!tokenRes.body.access_token) {
|
|
4984
5077
|
throw new Error("OAuth token exchange failed (status ".concat(tokenRes.status, "): ").concat(JSON.stringify(tokenRes.body)));
|
|
4985
5078
|
}
|
|
5079
|
+
tokenBody = tokenRes.body;
|
|
5080
|
+
_state.label = 14;
|
|
5081
|
+
case 14:
|
|
4986
5082
|
return [
|
|
4987
5083
|
2,
|
|
4988
5084
|
{
|
|
4989
|
-
|
|
4990
|
-
|
|
5085
|
+
stage: stage,
|
|
5086
|
+
authResponse: authRes,
|
|
5087
|
+
codeVerifier: codeVerifier,
|
|
5088
|
+
consentRedirectUrl: consentRedirectUrl,
|
|
5089
|
+
callbackUrl: callbackUrl,
|
|
5090
|
+
accessToken: tokenBody === null || tokenBody === void 0 ? void 0 : tokenBody.access_token,
|
|
5091
|
+
idToken: tokenBody === null || tokenBody === void 0 ? void 0 : tokenBody.id_token,
|
|
5092
|
+
tokenType: tokenBody === null || tokenBody === void 0 ? void 0 : tokenBody.token_type,
|
|
5093
|
+
scope: tokenBody === null || tokenBody === void 0 ? void 0 : tokenBody.scope,
|
|
5094
|
+
session: {
|
|
5095
|
+
client: client,
|
|
5096
|
+
cookieJar: cookieJar
|
|
5097
|
+
}
|
|
4991
5098
|
}
|
|
4992
5099
|
];
|
|
4993
5100
|
}
|
|
4994
5101
|
});
|
|
4995
5102
|
})();
|
|
4996
5103
|
}
|
|
5104
|
+
/**
|
|
5105
|
+
* Performs the full OAuth authorization code flow with PKCE and returns tokens.
|
|
5106
|
+
*
|
|
5107
|
+
* Steps: create client → PKCE → auth redirect → login → consent → code exchange → token
|
|
5108
|
+
*
|
|
5109
|
+
* Always runs to the `'token'` stage — {@link OAuthTestFlowConfig.stopAtStage} is ignored here, since
|
|
5110
|
+
* this function's result guarantees tokens. Use {@link performOAuthFlow} to stop earlier.
|
|
5111
|
+
*
|
|
5112
|
+
* @param input - Bag of services and overrides needed to drive the flow end-to-end.
|
|
5113
|
+
* @param input.server - HTTP server returned by `nestApp.getHttpServer()` against which all supertest requests are issued.
|
|
5114
|
+
* @param input.oidcClientService - Service used to create the OAuth client whose credentials drive the flow.
|
|
5115
|
+
* @param input.nestApp - Initialized NestJS application; used to resolve {@link OidcAccountService} for project-id-derived ID tokens and default scopes.
|
|
5116
|
+
* @param input.uid - Firebase user ID for whom the test ID token is minted and the OAuth flow is authorized.
|
|
5117
|
+
* @param input.config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles).
|
|
5118
|
+
* @returns The exchanged access token and ID token from the OIDC `/token` endpoint, plus the flow's intermediates.
|
|
5119
|
+
* @throws {Error} When the token exchange step fails (the response body and status are included in the message).
|
|
5120
|
+
*/ function performFullOAuthFlow(input) {
|
|
5121
|
+
return _async_to_generator$1(function() {
|
|
5122
|
+
var result;
|
|
5123
|
+
return _ts_generator$1(this, function(_state) {
|
|
5124
|
+
switch(_state.label){
|
|
5125
|
+
case 0:
|
|
5126
|
+
return [
|
|
5127
|
+
4,
|
|
5128
|
+
performOAuthFlow(_object_spread_props(_object_spread({}, input), {
|
|
5129
|
+
config: _object_spread_props(_object_spread({}, input.config), {
|
|
5130
|
+
stopAtStage: 'token'
|
|
5131
|
+
})
|
|
5132
|
+
}))
|
|
5133
|
+
];
|
|
5134
|
+
case 1:
|
|
5135
|
+
result = _state.sent();
|
|
5136
|
+
return [
|
|
5137
|
+
2,
|
|
5138
|
+
result
|
|
5139
|
+
];
|
|
5140
|
+
}
|
|
5141
|
+
});
|
|
5142
|
+
})();
|
|
5143
|
+
}
|
|
4997
5144
|
/**
|
|
4998
5145
|
* Higher-level helper that resolves OIDC services from the NestJS DI container,
|
|
4999
|
-
* rotates JWKS keys, and then performs the
|
|
5146
|
+
* rotates JWKS keys, and then performs the OAuth flow up to {@link OAuthTestFlowConfig.stopAtStage}.
|
|
5000
5147
|
*
|
|
5001
5148
|
* This avoids callers needing to import from `@dereekb/firebase-server/oidc` directly.
|
|
5002
5149
|
*
|
|
5003
5150
|
* @param nestApp - Initialized NestJS application from which {@link JwksService} and {@link OidcClientService} are resolved.
|
|
5004
|
-
* @param uid - Firebase user ID for whom the OAuth flow is authorized.
|
|
5005
|
-
* @param config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles).
|
|
5006
|
-
* @returns The
|
|
5007
|
-
*/ function
|
|
5151
|
+
* @param uid - Firebase user ID for whom the OAuth flow is authorized; only omittable for the `'auth'` stage.
|
|
5152
|
+
* @param config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles, stop stage).
|
|
5153
|
+
* @returns The result of {@link performOAuthFlow}.
|
|
5154
|
+
*/ function setupAndPerformOAuthFlow(nestApp, uid, config) {
|
|
5008
5155
|
return _async_to_generator$1(function() {
|
|
5009
5156
|
var jwksService, oidcClientService, server;
|
|
5010
5157
|
return _ts_generator$1(this, function(_state) {
|
|
@@ -5023,7 +5170,7 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
5023
5170
|
server = nestApp.getHttpServer();
|
|
5024
5171
|
return [
|
|
5025
5172
|
2,
|
|
5026
|
-
|
|
5173
|
+
performOAuthFlow({
|
|
5027
5174
|
server: server,
|
|
5028
5175
|
oidcClientService: oidcClientService,
|
|
5029
5176
|
nestApp: nestApp,
|
|
@@ -5035,6 +5182,38 @@ function _unsupported_iterable_to_array(o, minLen) {
|
|
|
5035
5182
|
});
|
|
5036
5183
|
})();
|
|
5037
5184
|
}
|
|
5185
|
+
/**
|
|
5186
|
+
* Higher-level helper that resolves OIDC services from the NestJS DI container,
|
|
5187
|
+
* rotates JWKS keys, and then performs the full OAuth flow.
|
|
5188
|
+
*
|
|
5189
|
+
* This avoids callers needing to import from `@dereekb/firebase-server/oidc` directly.
|
|
5190
|
+
*
|
|
5191
|
+
* @param nestApp - Initialized NestJS application from which {@link JwksService} and {@link OidcClientService} are resolved.
|
|
5192
|
+
* @param uid - Firebase user ID for whom the OAuth flow is authorized.
|
|
5193
|
+
* @param config - Optional flow overrides (scopes, redirect URI, client name, token endpoint auth method, provider profiles).
|
|
5194
|
+
* @returns The exchanged access token and ID token from {@link performFullOAuthFlow}.
|
|
5195
|
+
*/ function setupAndPerformFullOAuthFlow(nestApp, uid, config) {
|
|
5196
|
+
return _async_to_generator$1(function() {
|
|
5197
|
+
var result;
|
|
5198
|
+
return _ts_generator$1(this, function(_state) {
|
|
5199
|
+
switch(_state.label){
|
|
5200
|
+
case 0:
|
|
5201
|
+
return [
|
|
5202
|
+
4,
|
|
5203
|
+
setupAndPerformOAuthFlow(nestApp, uid, _object_spread_props(_object_spread({}, config), {
|
|
5204
|
+
stopAtStage: 'token'
|
|
5205
|
+
}))
|
|
5206
|
+
];
|
|
5207
|
+
case 1:
|
|
5208
|
+
result = _state.sent();
|
|
5209
|
+
return [
|
|
5210
|
+
2,
|
|
5211
|
+
result
|
|
5212
|
+
];
|
|
5213
|
+
}
|
|
5214
|
+
});
|
|
5215
|
+
})();
|
|
5216
|
+
}
|
|
5038
5217
|
|
|
5039
5218
|
function _assert_this_initialized(self) {
|
|
5040
5219
|
if (self === void 0) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
|
@@ -5425,7 +5604,9 @@ function _type_of(obj) {
|
|
|
5425
5604
|
"makeFixture",
|
|
5426
5605
|
"makeInstance"
|
|
5427
5606
|
]);
|
|
5428
|
-
var flowConfig =
|
|
5607
|
+
var flowConfig = Object.values(flowConfigOverrides).some(function(value) {
|
|
5608
|
+
return value != null;
|
|
5609
|
+
}) ? flowConfigOverrides : undefined;
|
|
5429
5610
|
return function(params, buildTests) {
|
|
5430
5611
|
var f = params.f, u = params.u;
|
|
5431
5612
|
describe('(oauth)', function() {
|
|
@@ -5484,4 +5665,4 @@ function _type_of(obj) {
|
|
|
5484
5665
|
* Uses @google-cloud/storage
|
|
5485
5666
|
*/ var dbxComponentsAdminTestWithMockItemStorage = testWithMockItemStorageFixture()(adminFirebaseStorageFactory);
|
|
5486
5667
|
|
|
5487
|
-
export { AUTHORIZED_USER_RANDOM_EMAIL_FACTORY, AUTHORIZED_USER_RANDOM_PHONE_NUMBER_FACTORY, AbstractFirebaseAdminTestContextInstanceChild, AuthorizedUserTestContextFixture, AuthorizedUserTestContextInstance, CallableRequestTestMultipleFixtureSuffix, DEFAULT_FIREBASE_ADMIN_FUNCTION_TEST_USE_FUNCTION_SINGLETON_CONTEXT, ExpectedHttpErrorWithSpecificServerErrorCode, FIREBASE_ADMIN_NEST_TEST_SERVER_INSTANCE_CONFIG_TOKEN, FirebaseAdminFunctionNestRootModule, FirebaseAdminFunctionNestTestContextFixture, FirebaseAdminFunctionNestTestContextInstance, FirebaseAdminFunctionTestContextFixture, FirebaseAdminFunctionTestContextInstance, FirebaseAdminNestTestContextFixture, FirebaseAdminNestTestContextInstance, FirebaseAdminTestContextFixture, FirebaseAdminTestContextInstance, GoogleCloudTestFirebaseStorageContextFixture, GoogleCloudTestFirebaseStorageInstance, GoogleCloudTestFirestoreContextFixture, GoogleCloudTestFirestoreInstance, ModelTestContextFixture, ModelTestContextInstance, OAuthAuthorizedSuperTestFixture, OAuthAuthorizedSuperTestInstance, adminFirebaseStorageFactory, adminFirestoreFactory, applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv, authorizedUserContext, authorizedUserContextFactory, callableRequestTest, cloudFunctionTest, createEncodedTestFirestoreTokenForUserRecord, createTestFirestoreTokenForUserRecord, createTestFunctionContextAuthData, createTestFunctionContextOptions, dbxComponentsAdminTestWithMockItemCollection, dbxComponentsAdminTestWithMockItemStorage, decodeEncodedCreateCustomTokenResult, describeCallableRequestTest, describeCloudFunctionTest, describeFirestoreTest, expectFailAssertHttpErrorServerErrorCode, firebaseAdminFirestoreContextFixture, firebaseAdminFirestoreContextWithFixture, firebaseAdminFunctionNestContextFactory, firebaseAdminFunctionNestContextFixture, firebaseAdminFunctionNestContextWithFixture, firebaseAdminFunctionTestBuilder, firebaseAdminFunctionTestContextFactory, firebaseAdminNestContextFactory, firebaseAdminNestContextFixture, firebaseAdminNestContextWithFixture, firebaseAdminTestBuilder, firebaseAdminTestContextFactory, generateNewProjectId, getGCloudProjectId, getGCloudTestProjectId, googleCloudTestFirebaseStorageBuilder, googleCloudTestFirestoreBuilder, initFirebaseAdminTestEnvironment, initFirebaseServerAdminTestEnvironment, isAdminEnvironmentInitialized, isCallableRequestTestSingleConfig, isCloudFunctionTestSingleConfig, makeGoogleFirebaseStorageContext, makeGoogleFirestoreContext, modelTestContextFactory, oAuthAuthorizedSuperTestContextFactory, performFullOAuthFlow, rerollFirebaseAdminFunctionTestSingleton, rollNewGCloudProjectEnvironmentVariable, setDefaultFirebaseAdminFunctionTestUseFunctionSingleton, setupAndPerformFullOAuthFlow, setupFirebaseAdminFunctionTestSingleton, testFirestoreClaimsFromUserRecord, testUidFactory, wrapCallableRequestForNestTestsGetter, wrapCloudFunctionForNestTestsGetter };
|
|
5668
|
+
export { AUTHORIZED_USER_RANDOM_EMAIL_FACTORY, AUTHORIZED_USER_RANDOM_PHONE_NUMBER_FACTORY, AbstractFirebaseAdminTestContextInstanceChild, AuthorizedUserTestContextFixture, AuthorizedUserTestContextInstance, CallableRequestTestMultipleFixtureSuffix, DEFAULT_FIREBASE_ADMIN_FUNCTION_TEST_USE_FUNCTION_SINGLETON_CONTEXT, ExpectedHttpErrorWithSpecificServerErrorCode, FIREBASE_ADMIN_NEST_TEST_SERVER_INSTANCE_CONFIG_TOKEN, FirebaseAdminFunctionNestRootModule, FirebaseAdminFunctionNestTestContextFixture, FirebaseAdminFunctionNestTestContextInstance, FirebaseAdminFunctionTestContextFixture, FirebaseAdminFunctionTestContextInstance, FirebaseAdminNestTestContextFixture, FirebaseAdminNestTestContextInstance, FirebaseAdminTestContextFixture, FirebaseAdminTestContextInstance, GoogleCloudTestFirebaseStorageContextFixture, GoogleCloudTestFirebaseStorageInstance, GoogleCloudTestFirestoreContextFixture, GoogleCloudTestFirestoreInstance, ModelTestContextFixture, ModelTestContextInstance, OAuthAuthorizedSuperTestFixture, OAuthAuthorizedSuperTestInstance, adminFirebaseStorageFactory, adminFirestoreFactory, applyFirebaseGCloudTestProjectIdToFirebaseConfigEnv, authorizedUserContext, authorizedUserContextFactory, callableRequestTest, cloudFunctionTest, createEncodedTestFirestoreTokenForUserRecord, createTestFirestoreTokenForUserRecord, createTestFunctionContextAuthData, createTestFunctionContextOptions, dbxComponentsAdminTestWithMockItemCollection, dbxComponentsAdminTestWithMockItemStorage, decodeEncodedCreateCustomTokenResult, describeCallableRequestTest, describeCloudFunctionTest, describeFirestoreTest, expectFailAssertHttpErrorServerErrorCode, firebaseAdminFirestoreContextFixture, firebaseAdminFirestoreContextWithFixture, firebaseAdminFunctionNestContextFactory, firebaseAdminFunctionNestContextFixture, firebaseAdminFunctionNestContextWithFixture, firebaseAdminFunctionTestBuilder, firebaseAdminFunctionTestContextFactory, firebaseAdminNestContextFactory, firebaseAdminNestContextFixture, firebaseAdminNestContextWithFixture, firebaseAdminTestBuilder, firebaseAdminTestContextFactory, generateNewProjectId, getGCloudProjectId, getGCloudTestProjectId, googleCloudTestFirebaseStorageBuilder, googleCloudTestFirestoreBuilder, initFirebaseAdminTestEnvironment, initFirebaseServerAdminTestEnvironment, isAdminEnvironmentInitialized, isCallableRequestTestSingleConfig, isCloudFunctionTestSingleConfig, makeGoogleFirebaseStorageContext, makeGoogleFirestoreContext, modelTestContextFactory, oAuthAuthorizedSuperTestContextFactory, performFullOAuthFlow, performOAuthFlow, rerollFirebaseAdminFunctionTestSingleton, rollNewGCloudProjectEnvironmentVariable, setDefaultFirebaseAdminFunctionTestUseFunctionSingleton, setupAndPerformFullOAuthFlow, setupAndPerformOAuthFlow, setupFirebaseAdminFunctionTestSingleton, testFirestoreClaimsFromUserRecord, testUidFactory, wrapCallableRequestForNestTestsGetter, wrapCloudFunctionForNestTestsGetter };
|
package/test/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/firebase-server/test",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.4.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/analytics": "14.
|
|
8
|
-
"@dereekb/date": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/firebase-server": "14.
|
|
11
|
-
"@dereekb/firebase-server/oidc": "14.
|
|
12
|
-
"@dereekb/model": "14.
|
|
13
|
-
"@dereekb/nestjs": "14.
|
|
14
|
-
"@dereekb/
|
|
15
|
-
"@dereekb/
|
|
7
|
+
"@dereekb/analytics": "14.4.0",
|
|
8
|
+
"@dereekb/date": "14.4.0",
|
|
9
|
+
"@dereekb/firebase": "14.4.0",
|
|
10
|
+
"@dereekb/firebase-server": "14.4.0",
|
|
11
|
+
"@dereekb/firebase-server/oidc": "14.4.0",
|
|
12
|
+
"@dereekb/model": "14.4.0",
|
|
13
|
+
"@dereekb/nestjs": "14.4.0",
|
|
14
|
+
"@dereekb/oauth-resource": "14.4.0",
|
|
15
|
+
"@dereekb/rxjs": "14.4.0",
|
|
16
|
+
"@dereekb/util": "14.4.0",
|
|
16
17
|
"@google-cloud/firestore": "^7.11.6",
|
|
17
18
|
"@google-cloud/storage": "^7.22.0",
|
|
18
19
|
"@nestjs/common": "^12.0.1",
|
|
@@ -25,7 +26,7 @@
|
|
|
25
26
|
"supertest": "^7.2.2"
|
|
26
27
|
},
|
|
27
28
|
"devDependencies": {
|
|
28
|
-
"@dereekb/nestjs": "14.
|
|
29
|
+
"@dereekb/nestjs": "14.4.0"
|
|
29
30
|
},
|
|
30
31
|
"exports": {
|
|
31
32
|
"./package.json": "./package.json",
|