Skip to content

Commit fc2482d

Browse files
web: make shared crypto.randomUUID() function (#4693)
* refactor: globalThis.crypto.randomUUID() Before, `crypto.randomUUID()` broke web mode since it is not available in the polyfill `crypto-browserify`. Solution: Use `globalThis.crypto.randomUUID()` as it works in both node + browser since each environment provides an implementation at runtime. In the long term we will want a better solution, but this commit quickly gets web mode working. Signed-off-by: Nikolas Komonen <[email protected]> * use randomUUID in existing places Signed-off-by: Nikolas Komonen <[email protected]> * add tests Signed-off-by: Nikolas Komonen <[email protected]> * add documentation Signed-off-by: Nikolas Komonen <[email protected]> --------- Signed-off-by: Nikolas Komonen <[email protected]>
1 parent 55e3211 commit fc2482d

File tree

9 files changed

+96
-6
lines changed

9 files changed

+96
-6
lines changed

packages/core/src/amazonqFeatureDev/session/sessionState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55

66
import { MynahIcons } from '@aws/mynah-ui'
7-
import { randomUUID } from 'crypto'
87
import * as path from 'path'
98
import * as vscode from 'vscode'
109
import { ToolkitError } from '../../shared/errors'
@@ -34,6 +33,7 @@ import { CodeReference } from '../../amazonq/webview/ui/connector'
3433
import { isPresent } from '../../shared/utilities/collectionUtils'
3534
import { encodeHTML } from '../../shared/utilities/textUtilities'
3635
import { AuthUtil } from '../../codewhisperer/util/authUtil'
36+
import { randomUUID } from '../../common/crypto'
3737

3838
export class ConversationNotStartedState implements Omit<SessionState, 'uploadId'> {
3939
public tokenSource: vscode.CancellationTokenSource

packages/core/src/amazonqGumby/telemetry/codeTransformTelemetryState.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
33
* SPDX-License-Identifier: Apache-2.0
44
*/
5-
import { randomUUID } from 'crypto'
5+
6+
import { randomUUID } from '../../common/crypto'
67

78
interface ICodeTransformerTelemetryState {
89
sessionId: string

packages/core/src/auth/auth.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ const localize = nls.loadMessageBundle()
1010

1111
import * as vscode from 'vscode'
1212
import * as localizedText from '../shared/localizedText'
13-
import { randomUUID } from 'crypto'
1413
import { Credentials } from '@aws-sdk/types'
1514
import { SsoAccessTokenProvider } from './sso/ssoAccessTokenProvider'
1615
import { Timeout } from '../shared/utilities/timeoutUtils'
@@ -61,6 +60,7 @@ import {
6160
} from './connection'
6261
import { isSageMaker, isCloud9 } from '../shared/extensionUtilities'
6362
import { telemetry } from '../shared/telemetry/telemetry'
63+
import { randomUUID } from '../common/crypto'
6464

6565
interface AuthService {
6666
/**

packages/core/src/codewhispererChat/controllers/chat/controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { EditorContentController } from '../../../amazonq/commons/controllers/co
3333
import { EditorContextCommand } from '../../commands/registerCommands'
3434
import { PromptsGenerator } from './prompts/promptsGenerator'
3535
import { TriggerEventsStorage } from '../../storages/triggerEvents'
36-
import { randomUUID } from 'crypto'
3736
import {
3837
CodeWhispererStreamingServiceException,
3938
GenerateAssistantResponseCommandOutput,
@@ -46,6 +45,7 @@ import { triggerPayloadToChatRequest } from './chatRequest/converter'
4645
import { OnboardingPageInteraction } from '../../../amazonq/onboardingPage/model'
4746
import { getChatAuthState } from '../../../codewhisperer/util/authUtil'
4847
import { openUrl } from '../../../shared/utilities/vsCodeUtils'
48+
import { randomUUID } from '../../../common/crypto'
4949

5050
export interface ChatControllerMessagePublishers {
5151
readonly processPromptChatMessage: MessagePublisher<PromptMessage>

packages/core/src/common/crypto.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
/**
7+
* Why do we need this?
8+
*
9+
* Depending on environment (node vs web), `crypto` is different.
10+
* Node requires `crypto` to be imported, while in web it is available globally
11+
* through just calling `crypto` or `globalThis.crypto`.
12+
*
13+
* The crypto signatures and functions are not 1:1 between the environments.
14+
* So this module provides environment agnostic functions for `crypto`.
15+
*
16+
* ---
17+
*
18+
* Node `crypto` has `crypto.webcrypto` except the interface is more cumbersome to use
19+
* compared to node `crypto`. So we will want to eventually exclusively use functions
20+
* in this class instead of the `crypto` functions.
21+
*
22+
* Once we do not need `crypto` anymore, we can get rid of the polyfill.
23+
*/
24+
25+
import { isWeb } from './webUtils'
26+
27+
export function randomUUID(): `${string}-${string}-${string}-${string}-${string}` {
28+
if (isWeb()) {
29+
return globalThis.crypto.randomUUID()
30+
}
31+
32+
return require('crypto').randomUUID()
33+
}

packages/core/src/shared/telemetry/util.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { env, Memento, version } from 'vscode'
77
import { getLogger } from '../logger'
88
import { fromExtensionManifest } from '../settings'
99
import { shared } from '../utilities/functionUtils'
10-
import { randomUUID } from 'crypto'
1110
import { isInDevEnv, extensionVersion, isAutomation } from '../vscode/env'
1211
import { addTypeName } from '../utilities/typeConstructors'
1312
import globals from '../extensionGlobals'
@@ -16,6 +15,7 @@ import { Result } from './telemetry.gen'
1615
import { MetricDatum } from './clienttelemetry'
1716
import { isValidationExemptMetric } from './exemptMetrics'
1817
import { isCloud9, isSageMaker } from '../../shared/extensionUtilities'
18+
import { randomUUID } from '../../common/crypto'
1919

2020
const legacySettingsTelemetryValueDisable = 'Disable'
2121
const legacySettingsTelemetryValueEnable = 'Enable'

packages/core/src/test/amazonqFeatureDev/session/sessionState.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { MessagePublisher } from '../../../amazonq/messages/messagePublisher'
2121
import { FeatureDevClient } from '../../../amazonqFeatureDev/client/featureDev'
2222
import { ToolkitError } from '../../../shared/errors'
2323
import { PrepareRepoFailedError } from '../../../amazonqFeatureDev/errors'
24-
import crypto from 'crypto'
24+
import * as crypto from '../../../common/crypto'
2525
import { TelemetryHelper } from '../../../amazonqFeatureDev/util/telemetryHelper'
2626
import { assertTelemetry, createTestWorkspaceFolder } from '../../testUtil'
2727
import { getFetchStubWithResponse } from '../../common/request.test'
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import assert from 'assert'
7+
import { randomUUID } from '../../common/crypto'
8+
9+
describe('crypto', function () {
10+
describe('randomUUID()', function () {
11+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
12+
13+
it('functions as normal', async function () {
14+
const result1 = randomUUID()
15+
const result2 = randomUUID()
16+
const result3 = randomUUID()
17+
assert(uuidPattern.test(result1))
18+
assert(uuidPattern.test(result2))
19+
assert(uuidPattern.test(result3))
20+
assert(result1 !== result2)
21+
assert(result2 !== result3)
22+
})
23+
24+
it('test pattern fails on non-uuid', function () {
25+
assert(uuidPattern.test('not-a-uuid') === false)
26+
})
27+
})
28+
})
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import assert from 'assert'
7+
import { randomUUID } from '../../common/crypto'
8+
9+
describe('crypto', function () {
10+
describe('randomUUID()', function () {
11+
const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
12+
13+
it('functions as normal', async function () {
14+
const result1 = randomUUID()
15+
const result2 = randomUUID()
16+
const result3 = randomUUID()
17+
assert(uuidPattern.test(result1))
18+
assert(uuidPattern.test(result2))
19+
assert(uuidPattern.test(result3))
20+
assert(result1 !== result2)
21+
assert(result2 !== result3)
22+
})
23+
24+
it('test pattern fails on non-uuid', function () {
25+
assert(uuidPattern.test('not-a-uuid') === false)
26+
})
27+
})
28+
})

0 commit comments

Comments
 (0)