@walkeros/server-source-gcp 4.0.0 → 4.0.1-next-1778183328892

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.
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # @walkeros/server-source-gcp
2
2
 
3
- Google Cloud Platform server sources for walkerOS - lightweight, single-purpose
4
- runtime adapters for GCP services.
3
+ Google Cloud Platform server sources for walkerOS, lightweight runtime adapters
4
+ for GCP services. Ships two surfaces: the Cloud Functions HTTP handler and
5
+ Pub/Sub (pull subscriber and push webhook).
5
6
 
6
7
  ## Installation
7
8
 
@@ -262,3 +263,216 @@ This source follows the walkerOS patterns:
262
263
 
263
264
  The source's `push` function accepts HTTP requests, transforms them into walker
264
265
  events, and forwards them to the collector for processing by destinations.
266
+
267
+ ---
268
+
269
+ ## Pub/Sub source
270
+
271
+ Subscribes to a Google Cloud Pub/Sub topic and forwards each message to the
272
+ walkerOS collector. Ships in two delivery models:
273
+
274
+ - `sourcePubSubPull`: long-running streaming pull subscriber. Use in containers,
275
+ VMs, or any process that stays alive. Highest throughput.
276
+ - `sourcePubSubPush`: HTTP push webhook handler. Use in serverless deployments
277
+ (Cloud Run, Cloud Functions, Lambda) where there is no long-running process to
278
+ keep a streaming subscriber alive.
279
+
280
+ ### Installation
281
+
282
+ Pub/Sub support is part of `@walkeros/server-source-gcp`. The Pub/Sub SDK is
283
+ declared as a runtime dependency:
284
+
285
+ ```bash
286
+ npm install @walkeros/server-source-gcp
287
+ ```
288
+
289
+ ### Quickstart, pull subscriber
290
+
291
+ ```typescript
292
+ import { sourcePubSubPull } from '@walkeros/server-source-gcp';
293
+ import { startFlow } from '@walkeros/collector';
294
+
295
+ await startFlow({
296
+ sources: {
297
+ pubsub: {
298
+ code: sourcePubSubPull,
299
+ config: {
300
+ settings: {
301
+ projectId: 'my-gcp-project',
302
+ subscription: 'events-sub',
303
+ // Optional: tighten flow control beyond SDK defaults
304
+ flowControl: { maxMessages: 100, maxBytes: 10 * 1024 * 1024 },
305
+ },
306
+ },
307
+ },
308
+ },
309
+ destinations: {
310
+ // Your destinations
311
+ },
312
+ });
313
+ ```
314
+
315
+ The pull source is event-driven: `init()` opens the streaming subscription and
316
+ forwards each delivered message to the collector via `env.push`. The source's
317
+ `push` is a deliberate no-op stub (the framework never calls it). `destroy()`
318
+ closes the subscriber gracefully, honoring `shutdownTimeoutMs` (default 30000).
319
+
320
+ ### Quickstart, push webhook
321
+
322
+ ```typescript
323
+ import express from 'express';
324
+ import { sourcePubSubPush } from '@walkeros/server-source-gcp';
325
+ import { startFlow } from '@walkeros/collector';
326
+
327
+ const { sources } = await startFlow({
328
+ sources: {
329
+ pubsub: {
330
+ code: sourcePubSubPush,
331
+ config: {
332
+ settings: { decoder: 'json' },
333
+ },
334
+ },
335
+ },
336
+ destinations: {
337
+ // Your destinations
338
+ },
339
+ });
340
+
341
+ const app = express();
342
+ app.use(express.json());
343
+ app.post('/pubsub-push', sources.pubsub.push);
344
+ app.listen(8080);
345
+ ```
346
+
347
+ Pub/Sub POSTs each message envelope to `/pubsub-push`. The source decodes the
348
+ envelope, base64-decodes the data field, runs the configured decoder, and
349
+ forwards to the collector. Returns 200 on success, 400 on malformed envelope,
350
+ 401 when OIDC verification fails, 500 on push failure (Pub/Sub will retry per
351
+ the subscription's retry policy).
352
+
353
+ ### Authentication
354
+
355
+ Three modes, in precedence order:
356
+
357
+ 1. **Pre-configured client** (`settings.client`). When you bring your own
358
+ `PubSub` instance with custom auth, this bypasses credentials resolution.
359
+ 2. **Service account JSON** (`settings.credentials`). Pass an object
360
+ `{ client_email, private_key }` or a JSON string the source will parse.
361
+ 3. **Application Default Credentials (ADC)**. The default. Works on GCP compute
362
+ (Cloud Run, GCE, GKE, Cloud Functions) and locally via
363
+ `gcloud auth application-default login`.
364
+
365
+ ```typescript
366
+ // Service account (object form)
367
+ config: {
368
+ settings: {
369
+ projectId: 'my-project',
370
+ subscription: 'events-sub',
371
+ credentials: {
372
+ client_email: 'sa@my-project.iam.gserviceaccount.com',
373
+ private_key: '-----BEGIN PRIVATE KEY-----\n...',
374
+ },
375
+ },
376
+ }
377
+ ```
378
+
379
+ ### Setup, idempotent subscription provisioning
380
+
381
+ `walkeros setup source.<id>` provisions the subscription. Idempotent: safe to
382
+ re-run; `ALREADY_EXISTS` is non-fatal. Drift detection emits `setup.drift`
383
+ warnings without auto-mutating.
384
+
385
+ ```typescript
386
+ config: {
387
+ setup: {
388
+ createTopic: true, // Create the topic if missing (default: false)
389
+ ackDeadlineSeconds: 60,
390
+ deadLetterPolicy: {
391
+ deadLetterTopic: 'events-dlq',
392
+ maxDeliveryAttempts: 5,
393
+ createDeadLetterTopic: true,
394
+ },
395
+ retryPolicy: {
396
+ minimumBackoff: { seconds: 10 },
397
+ maximumBackoff: { seconds: 600 },
398
+ },
399
+ },
400
+ settings: {
401
+ projectId: 'my-project',
402
+ subscription: 'events-sub',
403
+ topic: 'events',
404
+ },
405
+ }
406
+ ```
407
+
408
+ Auto-created topics use the EU multi-region storage policy (`eu-west1`,
409
+ `eu-west3`, `eu-west4`). Operators in non-EU regions should override
410
+ `messageStoragePolicy` per organisation policy.
411
+
412
+ The destination side (`@walkeros/server-destination-gcp`) provisions the topic
413
+ itself; you can use either side's setup for the topic. Subscription provisioning
414
+ is owned exclusively by this source.
415
+
416
+ ### Decoders
417
+
418
+ | Decoder | Behavior |
419
+ | ---------------- | -------------------------------------------------------------------------- |
420
+ | `json` (default) | `JSON.parse(data.toString('utf8'))`. Throws DecoderError on parse failure. |
421
+ | `text` | `data.toString('utf8')`. The text becomes the event payload. |
422
+ | `raw` | The raw `Buffer` is forwarded as-is. |
423
+
424
+ ### Backpressure and flow control
425
+
426
+ The pull subscriber has built-in flow control:
427
+
428
+ - `maxMessages` (default 100): max concurrent in-flight messages.
429
+ - `maxBytes` (default 10 MB): max concurrent in-flight bytes.
430
+
431
+ The subscriber automatically slows down when the collector pushes back. Tune via
432
+ `settings.flowControl`.
433
+
434
+ ### OIDC verification (push mode)
435
+
436
+ Off by default. Enable per push subscription when your endpoint is publicly
437
+ reachable:
438
+
439
+ ```typescript
440
+ config: {
441
+ settings: {
442
+ verifyOidc: true,
443
+ audience: 'https://my-service.example/pubsub-push',
444
+ },
445
+ }
446
+ ```
447
+
448
+ The source verifies the `Authorization: Bearer <jwt>` header against GCP public
449
+ keys via `google-auth-library`. Misconfigured OIDC silently rejects all
450
+ messages, so leave it off when running behind a private network and rely on
451
+ network isolation instead.
452
+
453
+ ### Emulator
454
+
455
+ Both pull and push honor `PUBSUB_EMULATOR_HOST`. For explicit configuration, set
456
+ `settings.apiEndpoint`:
457
+
458
+ ```typescript
459
+ config: {
460
+ settings: {
461
+ projectId: 'my-project',
462
+ subscription: 'events-sub',
463
+ apiEndpoint: 'localhost:8085',
464
+ },
465
+ }
466
+ ```
467
+
468
+ ### Troubleshooting
469
+
470
+ - **Subscription not found / unauthorized.** The pull source logs a canonical
471
+ hint:
472
+ `Pub/Sub subscription "X" not found or unauthorized in project "Y". Run "walkeros setup source.<id>" to create it.`
473
+ Run setup or grant `roles/pubsub.subscriber` to the runtime service account.
474
+ - **JSON decode failures.** Default `onPushError: 'nack'` redelivers; set
475
+ `onPushError: 'ack'` to drop instead. Switch to `decoder: 'raw'` if your
476
+ payloads are binary (Avro, Protobuf, etc.) and decode in a transformer.
477
+ - **Push 401 with OIDC enabled.** Verify the audience matches your endpoint URL
478
+ exactly. Pub/Sub signs tokens with the configured audience.
package/dist/dev.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { Source, Flow, Trigger } from '@walkeros/core';
2
2
  import * as _walkeros_core_dev from '@walkeros/core/dev';
3
3
  import { z } from '@walkeros/core/dev';
4
+ import { PubSub } from '@google-cloud/pubsub';
4
5
 
5
6
  /**
6
7
  * HTTP methods enum
@@ -46,7 +47,7 @@ type CorsOptions = z.infer<typeof CorsOptionsSchema>;
46
47
  /**
47
48
  * GCP CloudFunction source settings schema
48
49
  */
49
- declare const SettingsSchema: z.ZodObject<{
50
+ declare const SettingsSchema$2: z.ZodObject<{
50
51
  cors: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
51
52
  origin: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>>;
52
53
  methods: z.ZodOptional<z.ZodArray<z.ZodEnum<{
@@ -64,19 +65,16 @@ declare const SettingsSchema: z.ZodObject<{
64
65
  }, z.core.$strip>]>>;
65
66
  timeout: z.ZodOptional<z.ZodNumber>;
66
67
  }, z.core.$strip>;
67
- type Settings = z.infer<typeof SettingsSchema>;
68
+ type Settings$2 = z.infer<typeof SettingsSchema$2>;
68
69
 
69
- declare const settings: _walkeros_core_dev.JSONSchema;
70
+ declare const settings$2: _walkeros_core_dev.JSONSchema;
70
71
 
71
- type index$1_CorsOptions = CorsOptions;
72
- declare const index$1_CorsOptionsSchema: typeof CorsOptionsSchema;
73
- declare const index$1_CorsOrigin: typeof CorsOrigin;
74
- declare const index$1_HttpMethod: typeof HttpMethod;
75
- type index$1_Settings = Settings;
76
- declare const index$1_SettingsSchema: typeof SettingsSchema;
77
- declare const index$1_settings: typeof settings;
78
- declare namespace index$1 {
79
- export { type index$1_CorsOptions as CorsOptions, index$1_CorsOptionsSchema as CorsOptionsSchema, index$1_CorsOrigin as CorsOrigin, index$1_HttpMethod as HttpMethod, type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
72
+ type index$5_CorsOptions = CorsOptions;
73
+ declare const index$5_CorsOptionsSchema: typeof CorsOptionsSchema;
74
+ declare const index$5_CorsOrigin: typeof CorsOrigin;
75
+ declare const index$5_HttpMethod: typeof HttpMethod;
76
+ declare namespace index$5 {
77
+ export { type index$5_CorsOptions as CorsOptions, index$5_CorsOptionsSchema as CorsOptionsSchema, index$5_CorsOrigin as CorsOrigin, index$5_HttpMethod as HttpMethod, type Settings$2 as Settings, SettingsSchema$2 as SettingsSchema, settings$2 as settings };
80
78
  }
81
79
 
82
80
  declare module '@walkeros/core' {
@@ -87,21 +85,21 @@ declare module '@walkeros/core' {
87
85
  };
88
86
  }
89
87
  }
90
- interface Request {
88
+ interface Request$1 {
91
89
  method: string;
92
90
  body?: unknown;
93
91
  headers: Record<string, string | string[]>;
94
92
  get(name: string): string | undefined;
95
93
  }
96
- interface Response {
97
- status(code: number): Response;
98
- json(body: unknown): Response;
99
- send(body?: unknown): Response;
100
- set(key: string, value: string): Response;
94
+ interface Response$1 {
95
+ status(code: number): Response$1;
96
+ json(body: unknown): Response$1;
97
+ send(body?: unknown): Response$1;
98
+ set(key: string, value: string): Response$1;
101
99
  }
102
- interface Env extends Source.Env {
103
- req?: Request;
104
- res?: Response;
100
+ interface Env$2 extends Source.Env {
101
+ req?: Request$1;
102
+ res?: Response$1;
105
103
  }
106
104
 
107
105
  /**
@@ -110,28 +108,27 @@ interface Env extends Source.Env {
110
108
  * Use this for testing HTTP event ingestion and request/response handling
111
109
  * without requiring a real GCP Cloud Function environment.
112
110
  */
113
- declare const push: Env;
111
+ declare const push$2: Env$2;
114
112
 
115
- declare const env_push: typeof push;
116
- declare namespace env {
117
- export { env_push as push };
113
+ declare namespace env$2 {
114
+ export { push$2 as push };
118
115
  }
119
116
 
120
117
  declare const postEvent: Flow.StepExample;
121
118
  declare const orderEvent: Flow.StepExample;
122
119
 
123
- declare const step_orderEvent: typeof orderEvent;
124
- declare const step_postEvent: typeof postEvent;
125
- declare namespace step {
126
- export { step_orderEvent as orderEvent, step_postEvent as postEvent };
120
+ declare const step$2_orderEvent: typeof orderEvent;
121
+ declare const step$2_postEvent: typeof postEvent;
122
+ declare namespace step$2 {
123
+ export { step$2_orderEvent as orderEvent, step$2_postEvent as postEvent };
127
124
  }
128
125
 
129
- interface Content {
126
+ interface Content$2 {
130
127
  method: string;
131
128
  body: Record<string, unknown>;
132
129
  headers?: Record<string, string>;
133
130
  }
134
- interface Result {
131
+ interface Result$2 {
135
132
  status: number;
136
133
  body: unknown;
137
134
  }
@@ -143,13 +140,273 @@ interface Result {
143
140
  * This is the realistic approach for GCP Cloud Functions - the Functions Framework
144
141
  * synthesizes these objects in production too.
145
142
  */
143
+ declare const createTrigger$2: Trigger.CreateFn<Content$2, Result$2>;
144
+
145
+ declare namespace index$4 {
146
+ export { createTrigger$2 as createTrigger, env$2 as env, step$2 as step };
147
+ }
148
+
149
+ /**
150
+ * GCP Pub/Sub pull source settings schema.
151
+ *
152
+ * Required: projectId, subscription. All other fields optional with sensible
153
+ * defaults applied at runtime by `getConfig`.
154
+ */
155
+ declare const SettingsSchema$1: z.ZodObject<{
156
+ client: z.ZodOptional<z.ZodAny>;
157
+ projectId: z.ZodString;
158
+ subscription: z.ZodString;
159
+ topic: z.ZodOptional<z.ZodString>;
160
+ credentials: z.ZodOptional<z.ZodAny>;
161
+ apiEndpoint: z.ZodOptional<z.ZodString>;
162
+ decoder: z.ZodOptional<z.ZodEnum<{
163
+ json: "json";
164
+ text: "text";
165
+ raw: "raw";
166
+ }>>;
167
+ flowControl: z.ZodOptional<z.ZodObject<{
168
+ maxMessages: z.ZodOptional<z.ZodNumber>;
169
+ maxBytes: z.ZodOptional<z.ZodNumber>;
170
+ }, z.core.$strip>>;
171
+ ackDeadline: z.ZodOptional<z.ZodNumber>;
172
+ shutdownTimeoutMs: z.ZodOptional<z.ZodNumber>;
173
+ onPushError: z.ZodOptional<z.ZodEnum<{
174
+ nack: "nack";
175
+ ack: "ack";
176
+ }>>;
177
+ }, z.core.$strip>;
178
+ type Settings$1 = z.infer<typeof SettingsSchema$1>;
179
+
180
+ /**
181
+ * GCP Pub/Sub pull source setup schema.
182
+ *
183
+ * Provisioning options for `walkeros setup source.<id>`. Idempotent
184
+ * subscription creation, plus optional topic and dead-letter topic
185
+ * auto-create. Triggered only by the explicit CLI command.
186
+ */
187
+ declare const SetupSchema: z.ZodObject<{
188
+ createTopic: z.ZodOptional<z.ZodBoolean>;
189
+ ackDeadlineSeconds: z.ZodOptional<z.ZodNumber>;
190
+ messageRetentionDuration: z.ZodOptional<z.ZodObject<{
191
+ seconds: z.ZodNumber;
192
+ }, z.core.$strip>>;
193
+ filter: z.ZodOptional<z.ZodString>;
194
+ deadLetterPolicy: z.ZodOptional<z.ZodObject<{
195
+ deadLetterTopic: z.ZodString;
196
+ maxDeliveryAttempts: z.ZodNumber;
197
+ createDeadLetterTopic: z.ZodOptional<z.ZodBoolean>;
198
+ }, z.core.$strip>>;
199
+ retryPolicy: z.ZodOptional<z.ZodObject<{
200
+ minimumBackoff: z.ZodObject<{
201
+ seconds: z.ZodNumber;
202
+ }, z.core.$strip>;
203
+ maximumBackoff: z.ZodObject<{
204
+ seconds: z.ZodNumber;
205
+ }, z.core.$strip>;
206
+ }, z.core.$strip>>;
207
+ enableMessageOrdering: z.ZodOptional<z.ZodBoolean>;
208
+ labels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
209
+ expirationPolicy: z.ZodOptional<z.ZodObject<{
210
+ ttl: z.ZodOptional<z.ZodNullable<z.ZodObject<{
211
+ seconds: z.ZodNumber;
212
+ }, z.core.$strip>>>;
213
+ }, z.core.$strip>>;
214
+ }, z.core.$strip>;
215
+ type Setup = z.infer<typeof SetupSchema>;
216
+
217
+ declare const settings$1: _walkeros_core_dev.JSONSchema;
218
+ declare const setup: _walkeros_core_dev.JSONSchema;
219
+
220
+ type index$3_Setup = Setup;
221
+ declare const index$3_SetupSchema: typeof SetupSchema;
222
+ declare const index$3_setup: typeof setup;
223
+ declare namespace index$3 {
224
+ export { type Settings$1 as Settings, SettingsSchema$1 as SettingsSchema, type index$3_Setup as Setup, index$3_SetupSchema as SetupSchema, settings$1 as settings, index$3_setup as setup };
225
+ }
226
+
227
+ declare module '@walkeros/core' {
228
+ interface SourceMap {
229
+ 'pubsub-pull': {
230
+ type: 'pubsub-pull';
231
+ platform: 'server';
232
+ };
233
+ }
234
+ }
235
+ interface Env$1 extends Source.Env {
236
+ PubSub?: typeof PubSub;
237
+ }
238
+
239
+ /**
240
+ * Standard mock environment for the pull source.
241
+ *
242
+ * `PubSub` is intentionally absent: the canonical pattern is module-level
243
+ * `jest.mock('@google-cloud/pubsub')`, not env-injection.
244
+ */
245
+ declare const push$1: Env$1;
246
+ declare const simulation$1: string[];
247
+
248
+ declare namespace env$1 {
249
+ export { push$1 as push, simulation$1 as simulation };
250
+ }
251
+
252
+ declare const pageView: Flow.StepExample;
253
+ declare const orderComplete: Flow.StepExample;
254
+ declare const decoderText: Flow.StepExample;
255
+ declare const malformedJson: Flow.StepExample;
256
+ declare const malformedJsonAck: Flow.StepExample;
257
+
258
+ declare const step$1_decoderText: typeof decoderText;
259
+ declare const step$1_malformedJson: typeof malformedJson;
260
+ declare const step$1_malformedJsonAck: typeof malformedJsonAck;
261
+ declare const step$1_orderComplete: typeof orderComplete;
262
+ declare const step$1_pageView: typeof pageView;
263
+ declare namespace step$1 {
264
+ export { step$1_decoderText as decoderText, step$1_malformedJson as malformedJson, step$1_malformedJsonAck as malformedJsonAck, step$1_orderComplete as orderComplete, step$1_pageView as pageView };
265
+ }
266
+
267
+ /**
268
+ * Content shape for the pull-source trigger.
269
+ *
270
+ * The trigger synthesizes a message from this partial input and dispatches
271
+ * it through the source's `push()` (the same pipeline the SDK subscriber
272
+ * callback uses). `dataString` is the user-friendly way to provide the
273
+ * message body; the trigger encodes it to a Buffer.
274
+ */
275
+ interface Content$1 {
276
+ id: string;
277
+ dataString: string;
278
+ attributes?: Record<string, string>;
279
+ orderingKey?: string;
280
+ }
281
+ /**
282
+ * Result shape for the pull-source trigger.
283
+ *
284
+ * Returns the recorded ack/nack as `[method, id]` entries, mirroring the
285
+ * destination's `[method, ...args]` recording shape used elsewhere.
286
+ */
287
+ type Result$1 = Array<[string, ...unknown[]]>;
288
+ /**
289
+ * Pub/Sub pull source createTrigger.
290
+ *
291
+ * Boots the collector via startFlow, finds the registered pubsub-pull source,
292
+ * and invokes its `push()` with a synthesized message. The source dispatches
293
+ * the synthetic message through the same handler the SDK subscriber callback
294
+ * uses, exercising the full decode / forward / ack-nack pipeline without
295
+ * touching real Pub/Sub.
296
+ *
297
+ * Matches the convention used by other source triggers (express, lambda,
298
+ * cloudfunction): find the source by type from the collector and call its
299
+ * public `push()` interface.
300
+ */
301
+ declare const createTrigger$1: Trigger.CreateFn<Content$1, Result$1>;
302
+
303
+ declare namespace index$2 {
304
+ export { type Content$1 as Content, type Result$1 as Result, createTrigger$1 as createTrigger, env$1 as env, step$1 as step };
305
+ }
306
+
307
+ /**
308
+ * GCP Pub/Sub push source settings schema.
309
+ *
310
+ * No required fields. The push source is a request-handler; configuration
311
+ * tunables live here, but operators wire `source.push` into their own
312
+ * express/lambda runtime.
313
+ */
314
+ declare const SettingsSchema: z.ZodObject<{
315
+ projectId: z.ZodOptional<z.ZodString>;
316
+ decoder: z.ZodOptional<z.ZodEnum<{
317
+ json: "json";
318
+ text: "text";
319
+ raw: "raw";
320
+ }>>;
321
+ verifyOidc: z.ZodOptional<z.ZodBoolean>;
322
+ audience: z.ZodOptional<z.ZodString>;
323
+ }, z.core.$strip>;
324
+ type Settings = z.infer<typeof SettingsSchema>;
325
+
326
+ declare const settings: _walkeros_core_dev.JSONSchema;
327
+
328
+ type index$1_Settings = Settings;
329
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
330
+ declare const index$1_settings: typeof settings;
331
+ declare namespace index$1 {
332
+ export { type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
333
+ }
334
+
335
+ declare module '@walkeros/core' {
336
+ interface SourceMap {
337
+ 'pubsub-push': {
338
+ type: 'pubsub-push';
339
+ platform: 'server';
340
+ };
341
+ }
342
+ }
343
+ /**
344
+ * Minimal request shape for the push handler. Mirrors the cloudfunction
345
+ * source so operators can wire `sourcePubSubPush` into express, lambda,
346
+ * or any framework that delivers a similar contract.
347
+ */
348
+ interface Request {
349
+ method: string;
350
+ body?: unknown;
351
+ headers: Record<string, string | string[]>;
352
+ get(name: string): string | undefined;
353
+ }
354
+ interface Response {
355
+ status(code: number): Response;
356
+ json(body: unknown): Response;
357
+ send(body?: unknown): Response;
358
+ set(key: string, value: string): Response;
359
+ }
360
+ interface Env extends Source.Env {
361
+ req?: Request;
362
+ res?: Response;
363
+ /** Optional override for OIDC verification. Tests can inject a stub. */
364
+ verifyOidcToken?: (token: string, audience: string) => Promise<{
365
+ sub?: string;
366
+ email?: string;
367
+ }>;
368
+ }
369
+
370
+ declare const push: Env;
371
+ declare const simulation: string[];
372
+
373
+ declare const env_push: typeof push;
374
+ declare const env_simulation: typeof simulation;
375
+ declare namespace env {
376
+ export { env_push as push, env_simulation as simulation };
377
+ }
378
+
379
+ declare const validEnvelope: Flow.StepExample;
380
+ declare const orderEnvelope: Flow.StepExample;
381
+ declare const malformedEnvelope: Flow.StepExample;
382
+
383
+ declare const step_malformedEnvelope: typeof malformedEnvelope;
384
+ declare const step_orderEnvelope: typeof orderEnvelope;
385
+ declare const step_validEnvelope: typeof validEnvelope;
386
+ declare namespace step {
387
+ export { step_malformedEnvelope as malformedEnvelope, step_orderEnvelope as orderEnvelope, step_validEnvelope as validEnvelope };
388
+ }
389
+
390
+ /** Content for the push trigger: a Pub/Sub envelope or any POST body. */
391
+ type Content = Record<string, unknown>;
392
+ /** Result: the recorded HTTP response (`status` + `json` body). */
393
+ type Result = Array<[string, ...unknown[]]>;
394
+ /**
395
+ * Pub/Sub push source createTrigger.
396
+ *
397
+ * Boots the collector via startFlow, builds a fake Request/Response pair
398
+ * from the trigger Content, and invokes the source's HTTP handler. Returns
399
+ * the recorded response as a Result entry.
400
+ */
146
401
  declare const createTrigger: Trigger.CreateFn<Content, Result>;
147
402
 
403
+ type index_Content = Content;
404
+ type index_Result = Result;
148
405
  declare const index_createTrigger: typeof createTrigger;
149
406
  declare const index_env: typeof env;
150
407
  declare const index_step: typeof step;
151
408
  declare namespace index {
152
- export { index_createTrigger as createTrigger, index_env as env, index_step as step };
409
+ export { type index_Content as Content, type index_Result as Result, index_createTrigger as createTrigger, index_env as env, index_step as step };
153
410
  }
154
411
 
155
- export { index as examples, index$1 as schemas };
412
+ export { index$4 as examples, index$2 as pubsubPullExamples, index$3 as pubsubPullSchemas, index as pubsubPushExamples, index$1 as pubsubPushSchemas, index$5 as schemas };