@biffo/cli 0.284.0 → 0.284.2

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.
@@ -23,6 +23,17 @@ async function loadAuth() {
23
23
  return await import('./auth')
24
24
  }
25
25
 
26
+ /**
27
+ * What the real library hands back: an IMMUTABLE snapshot. `getIdToken()` on a
28
+ * `CognitoUserSession` returns the same `CognitoIdToken` forever, so the JWT
29
+ * inside one of these never changes — which is the whole reason a caller must
30
+ * not hold on to it, and the reason `getFreshIdToken` re-reads storage.
31
+ */
32
+ function session(jwt: string) {
33
+ const idToken = { getJwtToken: () => jwt, payload: {} }
34
+ return { isValid: () => true, getIdToken: () => idToken }
35
+ }
36
+
26
37
  describe('getCurrentSession', () => {
27
38
  beforeEach(() => {
28
39
  vi.clearAllMocks()
@@ -64,6 +75,87 @@ describe('getCurrentSession', () => {
64
75
  })
65
76
  })
66
77
 
78
+ // Folded up from biffo-plugin-ideation's own copy of this file (biffo-template#1564).
79
+ //
80
+ // `filesIfPresent` maps that repo's `web/src/lib/auth.test.ts` at THIS file, and
81
+ // #1546 added the mapping in the same commit that created this file — so the
82
+ // canonical copy has been a strict SUBSET of the one repo already holding that
83
+ // path, and the next sync round would have deleted every assertion below.
84
+ // AGENTS.md section 9 ("Reconcile before you distribute") says to fold the fixes
85
+ // upstream first, which is what this block is: the same four properties, restated
86
+ // in this file's `loadAuth()` idiom so they hold against the in-flight-memoised
87
+ // pool rather than the settled-value one they were written for.
88
+ //
89
+ // The invariant they guard is the one `getFreshIdToken`'s own docstring argues at
90
+ // length and nothing here tested: a `CognitoUserSession` is an immutable value
91
+ // object, so a caller that snapshots the JWT sends a frozen token that 401s for
92
+ // the life of the page once it lapses (biffo-plugin-ideation#69).
93
+ describe('getFreshIdToken', () => {
94
+ beforeEach(() => {
95
+ vi.clearAllMocks()
96
+ resolveCoreIdentity.mockResolvedValue({
97
+ userPoolId: 'us-east-1_DOCPOOL',
98
+ clientId: 'docclientid',
99
+ })
100
+ })
101
+
102
+ afterEach(() => {
103
+ vi.restoreAllMocks()
104
+ })
105
+
106
+ it('re-resolves through the pool on every call, so a refreshed token replaces a lapsed one', async () => {
107
+ // `stored` stands for what localStorage holds. The library rotates it when
108
+ // the cached ID token expires and the refresh token buys a new one — the
109
+ // caller sees that only if it asks again.
110
+ let stored = session('jwt-before-refresh')
111
+ getCurrentUser.mockReturnValue({
112
+ getSession: (cb: (e: Error | null, s: unknown) => void) => cb(null, stored),
113
+ })
114
+ const { getFreshIdToken } = await loadAuth()
115
+
116
+ expect(await getFreshIdToken()).toBe('jwt-before-refresh')
117
+
118
+ stored = session('jwt-after-refresh')
119
+
120
+ expect(await getFreshIdToken()).toBe('jwt-after-refresh')
121
+ // Two resolutions, not one memoised answer. The POOL is memoised; the
122
+ // session read deliberately is not.
123
+ expect(getCurrentUser).toHaveBeenCalledTimes(2)
124
+ expect(poolConstructor).toHaveBeenCalledTimes(1)
125
+ })
126
+
127
+ it('is null when there is no session, rather than throwing', async () => {
128
+ getCurrentUser.mockReturnValue(null)
129
+ const { getFreshIdToken } = await loadAuth()
130
+ await expect(getFreshIdToken()).resolves.toBeNull()
131
+ })
132
+
133
+ it('is null when the pool cannot be resolved (identity document unreachable)', async () => {
134
+ resolveCoreIdentity.mockResolvedValue(null)
135
+ const { getFreshIdToken } = await loadAuth()
136
+ await expect(getFreshIdToken()).resolves.toBeNull()
137
+ expect(getCurrentUser).not.toHaveBeenCalled()
138
+ })
139
+
140
+ it('only ever asks the pool built from the runtime identity document', async () => {
141
+ // The claim biffo-plugin-ideation#70 rests on and #69 disputed: the pool is
142
+ // constructed from the resolved identity and the library scopes every storage
143
+ // read by that Client ID, so no other pool's credentials can be reached here.
144
+ getCurrentUser.mockReturnValue({
145
+ getSession: (cb: (e: Error | null, s: unknown) => void) => cb(null, session('jwt')),
146
+ })
147
+ const { getFreshIdToken } = await loadAuth()
148
+
149
+ await getFreshIdToken()
150
+
151
+ expect(resolveCoreIdentity).toHaveBeenCalled()
152
+ expect(poolConstructor).toHaveBeenCalledWith({
153
+ UserPoolId: 'us-east-1_DOCPOOL',
154
+ ClientId: 'docclientid',
155
+ })
156
+ })
157
+ })
158
+
67
159
  // biffo-plugin-marketing#55: the pool used to be memoised on the SETTLED value,
68
160
  // so concurrent callers that started before the first resolution completed each
69
161
  // ran an independent resolution (including pruneForeignCognitoCredentials()'s
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.284.0",
3
+ "version": "0.284.2",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",