|
| 1 | +import { setTimeout as wait } from 'node:timers/promises' |
| 2 | + |
1 | 3 | import { isObject } from '@socketsecurity/registry/lib/objects' |
2 | 4 |
|
| 5 | +import constants from '../../constants' |
3 | 6 | import { isErrnoException } from '../errors' |
4 | 7 | import { getPublicToken, setupSdk } from '../sdk' |
5 | 8 | import { findSocketYmlSync, getSetting } from '../settings' |
@@ -36,6 +39,8 @@ type NonNormalizedResolvedRule = |
36 | 39 |
|
37 | 40 | type RuleActionUX = { block: boolean; display: boolean } |
38 | 41 |
|
| 42 | +const { abortSignal } = constants |
| 43 | + |
39 | 44 | const ERROR_UX: RuleActionUX = { |
40 | 45 | block: true, |
41 | 46 | display: true |
@@ -179,81 +184,89 @@ let _uxLookup: AlertUxLookup | undefined |
179 | 184 | export async function uxLookup( |
180 | 185 | settings: AlertUxLookupSettings |
181 | 186 | ): Promise<AlertUxLookupResult> { |
182 | | - if (_uxLookup === undefined) { |
183 | | - const { orgs, settings } = await (async () => { |
184 | | - try { |
185 | | - const sockSdk = await setupSdk(getPublicToken()) |
186 | | - const orgResult = await sockSdk.getOrganizations() |
187 | | - if (!orgResult.success) { |
188 | | - throw new Error( |
189 | | - `Failed to fetch Socket organization info: ${orgResult.error.message}` |
190 | | - ) |
191 | | - } |
192 | | - const orgs: Array< |
193 | | - Exclude<(typeof orgResult.data.organizations)[string], undefined> |
194 | | - > = [] |
195 | | - for (const org of Object.values(orgResult.data.organizations)) { |
196 | | - if (org) { |
197 | | - orgs.push(org) |
198 | | - } |
199 | | - } |
200 | | - const result = await sockSdk.postSettings( |
201 | | - orgs.map(org => ({ organization: org.id })) |
| 187 | + while (_uxLookup === undefined) { |
| 188 | + // eslint-disable-next-line no-await-in-loop |
| 189 | + await wait(1, { signal: abortSignal }) |
| 190 | + } |
| 191 | + return _uxLookup(settings) |
| 192 | +} |
| 193 | + |
| 194 | +// Start initializing the AlertUxLookupResult immediately. |
| 195 | +void (async () => { |
| 196 | + const { orgs, settings } = await (async () => { |
| 197 | + try { |
| 198 | + const sockSdk = await setupSdk(getPublicToken()) |
| 199 | + const orgResult = await sockSdk.getOrganizations() |
| 200 | + if (!orgResult.success) { |
| 201 | + throw new Error( |
| 202 | + `Failed to fetch Socket organization info: ${orgResult.error.message}` |
202 | 203 | ) |
203 | | - if (!result.success) { |
204 | | - throw new Error( |
205 | | - `Failed to fetch API key settings: ${result.error.message}` |
206 | | - ) |
207 | | - } |
208 | | - return { |
209 | | - orgs, |
210 | | - settings: result.data |
211 | | - } |
212 | | - } catch (e) { |
213 | | - const cause = isObject(e) && 'cause' in e ? e['cause'] : undefined |
214 | | - if ( |
215 | | - isErrnoException(cause) && |
216 | | - (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED') |
217 | | - ) { |
218 | | - throw new Error( |
219 | | - 'Unable to connect to socket.dev, ensure internet connectivity before retrying', |
220 | | - { |
221 | | - cause: e |
222 | | - } |
223 | | - ) |
| 204 | + } |
| 205 | + const orgs: Array< |
| 206 | + Exclude<(typeof orgResult.data.organizations)[string], undefined> |
| 207 | + > = [] |
| 208 | + for (const org of Object.values(orgResult.data.organizations)) { |
| 209 | + if (org) { |
| 210 | + orgs.push(org) |
224 | 211 | } |
225 | | - throw e |
226 | 212 | } |
227 | | - })() |
228 | | - // Remove any organizations not being enforced. |
229 | | - const enforcedOrgs = getSetting('enforcedOrgs') ?? [] |
230 | | - for (const { 0: i, 1: org } of orgs.entries()) { |
231 | | - if (!enforcedOrgs.includes(org.id)) { |
232 | | - settings.entries.splice(i, 1) |
| 213 | + const result = await sockSdk.postSettings( |
| 214 | + orgs.map(org => ({ organization: org.id })) |
| 215 | + ) |
| 216 | + if (!result.success) { |
| 217 | + throw new Error( |
| 218 | + `Failed to fetch API key settings: ${result.error.message}` |
| 219 | + ) |
| 220 | + } |
| 221 | + return { |
| 222 | + orgs, |
| 223 | + settings: result.data |
233 | 224 | } |
| 225 | + } catch (e) { |
| 226 | + const cause = isObject(e) && 'cause' in e ? e['cause'] : undefined |
| 227 | + if ( |
| 228 | + isErrnoException(cause) && |
| 229 | + (cause.code === 'ENOTFOUND' || cause.code === 'ECONNREFUSED') |
| 230 | + ) { |
| 231 | + throw new Error( |
| 232 | + 'Unable to connect to socket.dev, ensure internet connectivity before retrying', |
| 233 | + { |
| 234 | + cause: e |
| 235 | + } |
| 236 | + ) |
| 237 | + } |
| 238 | + throw e |
| 239 | + } |
| 240 | + })() |
| 241 | + |
| 242 | + // Remove any organizations not being enforced. |
| 243 | + const enforcedOrgs = getSetting('enforcedOrgs') ?? [] |
| 244 | + for (const { 0: i, 1: org } of orgs.entries()) { |
| 245 | + if (!enforcedOrgs.includes(org.id)) { |
| 246 | + settings.entries.splice(i, 1) |
234 | 247 | } |
235 | | - const socketYml = findSocketYmlSync() |
236 | | - if (socketYml) { |
237 | | - settings.entries.push({ |
238 | | - start: socketYml.path, |
239 | | - settings: { |
240 | | - [socketYml.path]: { |
241 | | - deferTo: null, |
242 | | - // TODO: TypeScript complains about the type not matching. We should |
243 | | - // figure out why are providing |
244 | | - // issueRules: { [issueName: string]: boolean } |
245 | | - // but expecting |
246 | | - // issueRules: { [issueName: string]: { action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' } } |
247 | | - issueRules: socketYml.parsed.issueRules as unknown as { |
248 | | - [key: string]: { |
249 | | - action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' |
250 | | - } |
| 248 | + } |
| 249 | + |
| 250 | + const socketYml = findSocketYmlSync() |
| 251 | + if (socketYml) { |
| 252 | + settings.entries.push({ |
| 253 | + start: socketYml.path, |
| 254 | + settings: { |
| 255 | + [socketYml.path]: { |
| 256 | + deferTo: null, |
| 257 | + // TODO: TypeScript complains about the type not matching. We should |
| 258 | + // figure out why are providing |
| 259 | + // issueRules: { [issueName: string]: boolean } |
| 260 | + // but expecting |
| 261 | + // issueRules: { [issueName: string]: { action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' } } |
| 262 | + issueRules: socketYml.parsed.issueRules as unknown as { |
| 263 | + [key: string]: { |
| 264 | + action: 'defer' | 'error' | 'ignore' | 'monitor' | 'warn' |
251 | 265 | } |
252 | 266 | } |
253 | 267 | } |
254 | | - }) |
255 | | - } |
256 | | - _uxLookup = createAlertUXLookup(settings) |
| 268 | + } |
| 269 | + }) |
257 | 270 | } |
258 | | - return _uxLookup(settings) |
259 | | -} |
| 271 | + _uxLookup = createAlertUXLookup(settings) |
| 272 | +})() |
0 commit comments