@dereekb/firebase 14.0.1 → 14.2.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.
@@ -1,7 +1,7 @@
1
- import { type Maybe } from '@dereekb/util';
1
+ import { type EmailAddress, type Maybe } from '@dereekb/util';
2
2
  import { type FirebaseAuthUserId } from '../../common';
3
- import { type UserExternalConnection, type UserExternalConnectionEntry, type UserExternalConnectionEntryMap, type UserExternalConnectionEntryStatus, type UserExternalConnectionErrorCode } from './userexternalconnection';
4
- import { type UserExternalConnectionCapability, type UserExternalConnectionExternalAccountId, type UserExternalConnectionProviderType } from './userexternalconnection.id';
3
+ import { type UserExternalConnection, type UserExternalConnectionEntry, type UserExternalConnectionEntryMap, type UserExternalConnectionEntryStatus, type UserExternalConnectionErrorCode, type UserExternalConnectionLogin, type UserExternalConnectionLoginMap } from './userexternalconnection';
4
+ import { type UserExternalConnectionCapability, type UserExternalConnectionExternalAccountId, type UserExternalConnectionExternalAccountKey, type UserExternalConnectionProviderType } from './userexternalconnection.id';
5
5
  /**
6
6
  * The facts about a granted third-party authorization that a {@link UserExternalConnectionEntry} is
7
7
  * allowed to summarize.
@@ -29,6 +29,36 @@ export interface UserExternalConnectionGrantSummary {
29
29
  * @returns The connected provider types, sorted for a stable stored value.
30
30
  */
31
31
  export declare function userExternalConnectionConnectedProviderTypes(entries: Maybe<UserExternalConnectionEntryMap>): UserExternalConnectionProviderType[];
32
+ /**
33
+ * Input for {@link userExternalConnectionExternalAccountKeys}.
34
+ *
35
+ * BOTH maps, always. Taking them as one object rather than as a positional entry map is deliberate:
36
+ * `ec` is the union of the two, and a signature that made either one omittable would make it possible
37
+ * to recompute the array from half its sources — which silently drops the other half's keys out of the
38
+ * lookup a sign-in performs.
39
+ */
40
+ export interface UserExternalConnectionExternalAccountKeysInput {
41
+ readonly entries?: Maybe<UserExternalConnectionEntryMap>;
42
+ readonly logins?: Maybe<UserExternalConnectionLoginMap>;
43
+ }
44
+ /**
45
+ * The SOLE producer of a {@link UserExternalConnection}'s `ec` array.
46
+ *
47
+ * Membership is every ENTRY carrying an `ea`, at ANY status, UNION every LOGIN LINK's `ea` —
48
+ * deliberately unlike {@link userExternalConnectionConnectedProviderTypes}, which is `connected`-only.
49
+ * `c` answers "whose credentials can I use?", a question about the credentials; `ec` answers "who IS
50
+ * this account?", a question about identity, which survives an expired token. Filtering it by status
51
+ * would make a returning user with `error` credentials look like a stranger, and a sign-in would
52
+ * mint them a second Firebase user.
53
+ *
54
+ * The union is what makes the two lifecycles independent. Disconnecting a data connection removes its
55
+ * entry, and if `ec` came from `e` alone that would take the sign-in binding with it — the next
56
+ * sign-in would find no match and mint a second Firebase user for the same person.
57
+ *
58
+ * @param input - The entry map and the login map to derive from.
59
+ * @returns The external account keys, deduped and sorted for a stable stored value.
60
+ */
61
+ export declare function userExternalConnectionExternalAccountKeys(input: UserExternalConnectionExternalAccountKeysInput): UserExternalConnectionExternalAccountKey[];
32
62
  /**
33
63
  * Input for {@link userExternalConnectionEntryForOutcome}.
34
64
  *
@@ -87,6 +117,29 @@ export interface ApplyUserExternalConnectionEntryInput {
87
117
  readonly entry: Maybe<UserExternalConnectionEntry>;
88
118
  readonly now: Date;
89
119
  }
120
+ /**
121
+ * Input for {@link userExternalConnectionValue}.
122
+ */
123
+ export interface UserExternalConnectionValueInput {
124
+ readonly uid: FirebaseAuthUserId;
125
+ readonly entries: UserExternalConnectionEntryMap;
126
+ readonly logins: UserExternalConnectionLoginMap;
127
+ readonly now: Date;
128
+ }
129
+ /**
130
+ * Assembles the COMPLETE document value from both maps.
131
+ *
132
+ * Extracted so the two appliers cannot diverge on how the derived arrays are produced: `ec` is the
133
+ * union of `e` and `li`, and either applier computing it from only the map it happened to change
134
+ * would drop the other map's keys out of the sign-in lookup.
135
+ *
136
+ * Exported for the one caller that legitimately replaces a whole map rather than one provider's key —
137
+ * the login backfill. Ordinary writes go through the two appliers.
138
+ *
139
+ * @param input - The uid, both maps, and the instant to stamp.
140
+ * @returns The next UserExternalConnection value to write.
141
+ */
142
+ export declare function userExternalConnectionValue(input: UserExternalConnectionValueInput): UserExternalConnection;
90
143
  /**
91
144
  * Applies a single provider's entry and returns the COMPLETE next document.
92
145
  *
@@ -94,10 +147,77 @@ export interface ApplyUserExternalConnectionEntryInput {
94
147
  * exported way to change `e`, and it always recomputes `c` from the resulting map. There is no
95
148
  * exported path that touches one without the other.
96
149
  *
150
+ * The login map is carried through UNCHANGED. A data connection's lifecycle says nothing about
151
+ * whether the provider is still a way to sign in, so a disconnect must not remove the link.
152
+ *
97
153
  * @param input - The current document plus the provider entry to apply.
98
154
  * @returns The next UserExternalConnection value to write.
99
155
  */
100
156
  export declare function applyUserExternalConnectionEntry(input: ApplyUserExternalConnectionEntryInput): UserExternalConnection;
157
+ /**
158
+ * Input for {@link applyUserExternalConnectionLogin}.
159
+ */
160
+ export interface ApplyUserExternalConnectionLoginInput {
161
+ /**
162
+ * The currently stored document, when one exists.
163
+ */
164
+ readonly current?: Maybe<UserExternalConnection>;
165
+ readonly uid: FirebaseAuthUserId;
166
+ readonly providerType: UserExternalConnectionProviderType;
167
+ /**
168
+ * The next login link for this provider, or null to remove the provider's key entirely.
169
+ */
170
+ readonly login: Maybe<UserExternalConnectionLogin>;
171
+ readonly now: Date;
172
+ }
173
+ /**
174
+ * Applies a single provider's LOGIN LINK and returns the COMPLETE next document.
175
+ *
176
+ * The mirror of {@link applyUserExternalConnectionEntry}, and the only exported way to change `li`.
177
+ * The entry map is carried through unchanged: linking a provider as a login method grants nothing
178
+ * about its data connection, because the identity scopes and the data scopes are not guaranteed to
179
+ * be the same set.
180
+ *
181
+ * @param input - The current document plus the login link to apply.
182
+ * @returns The next UserExternalConnection value to write.
183
+ */
184
+ export declare function applyUserExternalConnectionLogin(input: ApplyUserExternalConnectionLoginInput): UserExternalConnection;
185
+ /**
186
+ * The identity facts a {@link UserExternalConnectionLogin} is derived from.
187
+ *
188
+ * Structurally the subset of `UserExternalConnectionSignInIdentity` (in
189
+ * `@dereekb/firebase-server/model`) that a link records. Declared here rather than imported because
190
+ * this package is shared with the browser and cannot name a server type — and because the derivation
191
+ * genuinely needs nothing more than these four values.
192
+ */
193
+ export interface UserExternalConnectionLoginIdentity {
194
+ readonly externalAccountId: UserExternalConnectionExternalAccountId;
195
+ readonly email?: Maybe<EmailAddress>;
196
+ readonly emailVerified?: Maybe<boolean>;
197
+ readonly label?: Maybe<string>;
198
+ }
199
+ /**
200
+ * Input for {@link userExternalConnectionLoginForIdentity}.
201
+ */
202
+ export interface UserExternalConnectionLoginForIdentityInput {
203
+ readonly identity: UserExternalConnectionLoginIdentity;
204
+ /**
205
+ * The link currently stored for this provider, when there is one.
206
+ */
207
+ readonly previous?: Maybe<UserExternalConnectionLogin>;
208
+ readonly now: Date;
209
+ }
210
+ /**
211
+ * Derives the {@link UserExternalConnectionLogin} for an identity a link round trip resolved.
212
+ *
213
+ * `lat` survives a relink, the mirror of how {@link userExternalConnectionEntryForOutcome} preserves
214
+ * `coa`: relinking the same provider is a re-consent, not a new relationship, so the date the account
215
+ * first became a login method stays what it was.
216
+ *
217
+ * @param input - The resolved identity, the stored link, and the instant to stamp.
218
+ * @returns The next login link.
219
+ */
220
+ export declare function userExternalConnectionLoginForIdentity(input: UserExternalConnectionLoginForIdentityInput): UserExternalConnectionLogin;
101
221
  /**
102
222
  * Input for {@link emptyUserExternalConnection}.
103
223
  */
@@ -147,3 +267,18 @@ export declare function userExternalConnectionEntryIsExpired(entry: Maybe<UserEx
147
267
  * @returns True when the provider's entry is connected.
148
268
  */
149
269
  export declare function userExternalConnectionIsConnectedToProvider(connection: Maybe<UserExternalConnection>, providerType: UserExternalConnectionProviderType): boolean;
270
+ /**
271
+ * Returns the login link for the given provider, if any.
272
+ *
273
+ * @param connection - The loaded connection document.
274
+ * @param providerType - The provider to read.
275
+ * @returns The provider's login link, or null when the provider is not a login method for this user.
276
+ */
277
+ export declare function userExternalConnectionLoginForProvider(connection: Maybe<UserExternalConnection>, providerType: UserExternalConnectionProviderType): Maybe<UserExternalConnectionLogin>;
278
+ /**
279
+ * Returns every provider type that is a login method for this user.
280
+ *
281
+ * @param connection - The loaded connection document.
282
+ * @returns The linked provider types, sorted for a stable render order.
283
+ */
284
+ export declare function userExternalConnectionLinkedLoginProviderTypes(connection: Maybe<UserExternalConnection>): UserExternalConnectionProviderType[];
package/test/package.json CHANGED
@@ -1,13 +1,14 @@
1
1
  {
2
2
  "name": "@dereekb/firebase/test",
3
- "version": "14.0.1",
3
+ "version": "14.2.0",
4
+ "sideEffects": false,
4
5
  "type": "module",
5
6
  "peerDependencies": {
6
- "@dereekb/date": "14.0.1",
7
- "@dereekb/firebase": "14.0.1",
8
- "@dereekb/model": "14.0.1",
9
- "@dereekb/rxjs": "14.0.1",
10
- "@dereekb/util": "14.0.1",
7
+ "@dereekb/date": "14.2.0",
8
+ "@dereekb/firebase": "14.2.0",
9
+ "@dereekb/model": "14.2.0",
10
+ "@dereekb/rxjs": "14.2.0",
11
+ "@dereekb/util": "14.2.0",
11
12
  "@firebase/rules-unit-testing": "5.0.2",
12
13
  "date-fns": "^4.1.0",
13
14
  "firebase": "^12.18.0",