@trayio/cdk-runtime 5.24.0 → 5.26.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.
@@ -15,11 +15,15 @@ const fakePollingContext = () => ({
15
15
  connectorName: 'salesforce',
16
16
  connectorVersion: '7.2.0',
17
17
  executionToken: 'exec-jwt',
18
- publicUrl: 'https://trigger.example.test/tab-123',
19
18
  organizationId: 'org-uuid',
20
19
  workspaceId: 'ws-uuid',
21
20
  projectId: '7fa00000-1111-2222-3333-444455556666',
22
21
  });
22
+ const PUBLIC_URL = 'https://trigger.example.test/tab-123';
23
+ const fakePollingInput = (overrides = {}) => ({
24
+ publicUrl: PUBLIC_URL,
25
+ ...overrides,
26
+ });
23
27
  const createFakePollingServiceClient = () => {
24
28
  const registerCalls = [];
25
29
  const deregisterCalls = [];
@@ -42,13 +46,12 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
42
46
  const handler = new CompositeOperationHandler_1.CompositeOperationHandler(handlerFunction);
43
47
  const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollCreate, 'new_records', client);
44
48
  const input = {
49
+ publicUrl: PUBLIC_URL,
45
50
  pollingInterval: { value: 15, unit: PollingTypes_1.PollingIntervalUnit.Minutes },
46
51
  maxFailureCount: 50,
47
52
  initialCursor: { since: 't0' },
48
- operationInput: {
49
- soqlQuery: 'SELECT Id, Name FROM Account',
50
- objectType: 'Account',
51
- },
53
+ soqlQuery: 'SELECT Id, Name FROM Account',
54
+ objectType: 'Account',
52
55
  };
53
56
  const result = await execution.execute(fakePollingContext(), input);
54
57
  expect(result.isSuccess).toBe(true);
@@ -63,7 +66,7 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
63
66
  organizationId: 'org-uuid',
64
67
  workspaceId: 'ws-uuid',
65
68
  projectId: '7fa00000-1111-2222-3333-444455556666',
66
- publicUrl: 'https://trigger.example.test/tab-123',
69
+ publicUrl: PUBLIC_URL,
67
70
  pollingInterval: {
68
71
  value: 15,
69
72
  unit: PollingTypes_1.PollingIntervalUnit.Minutes,
@@ -82,7 +85,7 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
82
85
  const handlerFunction = jest.fn();
83
86
  const handler = new CompositeOperationHandler_1.CompositeOperationHandler(handlerFunction);
84
87
  const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollDestroy, 'new_records_destroy', client);
85
- const result = await execution.execute(fakePollingContext(), {});
88
+ const result = await execution.execute(fakePollingContext(), fakePollingInput());
86
89
  expect(result.isSuccess).toBe(true);
87
90
  expect(handlerFunction).not.toHaveBeenCalled();
88
91
  expect(deregisterCalls).toHaveLength(1);
@@ -91,7 +94,7 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
91
94
  connectorName: 'salesforce',
92
95
  connectorVersion: '7.2.0',
93
96
  registeredHandlerName: 'new_records_destroy',
94
- publicUrl: 'https://trigger.example.test/tab-123',
97
+ publicUrl: PUBLIC_URL,
95
98
  preserveCursor: true,
96
99
  });
97
100
  expect(token).toBe('exec-jwt');
@@ -107,45 +110,88 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
107
110
  expect(error).toMatch(/ctx\.connectorName/);
108
111
  expect(error).toMatch(/ctx\.connectorVersion/);
109
112
  expect(error).toMatch(/ctx\.executionToken/);
110
- expect(error).toMatch(/ctx\.publicUrl/);
111
113
  });
112
- it('fails register when org/workspace/project ctx fields are missing (auth is optional)', async () => {
114
+ it('register succeeds when org/workspace/project ctx fields are missing and forwards them as null', async () => {
113
115
  const { client, registerCalls } = createFakePollingServiceClient();
114
116
  const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
115
117
  const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollCreate, 'new_records', client);
116
- // Base polling ctx is present, but the identity fields the PS register
117
- // payload requires are not. `ctx.auth.authId` is intentionally omitted
118
- // to cover the "no auth" case.
118
+ // Base polling ctx is present, but the identity fields are not. These
119
+ // are best-effort and must not block registration (e.g. agent-driven
120
+ // invocations have no project context). `ctx.auth.authId` is also
121
+ // omitted to cover the "no auth" case.
119
122
  const incompleteCtx = {
120
123
  connectorName: 'x',
121
124
  connectorVersion: '1',
122
125
  executionToken: 'tok',
123
- publicUrl: 'u',
124
126
  };
125
- const result = await execution.execute(incompleteCtx, {});
126
- expect(registerCalls).toHaveLength(0);
127
- expect(result.isFailure).toBe(true);
128
- const error = result._tag === 'Failure' ? result.error.message : '';
129
- expect(error).not.toMatch(/ctx\.auth\.authId/);
130
- expect(error).toMatch(/ctx\.organizationId/);
131
- expect(error).toMatch(/ctx\.workspaceId/);
132
- expect(error).toMatch(/ctx\.projectId/);
127
+ const result = await execution.execute(incompleteCtx, fakePollingInput());
128
+ expect(result.isSuccess).toBe(true);
129
+ expect(registerCalls).toHaveLength(1);
130
+ const [payload] = registerCalls[0];
131
+ expect(payload).toMatchObject({
132
+ authenticationId: null,
133
+ organizationId: null,
134
+ workspaceId: null,
135
+ projectId: null,
136
+ });
133
137
  });
134
138
  it('deregister does NOT require the register-only ctx fields', async () => {
135
139
  const { client, deregisterCalls } = createFakePollingServiceClient();
136
140
  const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
137
141
  const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollDestroy, 'new_records_destroy', client);
138
- // Only the base four ctx fields; auth / org / workspace / project absent.
142
+ // Only the base three ctx fields; auth / org / workspace / project absent.
139
143
  const destroyOnlyCtx = {
140
144
  connectorName: 'x',
141
145
  connectorVersion: '1',
142
146
  executionToken: 'tok',
143
- publicUrl: 'u',
144
147
  };
145
- const result = await execution.execute(destroyOnlyCtx, {});
148
+ const result = await execution.execute(destroyOnlyCtx, fakePollingInput());
146
149
  expect(result.isSuccess).toBe(true);
147
150
  expect(deregisterCalls).toHaveLength(1);
148
151
  });
152
+ it('passes connector-defined input fields through to PS as operationInput, stripping platform fields', async () => {
153
+ const { client, registerCalls } = createFakePollingServiceClient();
154
+ const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
155
+ const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollCreate, 'new_records', client);
156
+ const input = {
157
+ publicUrl: PUBLIC_URL,
158
+ pollingInterval: { value: 5, unit: PollingTypes_1.PollingIntervalUnit.Minutes },
159
+ maxFailureCount: 10,
160
+ initialCursor: 'cur-1',
161
+ soqlQuery: 'SELECT Id FROM Account',
162
+ objectType: 'Account',
163
+ nested: { folderId: 'fld_1', tags: ['a', 'b'] },
164
+ };
165
+ const result = await execution.execute(fakePollingContext(), input);
166
+ expect(result.isSuccess).toBe(true);
167
+ expect(registerCalls).toHaveLength(1);
168
+ const [payload] = registerCalls[0];
169
+ expect(payload.operationInput).toEqual({
170
+ soqlQuery: 'SELECT Id FROM Account',
171
+ objectType: 'Account',
172
+ nested: { folderId: 'fld_1', tags: ['a', 'b'] },
173
+ });
174
+ });
175
+ it('fails register when input.publicUrl is missing', async () => {
176
+ const { client, registerCalls } = createFakePollingServiceClient();
177
+ const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
178
+ const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollCreate, 'new_records', client);
179
+ const result = await execution.execute(fakePollingContext(), {});
180
+ expect(registerCalls).toHaveLength(0);
181
+ expect(result.isFailure).toBe(true);
182
+ const error = result._tag === 'Failure' ? result.error.message : '';
183
+ expect(error).toMatch(/input\.publicUrl/);
184
+ });
185
+ it('fails deregister when input.publicUrl is missing', async () => {
186
+ const { client, deregisterCalls } = createFakePollingServiceClient();
187
+ const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
188
+ const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollDestroy, 'new_records_destroy', client);
189
+ const result = await execution.execute(fakePollingContext(), {});
190
+ expect(deregisterCalls).toHaveLength(0);
191
+ expect(result.isFailure).toBe(true);
192
+ const error = result._tag === 'Failure' ? result.error.message : '';
193
+ expect(error).toMatch(/input\.publicUrl/);
194
+ });
149
195
  it('maps a PollingServiceClient error into an OperationHandlerResult failure', async () => {
150
196
  const client = {
151
197
  register: jest.fn(() => Promise.reject(new Error('boom'))),
@@ -153,7 +199,7 @@ describe('CompositeOperationExecution polling lifecycle branch', () => {
153
199
  };
154
200
  const handler = new CompositeOperationHandler_1.CompositeOperationHandler(jest.fn());
155
201
  const execution = new CompositeOperationExecution_1.CompositeOperationExecution(noopHandlerInvocationFactory, handler, OperationHandler_1.OperationHandlerType.TriggerPollCreate, 'new_records', client);
156
- const result = await execution.execute(fakePollingContext(), {});
202
+ const result = await execution.execute(fakePollingContext(), fakePollingInput());
157
203
  expect(result.isFailure).toBe(true);
158
204
  const message = result._tag === 'Failure' ? result.error.message : '';
159
205
  expect(message).toBe('boom');
@@ -1 +1 @@
1
- {"version":3,"file":"CompositeOperationExecutionPolling.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/CompositeOperationExecutionPolling.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EAEvB,sBAAsB,EAEtB,oBAAoB,EAEpB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+DAA+D,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,MAAM,kDAAkD,CAAC;AAEvF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAExF,MAAM,MAAM,6BAA6B,GAAG,mBAAmB,GAAG;IACjE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAsEF,eAAO,MAAM,kBAAkB,gBACjB,oBAAoB,KAC/B,OAEqD,CAAC;AAoCzD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACxC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EACnD,EAAE,EACF,GAAG,EACF,IAAI,EAAE;IACP,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,EAAE,EAAE,CAAC;IACV,OAAO,EAAE,yBAAyB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,wBAAwB,EAAE,iCAAiC,CAAC;IAC5D,yBAAyB,EAAE,CAAC,CAAC,EAAE,sBAAsB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACpE,cAAc,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,sBAAsB,CAAC,GAAG,CAAC,CAAC;CAC5D,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAiCvC;AAED,wBAAgB,8BAA8B,CAC7C,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClD,IAAI,EAAE;IACP,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACnC,WAAW,EACR,oBAAoB,CAAC,iBAAiB,GACtC,oBAAoB,CAAC,kBAAkB,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,6BAA6B,CAAC;IAC5C,oBAAoB,EAAE,oBAAoB,CAAC;CAC3C,GAAG,OAAO,CAAC,IAAI,CAAC,CAkDhB"}
1
+ {"version":3,"file":"CompositeOperationExecutionPolling.d.ts","sourceRoot":"","sources":["../../../src/connector/operation/CompositeOperationExecutionPolling.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,oBAAoB,EACpB,uBAAuB,EAEvB,sBAAsB,EAEtB,oBAAoB,EAEpB,MAAM,sDAAsD,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+DAA+D,CAAC;AAC1G,OAAO,EAEN,mBAAmB,EACnB,MAAM,kDAAkD,CAAC;AAE1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,iCAAiC,EAAE,MAAM,qCAAqC,CAAC;AAExF,MAAM,MAAM,6BAA6B,GAAG,mBAAmB,GAAG;IACjE,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B,CAAC;AAiGF,eAAO,MAAM,kBAAkB,gBACjB,oBAAoB,KAC/B,OAEqD,CAAC;AAoCzD;;;;;;;GAOG;AACH,wBAAsB,mBAAmB,CACxC,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EACnD,EAAE,EACF,GAAG,EACF,IAAI,EAAE;IACP,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACnC,KAAK,EAAE,EAAE,CAAC;IACV,OAAO,EAAE,yBAAyB,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IAClD,wBAAwB,EAAE,iCAAiC,CAAC;IAC5D,yBAAyB,EAAE,CAAC,CAAC,EAAE,sBAAsB,CAAC,GAAG,CAAC,KAAK,IAAI,CAAC;IACpE,cAAc,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,sBAAsB,CAAC,GAAG,CAAC,CAAC;CAC5D,GAAG,OAAO,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAiCvC;AAED,wBAAgB,8BAA8B,CAC7C,IAAI,SAAS,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,EAClD,IAAI,EAAE;IACP,GAAG,EAAE,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACnC,WAAW,EACR,oBAAoB,CAAC,iBAAiB,GACtC,oBAAoB,CAAC,kBAAkB,CAAC;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,6BAA6B,CAAC;IAC5C,oBAAoB,EAAE,oBAAoB,CAAC;CAC3C,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDhB"}
@@ -2,6 +2,33 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runPollingRegisterOrDeregister = exports.runTriggerPollDedup = exports.isPollingLifecycle = void 0;
4
4
  const OperationHandler_1 = require("@trayio/cdk-dsl/connector/operation/OperationHandler");
5
+ const PollingTypes_1 = require("@trayio/cdk-dsl/connector/operation/PollingTypes");
6
+ /**
7
+ * Field names on a polling trigger input that the runtime owns and must not
8
+ * leak into the `operationInput` blob forwarded to the Polling Service.
9
+ * Mirrors `PLATFORM_POLLING_INPUT_KEYS` from cdk-dsl plus the runtime-only
10
+ * `initialCursor` field that lives on `PollingTriggerInvocationInput`.
11
+ */
12
+ const RUNTIME_POLLING_INPUT_KEYS = new Set([
13
+ ...PollingTypes_1.PLATFORM_POLLING_INPUT_KEYS,
14
+ 'initialCursor',
15
+ ]);
16
+ /**
17
+ * Computes the `operationInput` blob the Polling Service persists for a poll
18
+ * subscription. Connector-specific config (e.g. SOQL query, object type) is
19
+ * authored as top-level fields on the connector's `IN extends
20
+ * PollingTriggerInput`; this strips the platform-managed keys so PS only
21
+ * sees the connector's own config.
22
+ */
23
+ const extractOperationInput = (pollingInput) => {
24
+ const result = {};
25
+ for (const [key, value] of Object.entries(pollingInput)) {
26
+ if (!RUNTIME_POLLING_INPUT_KEYS.has(key)) {
27
+ result[key] = value;
28
+ }
29
+ }
30
+ return result;
31
+ };
5
32
  const requirePollingCtxFields = (ctx) => {
6
33
  const missing = [];
7
34
  if (!ctx.connectorName)
@@ -10,8 +37,6 @@ const requirePollingCtxFields = (ctx) => {
10
37
  missing.push('ctx.connectorVersion');
11
38
  if (!ctx.executionToken)
12
39
  missing.push('ctx.executionToken');
13
- if (!ctx.publicUrl)
14
- missing.push('ctx.publicUrl');
15
40
  if (missing.length > 0) {
16
41
  throw new Error(`polling lifecycle is missing required context fields: ${missing.join(', ')}`);
17
42
  }
@@ -19,29 +44,24 @@ const requirePollingCtxFields = (ctx) => {
19
44
  connectorName: ctx.connectorName,
20
45
  connectorVersion: ctx.connectorVersion,
21
46
  executionToken: ctx.executionToken,
22
- publicUrl: ctx.publicUrl,
23
47
  };
24
48
  };
25
49
  const requirePollingRegisterCtxFields = (ctx) => {
26
50
  const base = requirePollingCtxFields(ctx);
27
- const missing = [];
28
- if (!ctx.organizationId)
29
- missing.push('ctx.organizationId');
30
- if (!ctx.workspaceId)
31
- missing.push('ctx.workspaceId');
32
- if (!ctx.projectId)
33
- missing.push('ctx.projectId');
34
- if (missing.length > 0) {
35
- throw new Error(`polling register is missing required context fields: ${missing.join(', ')}`);
36
- }
37
51
  return {
38
52
  ...base,
39
53
  authenticationId: ctx.auth?.authId ?? null,
40
- organizationId: ctx.organizationId,
41
- workspaceId: ctx.workspaceId,
42
- projectId: ctx.projectId,
54
+ organizationId: ctx.organizationId ?? null,
55
+ workspaceId: ctx.workspaceId ?? null,
56
+ projectId: ctx.projectId ?? null,
43
57
  };
44
58
  };
59
+ const requirePollingPublicUrl = (pollingInput) => {
60
+ if (!pollingInput.publicUrl) {
61
+ throw new Error('polling lifecycle is missing required input field: input.publicUrl');
62
+ }
63
+ return pollingInput.publicUrl;
64
+ };
45
65
  const isPollingLifecycle = (handlerType) => handlerType === OperationHandler_1.OperationHandlerType.TriggerPollCreate ||
46
66
  handlerType === OperationHandler_1.OperationHandlerType.TriggerPollDestroy;
47
67
  exports.isPollingLifecycle = isPollingLifecycle;
@@ -109,6 +129,7 @@ function runPollingRegisterOrDeregister(args) {
109
129
  switch (handlerType) {
110
130
  case OperationHandler_1.OperationHandlerType.TriggerPollCreate: {
111
131
  const registerCtx = requirePollingRegisterCtxFields(ctx);
132
+ const publicUrl = requirePollingPublicUrl(pollingInput);
112
133
  return pollingServiceClient.register({
113
134
  connectorName: registerCtx.connectorName,
114
135
  connectorVersion: registerCtx.connectorVersion,
@@ -117,20 +138,21 @@ function runPollingRegisterOrDeregister(args) {
117
138
  organizationId: registerCtx.organizationId,
118
139
  workspaceId: registerCtx.workspaceId,
119
140
  projectId: registerCtx.projectId,
120
- publicUrl: registerCtx.publicUrl,
141
+ publicUrl,
121
142
  pollingInterval: pollingInput.pollingInterval,
122
143
  maxFailureCount: pollingInput.maxFailureCount,
123
144
  initialCursor: pollingInput.initialCursor,
124
- operationInput: pollingInput.operationInput,
145
+ operationInput: extractOperationInput(pollingInput),
125
146
  }, registerCtx.executionToken);
126
147
  }
127
148
  case OperationHandler_1.OperationHandlerType.TriggerPollDestroy: {
128
149
  const destroyCtx = requirePollingCtxFields(ctx);
150
+ const publicUrl = requirePollingPublicUrl(pollingInput);
129
151
  return pollingServiceClient.deregister({
130
152
  connectorName: destroyCtx.connectorName,
131
153
  connectorVersion: destroyCtx.connectorVersion,
132
154
  registeredHandlerName,
133
- publicUrl: destroyCtx.publicUrl,
155
+ publicUrl,
134
156
  preserveCursor: true,
135
157
  }, destroyCtx.executionToken);
136
158
  }
@@ -5,9 +5,9 @@ export type PollingServiceRegisterPayload = {
5
5
  connectorVersion: string;
6
6
  registeredHandlerName: string;
7
7
  authenticationId: string | null;
8
- organizationId: string;
9
- workspaceId: string;
10
- projectId: string;
8
+ organizationId: string | null;
9
+ workspaceId: string | null;
10
+ projectId: string | null;
11
11
  publicUrl: string;
12
12
  pollingInterval?: PollingInterval;
13
13
  maxFailureCount?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"PollingServiceClient.d.ts","sourceRoot":"","sources":["../../../src/connector/polling/PollingServiceClient.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAGN,eAAe,EAEf,MAAM,kDAAkD,CAAC;AAuB1D,MAAM,MAAM,6BAA6B,GAAG;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACxB,CAAC;AA4BF;;;;GAIG;AACH,qBAAa,oBAAoB;IACpB,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,UAAU;IAEpC,QAAQ,CACb,OAAO,EAAE,6BAA6B,EACtC,cAAc,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAyBV,UAAU,CACf,OAAO,EAAE,+BAA+B,EACxC,cAAc,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;YAaF,QAAQ;CAgCtB"}
1
+ {"version":3,"file":"PollingServiceClient.d.ts","sourceRoot":"","sources":["../../../src/connector/polling/PollingServiceClient.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAE7D,OAAO,EAGN,eAAe,EAEf,MAAM,kDAAkD,CAAC;AAuB1D,MAAM,MAAM,6BAA6B,GAAG;IAC3C,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,+BAA+B,GAAG;IAC7C,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB;;;;OAIG;IACH,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;OAKG;IACH,cAAc,EAAE,OAAO,CAAC;CACxB,CAAC;AA4BF;;;;GAIG;AACH,qBAAa,oBAAoB;IACpB,OAAO,CAAC,UAAU;gBAAV,UAAU,EAAE,UAAU;IAEpC,QAAQ,CACb,OAAO,EAAE,6BAA6B,EACtC,cAAc,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;IAmCV,UAAU,CACf,OAAO,EAAE,+BAA+B,EACxC,cAAc,EAAE,MAAM,GACpB,OAAO,CAAC,IAAI,CAAC;YAaF,QAAQ;CAgCtB"}
@@ -80,15 +80,25 @@ class PollingServiceClient {
80
80
  connectorVersion: payload.connectorVersion,
81
81
  operationName: toCanonicalPollOperationName(payload.registeredHandlerName),
82
82
  authenticationId: payload.authenticationId,
83
- organizationId: payload.organizationId,
84
- workspaceId: payload.workspaceId,
85
- projectId: payload.projectId,
86
83
  publicUrl: payload.publicUrl,
87
84
  interval: intervalMinutes,
88
85
  maxFailureCount,
89
86
  initialCursor: payload.initialCursor ?? null,
90
87
  operationInput: payload.operationInput ?? null,
91
88
  };
89
+ // organizationId / workspaceId / projectId are best-effort identity
90
+ // fields. Some callsites (e.g. agent-driven invocations) don't have a
91
+ // project context, so we omit the keys from the wire payload entirely
92
+ // when they're absent rather than sending `null`.
93
+ if (payload.organizationId) {
94
+ body.organizationId = payload.organizationId;
95
+ }
96
+ if (payload.workspaceId) {
97
+ body.workspaceId = payload.workspaceId;
98
+ }
99
+ if (payload.projectId) {
100
+ body.projectId = payload.projectId;
101
+ }
92
102
  await this.sendJson(Http_1.HttpMethod.Post, executionToken, body);
93
103
  }
94
104
  async deregister(payload, executionToken) {
@@ -182,6 +182,19 @@ describe('PollingServiceClient', () => {
182
182
  const body = captured[0].body;
183
183
  expect(body).toHaveProperty('authenticationId', null);
184
184
  });
185
+ it('omits organizationId, workspaceId, and projectId from the wire body when null', async () => {
186
+ const captured = [];
187
+ const client = new PollingServiceClient_1.PollingServiceClient(createMockHttpClient(captured));
188
+ await client.register(minimalRegister({
189
+ organizationId: null,
190
+ workspaceId: null,
191
+ projectId: null,
192
+ }), 'tok');
193
+ const body = captured[0].body;
194
+ expect(body).not.toHaveProperty('organizationId');
195
+ expect(body).not.toHaveProperty('workspaceId');
196
+ expect(body).not.toHaveProperty('projectId');
197
+ });
185
198
  it('trims trailing slashes from the PS base URL', async () => {
186
199
  process.env[ENV_VAR] = `${BASE_URL}/`;
187
200
  const captured = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trayio/cdk-runtime",
3
- "version": "5.24.0",
3
+ "version": "5.26.0",
4
4
  "description": "A Runtime that executes connector operations defined using the CDK DSL",
5
5
  "exports": {
6
6
  "./*": "./dist/*.js"
@@ -14,10 +14,10 @@
14
14
  "node": ">=18.x"
15
15
  },
16
16
  "dependencies": {
17
- "@trayio/axios": "5.24.0",
18
- "@trayio/cdk-dsl": "5.24.0",
19
- "@trayio/express": "5.24.0",
20
- "@trayio/winston": "5.24.0",
17
+ "@trayio/axios": "5.26.0",
18
+ "@trayio/cdk-dsl": "5.26.0",
19
+ "@trayio/express": "5.26.0",
20
+ "@trayio/winston": "5.26.0",
21
21
  "mime": "3.0.0",
22
22
  "uuid": "9.0.0"
23
23
  },