From 4038596705aeb20233d7479d16d1cab03a198f73 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 8 Jul 2026 11:41:43 +0200 Subject: [PATCH] test(cloudflare-integration-tests): Type-check test suites in CI The `suites/**` files were never type-checked in CI: there was no `type-check` script and vitest transpiles with esbuild. The suites are already covered by `tsconfig.json`, so this adds a gate and fixes the ~30 latent type errors it surfaced. All fixes are type-only; no runtime behavior changed. - Add a `type-check` script (`tsc --noEmit`) and run it in the Lint CI job. - Worker fixtures: drop incorrect `implements RpcTarget` (DurableObjects expose RPC inherently), and let WorkerEntrypoint classes use the ambient `Cloudflare.Env` (which `withSentry`'s `WorkerEntrypointConstructor` requires), casting `this.env` to the local `Env` for binding access. - AI assertions: type the `span` callback params as `SerializedStreamedSpan`. - Narrow envelope items before accessing `.spans` in durable-object tests. - Fix the runner's `Expected` argument typing. - Targeted casts for version-skewed AI mocks (LangChain callback handler, OpenAI mock client, vercel AI mock language model). - Exclude `suites/prisma/**` (imports a Prisma-generated client that only exists after codegen). Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build.yml | 3 +++ .../cloudflare-integration-tests/package.json | 1 + dev-packages/cloudflare-integration-tests/runner.ts | 5 ++++- .../suites/tracing/durableobject-sql/test.ts | 8 +++----- .../suites/tracing/durableobject-sync-kv/test.ts | 4 ++-- .../suites/tracing/google-genai/test.ts | 13 +++++++++---- .../suites/tracing/langchain/index.ts | 5 +++-- .../suites/tracing/langchain/test.ts | 11 +++++++---- .../suites/tracing/langgraph/test.ts | 11 ++++++++--- .../suites/tracing/openai/index.ts | 6 +++++- .../tracing/propagation/worker-do-rpc/index.ts | 3 +-- .../worker-worker-do-rpc/index-sub-worker.ts | 3 +-- .../worker-workerentrypoint-rpc/index-sub-worker.ts | 2 +- .../workerentrypoint-do-rpc-disabled/index.ts | 6 +++--- .../propagation/workerentrypoint-do-rpc/index.ts | 4 ++-- .../index-sub-worker.ts | 9 ++++----- .../index.ts | 4 ++-- .../suites/tracing/vercelai/als_v6/index.ts | 3 ++- .../suites/tracing/vercelai/compat_v6/index.ts | 3 ++- .../cloudflare-integration-tests/tsconfig.json | 4 ++++ 20 files changed, 67 insertions(+), 41 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0d8e992b97c8..58cc9fa75004 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -337,6 +337,9 @@ jobs: run: yarn lint - name: Lint for ES compatibility run: yarn lint:es-compatibility + - name: Type check cloudflare integration test suites + working-directory: dev-packages/cloudflare-integration-tests + run: yarn type-check job_check_lockfile: name: Check lockfile diff --git a/dev-packages/cloudflare-integration-tests/package.json b/dev-packages/cloudflare-integration-tests/package.json index 43f4dc948ea0..72e9379617f2 100644 --- a/dev-packages/cloudflare-integration-tests/package.json +++ b/dev-packages/cloudflare-integration-tests/package.json @@ -9,6 +9,7 @@ "scripts": { "lint": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --type-aware", "lint:fix": "OXLINT_TSGOLINT_DANGEROUSLY_SUPPRESS_PROGRAM_DIAGNOSTICS=true oxlint . --fix --type-aware", + "type-check": "tsc --noEmit", "test": "vitest run", "test:watch": "yarn test --watch" }, diff --git a/dev-packages/cloudflare-integration-tests/runner.ts b/dev-packages/cloudflare-integration-tests/runner.ts index d50422ade021..1b19e9e15efd 100644 --- a/dev-packages/cloudflare-integration-tests/runner.ts +++ b/dev-packages/cloudflare-integration-tests/runner.ts @@ -408,7 +408,10 @@ export function createRunner(...paths: string[]) { expected: Expected | Expected[], options: { headers?: Record; data?: BodyInit; expectError?: boolean } = {}, ): Promise { - const expectations = Array.isArray(expected) ? expected : [expected]; + // `Expected` includes `Envelope`, which is itself an array, so `Array.isArray` can't + // distinguish a single `Envelope` from an `Expected[]`. Callers pass expectation + // callbacks (or an array of them), so the narrowed value is always `Expected[]`. + const expectations = (Array.isArray(expected) ? expected : [expected]) as Expected[]; const envelopePromises = expectations.map(e => waitForEnvelope(e)); const result = await this.makeRequest(method, path, options); await Promise.all(envelopePromises); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sql/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sql/test.ts index 9aacb42f00a3..8e185df57558 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sql/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sql/test.ts @@ -1,4 +1,4 @@ -import type { Envelope } from '@sentry/core'; +import type { Envelope, TransactionEvent } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; import { expect, it } from 'vitest'; import { createRunner } from '../../../runner'; @@ -14,7 +14,7 @@ const flushMarkerMatcher = (envelope: Envelope): void => { it('instruments SQL exec operations on Durable Object storage', async ({ signal }) => { const runner = createRunner(__dirname) .expect(envelope => { - const transactionEvent = envelope[1]?.[0]?.[1]; + const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent | undefined; const spans = transactionEvent?.spans ?? []; expect(transactionEvent).toEqual( @@ -24,9 +24,7 @@ it('instruments SQL exec operations on Durable Object storage', async ({ signal }), ); - const sqlSpans = (spans as Array>).filter( - s => s.origin === 'auto.db.cloudflare.durable_object.sql', - ); + const sqlSpans = spans.filter(s => s.origin === 'auto.db.cloudflare.durable_object.sql'); expect(sqlSpans).toHaveLength(3); expect(sqlSpans).toEqual( diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sync-kv/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sync-kv/test.ts index c37ec1a64c69..25103e4e0ceb 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sync-kv/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/durableobject-sync-kv/test.ts @@ -1,4 +1,4 @@ -import type { Envelope } from '@sentry/core'; +import type { Envelope, TransactionEvent } from '@sentry/core'; import { expect, it } from 'vitest'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from '@sentry/core'; import { createRunner } from '../../../runner'; @@ -14,7 +14,7 @@ const flushMarkerMatcher = (envelope: Envelope): void => { it('instruments sync KV operations on Durable Object storage', async ({ signal }) => { const runner = createRunner(__dirname) .expect(envelope => { - const transactionEvent = envelope[1]?.[0]?.[1]; + const transactionEvent = envelope[1]?.[0]?.[1] as TransactionEvent | undefined; const spans = transactionEvent?.spans ?? []; expect(transactionEvent).toEqual( diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts index 2724c8017c7c..9dfa2b3d221d 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/google-genai/test.ts @@ -1,4 +1,5 @@ import { expect, it } from 'vitest'; +import type { SerializedStreamedSpan } from '@sentry/core'; import { GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, @@ -29,13 +30,13 @@ it('traces Google GenAI chat creation and message sending', async ({ signal }) = const container = envelope[1]?.[1]?.[1] as any; expect(container).toBeDefined(); expect(container.items).toHaveLength(3); - expect(container.items.map(span => span.name).sort()).toEqual([ + expect(container.items.map((span: SerializedStreamedSpan) => span.name).sort()).toEqual([ 'chat gemini-1.5-pro', 'embeddings text-embedding-004', 'generate_content gemini-1.5-flash', ]); - const chatSpan = container.items.find(span => span.name === 'chat gemini-1.5-pro'); + const chatSpan = container.items.find((span: SerializedStreamedSpan) => span.name === 'chat gemini-1.5-pro'); expect(chatSpan).toBeDefined(); expect(chatSpan!.status).toBe('ok'); expect(chatSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ type: 'string', value: 'chat' }); @@ -50,7 +51,9 @@ it('traces Google GenAI chat creation and message sending', async ({ signal }) = expect(chatSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 12 }); expect(chatSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 20 }); - const generateContentSpan = container.items.find(span => span.name === 'generate_content gemini-1.5-flash'); + const generateContentSpan = container.items.find( + (span: SerializedStreamedSpan) => span.name === 'generate_content gemini-1.5-flash', + ); expect(generateContentSpan).toBeDefined(); expect(generateContentSpan!.status).toBe('ok'); expect(generateContentSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ @@ -95,7 +98,9 @@ it('traces Google GenAI chat creation and message sending', async ({ signal }) = value: 20, }); - const embeddingsSpan = container.items.find(span => span.name === 'embeddings text-embedding-004'); + const embeddingsSpan = container.items.find( + (span: SerializedStreamedSpan) => span.name === 'embeddings text-embedding-004', + ); expect(embeddingsSpan).toBeDefined(); expect(embeddingsSpan!.status).toBe('ok'); expect(embeddingsSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/index.ts index b1cd17c5eda1..7fac26ed8774 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/index.ts @@ -1,5 +1,5 @@ import * as Sentry from '@sentry/cloudflare'; -import { MockChain, MockChatModel, MockTool } from './mocks'; +import { type CallbackHandler, MockChain, MockChatModel, MockTool } from './mocks'; interface Env { SENTRY_DSN: string; @@ -14,10 +14,11 @@ export default Sentry.withSentry( { async fetch(_request, _env, _ctx) { // Create LangChain callback handler + // The mock models accept their own local `CallbackHandler` shape, which differs from the SDK's handler type. const callbackHandler = Sentry.createLangChainCallbackHandler({ recordInputs: false, recordOutputs: false, - }); + }) as unknown as CallbackHandler; // Test 1: Chat model invocation const chatModel = new MockChatModel({ diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts index 6968d57bfef9..c663fc6b3289 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/langchain/test.ts @@ -1,4 +1,5 @@ import { expect, it } from 'vitest'; +import type { SerializedStreamedSpan } from '@sentry/core'; import { GEN_AI_OPERATION_NAME_ATTRIBUTE, GEN_AI_REQUEST_MAX_TOKENS_ATTRIBUTE, @@ -29,13 +30,15 @@ it('traces langchain chat model, chain, and tool invocations', async ({ signal } const container = envelope[1]?.[1]?.[1] as any; expect(container).toBeDefined(); expect(container.items).toHaveLength(3); - expect(container.items.map(span => span.name).sort()).toEqual([ + expect(container.items.map((span: SerializedStreamedSpan) => span.name).sort()).toEqual([ 'chain my_test_chain', 'chat claude-3-5-sonnet-20241022', 'execute_tool search_tool', ]); - const chatSpan = container.items.find(span => span.name === 'chat claude-3-5-sonnet-20241022'); + const chatSpan = container.items.find( + (span: SerializedStreamedSpan) => span.name === 'chat claude-3-5-sonnet-20241022', + ); expect(chatSpan).toBeDefined(); expect(chatSpan!.status).toBe('ok'); expect(chatSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ type: 'string', value: 'chat' }); @@ -52,14 +55,14 @@ it('traces langchain chat model, chain, and tool invocations', async ({ signal } expect(chatSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 15 }); expect(chatSpan!.attributes[GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE]).toEqual({ type: 'integer', value: 25 }); - const chainSpan = container.items.find(span => span.name === 'chain my_test_chain'); + const chainSpan = container.items.find((span: SerializedStreamedSpan) => span.name === 'chain my_test_chain'); expect(chainSpan).toBeDefined(); expect(chainSpan!.status).toBe('ok'); expect(chainSpan!.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.ai.langchain' }); expect(chainSpan!.attributes['sentry.op']).toEqual({ type: 'string', value: 'gen_ai.invoke_agent' }); expect(chainSpan!.attributes['langchain.chain.name']).toEqual({ type: 'string', value: 'my_test_chain' }); - const toolSpan = container.items.find(span => span.name === 'execute_tool search_tool'); + const toolSpan = container.items.find((span: SerializedStreamedSpan) => span.name === 'execute_tool search_tool'); expect(toolSpan).toBeDefined(); expect(toolSpan!.status).toBe('ok'); expect(toolSpan!.attributes['sentry.origin']).toEqual({ type: 'string', value: 'auto.ai.langchain' }); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/langgraph/test.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/langgraph/test.ts index 542f29ad7206..aad02e48ee73 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/langgraph/test.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/langgraph/test.ts @@ -1,4 +1,5 @@ import { expect, it } from 'vitest'; +import type { SerializedStreamedSpan } from '@sentry/core'; import { GEN_AI_AGENT_NAME_ATTRIBUTE, GEN_AI_INPUT_MESSAGES_ATTRIBUTE, @@ -29,12 +30,14 @@ it('traces langgraph compile and invoke operations', async ({ signal }) => { expect(container).toBeDefined(); expect(container.items).toHaveLength(2); - expect(container.items.map(span => span.name).sort()).toEqual([ + expect(container.items.map((span: SerializedStreamedSpan) => span.name).sort()).toEqual([ 'create_agent weather_assistant', 'invoke_agent weather_assistant', ]); - const createAgentSpan = container.items.find(span => span.name === 'create_agent weather_assistant'); + const createAgentSpan = container.items.find( + (span: SerializedStreamedSpan) => span.name === 'create_agent weather_assistant', + ); expect(createAgentSpan).toBeDefined(); expect(createAgentSpan!.status).toBe('ok'); expect(createAgentSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ @@ -48,7 +51,9 @@ it('traces langgraph compile and invoke operations', async ({ signal }) => { value: 'weather_assistant', }); - const invokeAgentSpan = container.items.find(span => span.name === 'invoke_agent weather_assistant'); + const invokeAgentSpan = container.items.find( + (span: SerializedStreamedSpan) => span.name === 'invoke_agent weather_assistant', + ); expect(invokeAgentSpan).toBeDefined(); expect(invokeAgentSpan!.status).toBe('ok'); expect(invokeAgentSpan!.attributes[GEN_AI_OPERATION_NAME_ATTRIBUTE]).toEqual({ diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/openai/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/openai/index.ts index 0a50b60c43a6..ba5ca07ce9e9 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/openai/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/openai/index.ts @@ -19,7 +19,11 @@ export default Sentry.withSentry( }), { async fetch(_request, _env, _ctx) { - const response = await client.chat?.completions?.create({ + // The mock client types `chat` loosely (`Record`), so narrow it to the shape used here. + const completions = ( + client.chat as { completions?: { create: (args: Record) => Promise } } + )?.completions; + const response = await completions?.create({ model: 'gpt-3.5-turbo', messages: [ { role: 'system', content: 'You are a helpful assistant.' }, diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc/index.ts index 8c6ab60fbdd5..07e8a33a1f69 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-do-rpc/index.ts @@ -1,13 +1,12 @@ import * as Sentry from '@sentry/cloudflare'; import { DurableObject } from 'cloudflare:workers'; -import type { RpcTarget } from 'cloudflare:workers'; interface Env { SENTRY_DSN: string; MY_DURABLE_OBJECT: DurableObjectNamespace; } -class MyDurableObjectBase extends DurableObject implements RpcTarget { +class MyDurableObjectBase extends DurableObject { async sayHello(name: string): Promise { return `Hello, ${name}!`; } diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-worker-do-rpc/index-sub-worker.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-worker-do-rpc/index-sub-worker.ts index f9a6fd2ed8ff..ca18a69c530f 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-worker-do-rpc/index-sub-worker.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-worker-do-rpc/index-sub-worker.ts @@ -1,13 +1,12 @@ import * as Sentry from '@sentry/cloudflare'; import { DurableObject } from 'cloudflare:workers'; -import type { RpcTarget } from 'cloudflare:workers'; interface Env { SENTRY_DSN: string; MY_DURABLE_OBJECT: DurableObjectNamespace; } -class MyDurableObjectBase extends DurableObject implements RpcTarget { +class MyDurableObjectBase extends DurableObject { async computeAnswer(): Promise { return 42; } diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-workerentrypoint-rpc/index-sub-worker.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-workerentrypoint-rpc/index-sub-worker.ts index 5e59441803e5..f37d654d9831 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-workerentrypoint-rpc/index-sub-worker.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/worker-workerentrypoint-rpc/index-sub-worker.ts @@ -5,7 +5,7 @@ interface Env { SENTRY_DSN: string; } -class MySubWorkerEntrypointBase extends WorkerEntrypoint { +class MySubWorkerEntrypointBase extends WorkerEntrypoint { async fetch(request: Request): Promise { const url = new URL(request.url); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/index.ts index 222ac72599b2..07e8445ca772 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc-disabled/index.ts @@ -24,11 +24,11 @@ export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry( MyDurableObjectBase, ); -class MyWorkerEntrypointBase extends WorkerEntrypoint { +class MyWorkerEntrypointBase extends WorkerEntrypoint { async fetch(request: Request): Promise { const url = new URL(request.url); - const id = this.env.MY_DURABLE_OBJECT.idFromName('test'); - const stub = this.env.MY_DURABLE_OBJECT.get(id); + const id = (this.env as Env).MY_DURABLE_OBJECT.idFromName('test'); + const stub = (this.env as Env).MY_DURABLE_OBJECT.get(id); if (url.pathname === '/do/hello') { const doResponse = await stub.fetch(new Request('http://do/hello')); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc/index.ts index 63876045722b..7633be9e7c8e 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-do-rpc/index.ts @@ -28,8 +28,8 @@ export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry( class MyWorkerEntrypointBase extends WorkerEntrypoint { async fetch(request: Request): Promise { const url = new URL(request.url); - const id = this.env.MY_DURABLE_OBJECT.idFromName('test'); - const stub = this.env.MY_DURABLE_OBJECT.get(id); + const id = (this.env as Env).MY_DURABLE_OBJECT.idFromName('test'); + const stub = (this.env as Env).MY_DURABLE_OBJECT.get(id); if (url.pathname === '/rpc/hello') { const result = await stub.sayHello('World'); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index-sub-worker.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index-sub-worker.ts index 4ff513ccfd03..97bb6b28b3bd 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index-sub-worker.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index-sub-worker.ts @@ -1,13 +1,12 @@ import * as Sentry from '@sentry/cloudflare'; import { DurableObject, WorkerEntrypoint } from 'cloudflare:workers'; -import type { RpcTarget } from 'cloudflare:workers'; interface Env { SENTRY_DSN: string; MY_DURABLE_OBJECT: DurableObjectNamespace; } -class MyDurableObjectBase extends DurableObject implements RpcTarget { +class MyDurableObjectBase extends DurableObject { async computeAnswer(): Promise { return 42; } @@ -22,13 +21,13 @@ export const MyDurableObject = Sentry.instrumentDurableObjectWithSentry( MyDurableObjectBase, ); -class MySubWorkerEntrypointBase extends WorkerEntrypoint { +class MySubWorkerEntrypointBase extends WorkerEntrypoint { async fetch(request: Request): Promise { const url = new URL(request.url); if (url.pathname === '/call-do') { - const id = this.env.MY_DURABLE_OBJECT.idFromName('test'); - const stub = this.env.MY_DURABLE_OBJECT.get(id); + const id = (this.env as Env).MY_DURABLE_OBJECT.idFromName('test'); + const stub = (this.env as Env).MY_DURABLE_OBJECT.get(id); const result = await stub.computeAnswer(); return new Response(`The answer is ${result}`); } diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index.ts index 19ebc32abc55..40577610004f 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/propagation/workerentrypoint-workerentrypoint-do-rpc/index.ts @@ -6,12 +6,12 @@ interface Env { SUB_WORKER: Fetcher; } -class MyWorkerEntrypointBase extends WorkerEntrypoint { +class MyWorkerEntrypointBase extends WorkerEntrypoint { async fetch(request: Request): Promise { const url = new URL(request.url); if (url.pathname === '/chain') { - const response = await this.env.SUB_WORKER.fetch(new Request('http://fake-host/call-do')); + const response = await (this.env as Env).SUB_WORKER.fetch(new Request('http://fake-host/call-do')); const text = await response.text(); return new Response(text); } diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/als_v6/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/als_v6/index.ts index 1131a873bb44..a5671f317cc5 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/als_v6/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/als_v6/index.ts @@ -27,7 +27,8 @@ export default Sentry.withSentry( content: [{ type: 'text', text: 'Hello from mock AI!' }], warnings: [], }), - }), + // The mock result shape differs from this `ai` version's LanguageModelV3 result type; cast to the mock's expected config. + } as unknown as ConstructorParameters[0]), prompt: 'Where is the first span?', }); diff --git a/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/compat_v6/index.ts b/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/compat_v6/index.ts index ea44319195d3..281d762e5a96 100644 --- a/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/compat_v6/index.ts +++ b/dev-packages/cloudflare-integration-tests/suites/tracing/vercelai/compat_v6/index.ts @@ -27,7 +27,8 @@ export default Sentry.withSentry( content: [{ type: 'text', text: 'Hello from mock AI!' }], warnings: [], }), - }), + // The mock result shape differs from this `ai` version's LanguageModelV3 result type; cast to the mock's expected config. + } as unknown as ConstructorParameters[0]), prompt: 'Where is the first span?', }); diff --git a/dev-packages/cloudflare-integration-tests/tsconfig.json b/dev-packages/cloudflare-integration-tests/tsconfig.json index b93dc5f57c50..f90c59831b76 100644 --- a/dev-packages/cloudflare-integration-tests/tsconfig.json +++ b/dev-packages/cloudflare-integration-tests/tsconfig.json @@ -3,6 +3,10 @@ "include": ["suites/**/*.ts", "*.ts"], + // `suites/prisma` imports a Prisma-generated client (`./generated`) that only exists after codegen, + // so it can't be type-checked as part of the static suite check. + "exclude": ["suites/prisma/**"], + "compilerOptions": { // Although this seems wrong to include `DOM` here, it's necessary to make // global fetch available in tests in lower Node versions.