@outputai/core 0.2.1-next.af8a069.0 → 0.2.1-next.bc8ccee.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.
@@ -16,6 +16,7 @@ const configValues = {
16
16
  namespace: 'default',
17
17
  taskQueue: 'test-queue',
18
18
  catalogId: 'test-catalog',
19
+ grpcProxy: undefined,
19
20
  maxConcurrentWorkflowTaskExecutions: 200,
20
21
  maxConcurrentActivityTaskExecutions: 40,
21
22
  maxCachedWorkflows: 1000,
@@ -52,6 +53,9 @@ vi.mock( './interceptors.js', () => ( { initInterceptors: initInterceptorsMock }
52
53
  const startCatalogMock = vi.fn().mockResolvedValue( undefined );
53
54
  vi.mock( './start_catalog.js', () => ( { startCatalog: startCatalogMock } ) );
54
55
 
56
+ const bootstrapFetchProxyMock = vi.fn();
57
+ vi.mock( './proxy.js', () => ( { bootstrapFetchProxy: bootstrapFetchProxyMock } ) );
58
+
55
59
  const registerShutdownMock = vi.fn();
56
60
  vi.mock( './shutdown.js', () => ( { registerShutdown: registerShutdownMock } ) );
57
61
 
@@ -101,10 +105,12 @@ describe( 'worker/index', () => {
101
105
  expect( createWorkflowsEntryPointMock ).toHaveBeenCalledWith( [] );
102
106
  expect( initTracing ).toHaveBeenCalled();
103
107
  expect( createCatalogMock ).toHaveBeenCalledWith( { workflows: [], activities: {} } );
108
+ expect( bootstrapFetchProxyMock ).toHaveBeenCalled();
104
109
  expect( NativeConnection.connect ).toHaveBeenCalledWith( {
105
110
  address: configValues.address,
106
111
  tls: false,
107
- apiKey: undefined
112
+ apiKey: undefined,
113
+ proxy: undefined
108
114
  } );
109
115
  expect( Worker.create ).toHaveBeenCalledWith( expect.objectContaining( {
110
116
  namespace: configValues.namespace,
@@ -0,0 +1,32 @@
1
+ import { EnvHttpProxyAgent, setGlobalDispatcher } from 'undici';
2
+ import { createChildLogger } from '#logger';
3
+
4
+ const log = createChildLogger( 'Proxy' );
5
+
6
+ /**
7
+ * Routes all `fetch()` calls (including those inside Temporal activities)
8
+ * through an HTTP/HTTPS proxy when standard proxy env vars are set
9
+ * (`HTTPS_PROXY`, `https_proxy`, `HTTP_PROXY`, `http_proxy`). No-op when
10
+ * none are set. Invalid URLs are logged and skipped so the worker keeps
11
+ * running.
12
+ *
13
+ * Call once at worker startup, before any network activity.
14
+ */
15
+ export const bootstrapFetchProxy = () => {
16
+ const proxyUrl = process.env.HTTPS_PROXY || process.env.https_proxy ||
17
+ process.env.HTTP_PROXY || process.env.http_proxy;
18
+
19
+ if ( !proxyUrl ) {
20
+ return;
21
+ }
22
+
23
+ try {
24
+ new URL( proxyUrl );
25
+ } catch {
26
+ log.warn( 'Ignoring invalid proxy URL', { proxyUrl } );
27
+ return;
28
+ }
29
+
30
+ log.info( 'Routing fetch() through HTTP proxy', { proxyUrl } );
31
+ setGlobalDispatcher( new EnvHttpProxyAgent() );
32
+ };
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+
3
+ const mockSetGlobalDispatcher = vi.fn();
4
+ const MockEnvHttpProxyAgent = vi.fn();
5
+
6
+ vi.mock( 'undici', () => ( {
7
+ EnvHttpProxyAgent: MockEnvHttpProxyAgent,
8
+ setGlobalDispatcher: mockSetGlobalDispatcher
9
+ } ) );
10
+
11
+ vi.mock( '#logger', () => ( {
12
+ createChildLogger: () => ( { info: vi.fn(), warn: vi.fn(), error: vi.fn() } )
13
+ } ) );
14
+
15
+ describe( 'worker/proxy', () => {
16
+ const originalEnv = { ...process.env };
17
+
18
+ beforeEach( () => {
19
+ vi.clearAllMocks();
20
+ delete process.env.HTTPS_PROXY;
21
+ delete process.env.https_proxy;
22
+ delete process.env.HTTP_PROXY;
23
+ delete process.env.http_proxy;
24
+ } );
25
+
26
+ afterEach( () => {
27
+ process.env = { ...originalEnv };
28
+ } );
29
+
30
+ it( 'does nothing when no proxy env vars are set', async () => {
31
+ const { bootstrapFetchProxy } = await import( './proxy.js' );
32
+ bootstrapFetchProxy();
33
+
34
+ expect( mockSetGlobalDispatcher ).not.toHaveBeenCalled();
35
+ } );
36
+
37
+ it( 'sets global dispatcher when HTTPS_PROXY is set', async () => {
38
+ process.env.HTTPS_PROXY = 'http://proxy:8080';
39
+ const { bootstrapFetchProxy } = await import( './proxy.js' );
40
+ bootstrapFetchProxy();
41
+
42
+ expect( MockEnvHttpProxyAgent ).toHaveBeenCalled();
43
+ expect( mockSetGlobalDispatcher ).toHaveBeenCalledTimes( 1 );
44
+ } );
45
+
46
+ it( 'sets global dispatcher when HTTP_PROXY is set', async () => {
47
+ process.env.HTTP_PROXY = 'http://proxy:8080';
48
+ const { bootstrapFetchProxy } = await import( './proxy.js' );
49
+ bootstrapFetchProxy();
50
+
51
+ expect( MockEnvHttpProxyAgent ).toHaveBeenCalled();
52
+ expect( mockSetGlobalDispatcher ).toHaveBeenCalledTimes( 1 );
53
+ } );
54
+
55
+ it( 'prefers HTTPS_PROXY over HTTP_PROXY for detection', async () => {
56
+ process.env.HTTPS_PROXY = 'http://secure-proxy:8080';
57
+ process.env.HTTP_PROXY = 'http://plain-proxy:8080';
58
+ const { bootstrapFetchProxy } = await import( './proxy.js' );
59
+ bootstrapFetchProxy();
60
+
61
+ expect( mockSetGlobalDispatcher ).toHaveBeenCalledTimes( 1 );
62
+ } );
63
+
64
+ it( 'does not set global dispatcher when proxy URL is malformed', async () => {
65
+ process.env.HTTPS_PROXY = 'not a url';
66
+ const { bootstrapFetchProxy } = await import( './proxy.js' );
67
+ bootstrapFetchProxy();
68
+
69
+ expect( mockSetGlobalDispatcher ).not.toHaveBeenCalled();
70
+ } );
71
+ } );