@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/dist/dev.d.ts 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 };
package/dist/dev.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,o=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,a=(e,o)=>{for(var r in o)t(e,r,{get:o[r],enumerable:!0})},i={};a(i,{examples:()=>h,schemas:()=>s}),module.exports=(e=i,((e,a,i,s)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let l of r(a))n.call(e,l)||l===i||t(e,l,{get:()=>a[l],enumerable:!(s=o(a,l))||s.enumerable});return e})(t({},"__esModule",{value:!0}),e));var s={};a(s,{CorsOptionsSchema:()=>m,CorsOrigin:()=>p,HttpMethod:()=>u,SettingsSchema:()=>g,settings:()=>b});var l=require("@walkeros/core/dev"),c=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),u=d.z.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),p=d.z.union([d.z.string(),d.z.array(d.z.string()),d.z.literal("*")]),m=d.z.object({origin:p.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:d.z.array(u).describe("Allowed HTTP methods").optional(),headers:d.z.array(d.z.string()).describe("Allowed request headers").optional(),credentials:d.z.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:d.z.number().int().positive().describe("Preflight cache duration in seconds").optional()}),g=c.z.object({cors:c.z.union([c.z.boolean(),m]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:c.z.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),b=(0,l.zodToSchema)(g),h={};a(h,{createTrigger:()=>j,env:()=>y,step:()=>P});var y={};a(y,{push:()=>O});var v=()=>()=>Promise.resolve({ok:!0}),w=()=>{},f={error:w,warn:w,info:w,debug:w,throw:e=>{throw"string"==typeof e?new Error(e):e},json:w,scope:()=>f},O={get push(){return v()},get command(){return v()},get elb(){return v()},logger:f},P={};a(P,{orderEvent:()=>z,postEvent:()=>T});var T={title:"POST event",description:"A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"page view",data:{title:"Home",url:"https://example.com/"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"page view",data:{title:"Home",url:"https://example.com/"}}]]},z={title:"Order POST",description:"A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}}]]},S=require("@walkeros/collector");var j=async e=>{let t;return{get flow(){return t},trigger:()=>async o=>{if(!t){const o=await(0,S.startFlow)(e);t={collector:o.collector,elb:o.elb}}const r=function(e){for(const t of Object.values(e.sources||{}))if("cloudfunction"===t.type)return t}(t.collector);if(!r)throw new Error("CloudFunction source not found in collector — ensure it is configured in sources");const n={...o.body};n.name&&!n.event&&(n.event=n.name,delete n.name);const a=o.headers||{"content-type":"application/json"},i={method:o.method,body:n,headers:a,get:e=>a[e.toLowerCase()]};let s,l=200;const c={status:e=>(l=e,c),json:e=>(s=e,c),send:e=>(s=e,c),set:()=>c};return await r.push(i,c),{status:l,body:s}}}};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,o=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,i=(e,o)=>{for(var r in o)t(e,r,{get:o[r],enumerable:!0})},n={};i(n,{examples:()=>f,pubsubPullExamples:()=>J,pubsubPullSchemas:()=>T,pubsubPushExamples:()=>oe,pubsubPushSchemas:()=>Y,schemas:()=>a}),module.exports=(e=n,((e,i,n,a)=>{if(i&&"object"==typeof i||"function"==typeof i)for(let c of r(i))s.call(e,c)||c===n||t(e,c,{get:()=>i[c],enumerable:!(a=o(i,c))||a.enumerable});return e})(t({},"__esModule",{value:!0}),e));var a={};i(a,{CorsOptionsSchema:()=>b,CorsOrigin:()=>p,HttpMethod:()=>u,SettingsSchema:()=>m,settings:()=>g});var c=require("@walkeros/core/dev"),l=require("@walkeros/core/dev"),d=require("@walkeros/core/dev"),u=d.z.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),p=d.z.union([d.z.string(),d.z.array(d.z.string()),d.z.literal("*")]),b=d.z.object({origin:p.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:d.z.array(u).describe("Allowed HTTP methods").optional(),headers:d.z.array(d.z.string()).describe("Allowed request headers").optional(),credentials:d.z.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:d.z.number().int().positive().describe("Preflight cache duration in seconds").optional()}),m=l.z.object({cors:l.z.union([l.z.boolean(),b]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:l.z.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),g=(0,c.zodToSchema)(m),f={};i(f,{createTrigger:()=>P,env:()=>h,step:()=>z});var h={};i(h,{push:()=>S});var w=()=>()=>Promise.resolve({ok:!0}),y=()=>{},v={error:y,warn:y,info:y,debug:y,throw:e=>{throw"string"==typeof e?new Error(e):e},json:y,scope:()=>v},S={get push(){return w()},get command(){return w()},get elb(){return w()},logger:v},z={};i(z,{orderEvent:()=>O,postEvent:()=>k});var k={title:"POST event",description:"A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"page view",data:{title:"Home",url:"https://example.com/"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"page view",data:{title:"Home",url:"https://example.com/"}}]]},O={title:"Order POST",description:"A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}}]]},j=require("@walkeros/collector");var P=async e=>{let t;return{get flow(){return t},trigger:()=>async o=>{if(!t){const o=await(0,j.startFlow)(e);t={collector:o.collector,elb:o.elb}}const r=function(e){for(const t of Object.values(e.sources||{}))if("cloudfunction"===t.type)return t}(t.collector);if(!r)throw new Error("CloudFunction source not found in collector — ensure it is configured in sources");const s={...o.body};s.name&&!s.event&&(s.event=s.name,delete s.name);const i=o.headers||{"content-type":"application/json"},n={method:o.method,body:s,headers:i,get:e=>i[e.toLowerCase()]};let a,c=200;const l={status:e=>(c=e,l),json:e=>(a=e,l),send:e=>(a=e,l),set:()=>l};return await r.push(n,l),{status:c,body:a}}}},T={};i(T,{SettingsSchema:()=>E,SetupSchema:()=>A,settings:()=>q,setup:()=>R});var D=require("@walkeros/core/dev"),x=require("@walkeros/core/dev"),E=x.z.object({client:x.z.any().describe("Pre-configured Google Cloud Pub/Sub client (like new PubSub({ projectId })). Bypasses credentials resolution when supplied.").optional(),projectId:x.z.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)."),subscription:x.z.string().min(1).describe("Pub/Sub subscription short name (like events-sub). The full resource name projects/<projectId>/subscriptions/<subscription> is built by the SDK."),topic:x.z.string().describe("Pub/Sub topic short name. Required when setup.createTopic is true; otherwise informational.").optional(),credentials:x.z.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC).").optional(),apiEndpoint:x.z.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),decoder:x.z.enum(["json","text","raw"]).describe("Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.").optional(),flowControl:x.z.object({maxMessages:x.z.number().describe("Maximum in-flight messages. Default: 100.").optional(),maxBytes:x.z.number().describe("Maximum in-flight bytes. Default: 10485760 (10 MB).").optional()}).describe("Subscriber flow control. Tightens the SDK defaults.").optional(),ackDeadline:x.z.number().describe("Subscriber ack deadline in seconds. Default: 60.").optional(),shutdownTimeoutMs:x.z.number().describe("Graceful shutdown timeout in milliseconds. Default: 30000. After this window, destroy() force-closes the subscriber.").optional(),onPushError:x.z.enum(["nack","ack"]).describe("Behavior when forwarding to the collector throws. nack (default) redelivers the message; ack drops it.").optional()}),C=require("@walkeros/core/dev"),A=C.z.object({createTopic:C.z.boolean().describe("Create the topic if it does not exist. Requires settings.topic. Default: false (require pre-existing topic).").optional(),ackDeadlineSeconds:C.z.number().describe("Subscription ack deadline in seconds. Default: 60.").optional(),messageRetentionDuration:C.z.object({seconds:C.z.number().describe("Retention window in seconds. Default: project default.")}).describe("Subscription-level retention configuration.").optional(),filter:C.z.string().describe("Subscription filter expression. Only messages matching this filter are delivered.").optional(),deadLetterPolicy:C.z.object({deadLetterTopic:C.z.string().describe("Dead-letter topic short name."),maxDeliveryAttempts:C.z.number().describe("Maximum delivery attempts before forwarding to the dead-letter topic."),createDeadLetterTopic:C.z.boolean().describe("Auto-create the dead-letter topic if it does not exist. Default: false.").optional()}).describe("Dead-letter policy. Strongly recommended for production.").optional(),retryPolicy:C.z.object({minimumBackoff:C.z.object({seconds:C.z.number().describe("Minimum backoff in seconds.")}),maximumBackoff:C.z.object({seconds:C.z.number().describe("Maximum backoff in seconds.")})}).describe("Subscription retry policy.").optional(),enableMessageOrdering:C.z.boolean().describe("Enable message ordering on the subscription. Default: false.").optional(),labels:C.z.record(C.z.string(),C.z.string()).describe("Subscription labels for organization and billing.").optional(),expirationPolicy:C.z.object({ttl:C.z.object({seconds:C.z.number().describe("TTL in seconds. null means never expire.")}).nullable().optional()}).describe("Subscription expiration policy.").optional()}),q=(0,D.zodToSchema)(E),R=(0,D.zodToSchema)(A),J={};i(J,{createTrigger:()=>X,env:()=>N,step:()=>F});var N={};i(N,{push:()=>B,simulation:()=>L});var M=()=>{},I={error:M,warn:M,info:M,debug:M,throw:e=>{throw"string"==typeof e?new Error(e):e},json:M,scope:()=>I},U=()=>()=>Promise.resolve({ok:!0}),B={get push(){return U()},get command(){return U()},get elb(){return U()},logger:I},L=["PubSub"],F={};i(F,{decoderText:()=>_,malformedJson:()=>K,malformedJsonAck:()=>V,orderComplete:()=>G,pageView:()=>H});var H={title:"Page view",description:"A JSON-encoded page view event arrives on the subscription, decodes successfully, and is acked.",in:{id:"msg-1",dataString:JSON.stringify({name:"page view",data:{title:"Documentation",url:"https://example.com/docs"}}),attributes:{}},out:[["message.ack","msg-1"]]},G={title:"Order complete",description:"A JSON-encoded order event arrives and is acked after successful collector forwarding.",in:{id:"msg-2",dataString:JSON.stringify({name:"order complete",data:{id:"ORD-500",total:199.99,currency:"EUR"}}),attributes:{entity:"order",action:"complete"}},out:[["message.ack","msg-2"]]},_={title:"Text decoder",description:"With decoder=text on the source settings, the message data is forwarded to the collector as a UTF-8 string and acked.",in:{id:"msg-3",dataString:"plain text payload",attributes:{}},out:[["message.ack","msg-3"]]},K={title:"Malformed JSON nack",description:"A non-JSON body with the default json decoder fails to decode; the message is nacked for redelivery.",in:{id:"msg-4",dataString:"not-json{",attributes:{}},out:[["message.nack","msg-4"]]},V={title:"Malformed JSON ack-and-drop",description:"With onPushError=ack on the source settings, a malformed JSON message is acked-and-dropped instead of redelivered.",in:{id:"msg-5",dataString:"not-json{",attributes:{}},out:[["message.ack","msg-5"]]},W=require("@walkeros/collector");function Q(e){if("object"!=typeof e||null===e)return!1;const t=e;return"pubsub-pull"===t.type&&"function"==typeof t.push}var X=async e=>{let t;return{get flow(){return t},trigger:()=>async o=>{if(!t){const o=await(0,W.startFlow)(e);t={collector:o.collector,elb:o.elb}}const r=function(e){for(const t of Object.values(e.sources??{}))if(Q(t))return t}(t.collector);if(!r)throw new Error("pubsub-pull source not registered in collector — ensure it is configured in sources");const s={id:o.id,data:Buffer.from(o.dataString,"utf8"),attributes:o.attributes,orderingKey:o.orderingKey},i=await r.push(s),n=[];return i&&"object"==typeof i&&(i.acked&&n.push(["message.ack",o.id]),i.nacked&&n.push(["message.nack",o.id])),n}}},Y={};i(Y,{SettingsSchema:()=>ee,settings:()=>te});var Z=require("@walkeros/core/dev"),$=require("@walkeros/core/dev"),ee=$.z.object({projectId:$.z.string().describe("Google Cloud Project ID (informational, surfaced in error messages).").optional(),decoder:$.z.enum(["json","text","raw"]).describe("Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.").optional(),verifyOidc:$.z.boolean().describe("Verify the OIDC bearer token Pub/Sub attaches to push requests. Default: false.").optional(),audience:$.z.string().describe("OIDC audience (your endpoint URL or a custom audience). Required when verifyOidc is true.").optional()}),te=(0,Z.zodToSchema)(ee),oe={};i(oe,{createTrigger:()=>fe,env:()=>re,step:()=>le});var re={};i(re,{push:()=>ae,simulation:()=>ce});var se=()=>{},ie={error:se,warn:se,info:se,debug:se,throw:e=>{throw"string"==typeof e?new Error(e):e},json:se,scope:()=>ie},ne=()=>()=>Promise.resolve({ok:!0}),ae={get push(){return ne()},get command(){return ne()},get elb(){return ne()},logger:ie},ce=[],le={};i(le,{malformedEnvelope:()=>be,orderEnvelope:()=>pe,validEnvelope:()=>ue});function de(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64")}var ue={title:"Valid push envelope",description:"A well-formed Pub/Sub push envelope decodes the base64 data, parses JSON, and forwards the event to the collector with a 200 response.",in:{message:{messageId:"push-1",data:de({name:"page view",data:{title:"Documentation",url:"https://example.com/docs"}}),attributes:{source:"analytics"}},subscription:"projects/test/subscriptions/events-sub"},out:[["response",200,{success:!0,id:"push-1"}]]},pe={title:"Order envelope",description:"A push envelope carrying an order event is decoded and forwarded to the collector.",in:{message:{messageId:"push-2",data:de({name:"order complete",data:{id:"ORD-500",total:199.99,currency:"EUR"}}),attributes:{}},subscription:"projects/test/subscriptions/events-sub"},out:[["response",200,{success:!0,id:"push-2"}]]},be={title:"Malformed envelope",description:"A POST body lacking message.messageId returns 400 Bad Request without forwarding to the collector.",in:{not_a:"pubsub envelope"},out:[["response",400,{success:!1,error:"Malformed Pub/Sub envelope (missing message.messageId)."}]]},me=require("@walkeros/collector");function ge(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.type&&"pubsub-push"===t.type&&"function"==typeof t.push}var fe=async e=>{let t;return{get flow(){return t},trigger:(o,r)=>async o=>{if(!t){const o=await(0,me.startFlow)(e);t={collector:o.collector,elb:o.elb}}const s=("object"==typeof r&&null!==r?r:{}).headers??{},i=function(e){for(const t of Object.values(e.sources??{}))if(ge(t))return t}(t.collector);if(!i)throw new Error("pubsub-push source not registered");const n={},a=function(e,t){return{method:"POST",body:e,headers:t,get:e=>t[e.toLowerCase()]??t[e]}}(o,s),c=function(e){const t={status:o=>(e.statusCode=o,t),json:o=>(e.body=o,t),send:o=>(e.body=o,t),set:()=>t};return t}(n);await i.push(a,c);return[["response",n.statusCode??0,n.body??null]]}}};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/cloudfunction/schemas/index.ts","../src/cloudfunction/schemas/settings.ts","../src/cloudfunction/schemas/primitives.ts","../src/cloudfunction/examples/index.ts","../src/cloudfunction/examples/env.ts","../src/cloudfunction/examples/step.ts","../src/cloudfunction/examples/trigger.ts"],"sourcesContent":["export { schemas, examples } from './cloudfunction';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export primitives\nexport * from './primitives';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable and documentation tools)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\nimport { CorsOptionsSchema } from './primitives';\n\n/**\n * GCP CloudFunction source settings schema\n */\nexport const SettingsSchema = z.object({\n cors: z\n .union([z.boolean(), CorsOptionsSchema])\n .describe(\n 'CORS configuration: false = disabled, true = allow all origins, object = custom configuration',\n )\n .optional(),\n\n timeout: z\n .number()\n .int()\n .positive()\n .max(540000) // GCP Cloud Functions max timeout: 9 minutes\n .describe('Request timeout in milliseconds (max: 540000 for GCP)')\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * HTTP methods enum\n */\nexport const HttpMethod = z.enum([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n 'HEAD',\n]);\n\n/**\n * CORS origin configuration\n * Accepts:\n * - '*' for all origins\n * - Single URL string\n * - Array of URL strings\n */\nexport const CorsOrigin = z.union([\n z.string(),\n z.array(z.string()),\n z.literal('*'),\n]);\n\n/**\n * CORS options schema\n * Configuration for Cross-Origin Resource Sharing\n */\nexport const CorsOptionsSchema = z.object({\n origin: CorsOrigin.describe(\n 'Allowed origins (* for all, URL string, or array of URLs)',\n ).optional(),\n\n methods: z.array(HttpMethod).describe('Allowed HTTP methods').optional(),\n\n headers: z.array(z.string()).describe('Allowed request headers').optional(),\n\n credentials: z\n .boolean()\n .describe('Allow credentials (cookies, authorization headers)')\n .optional(),\n\n maxAge: z\n .number()\n .int()\n .positive()\n .describe('Preflight cache duration in seconds')\n .optional(),\n});\n\nexport type CorsOptions = z.infer<typeof CorsOptionsSchema>;\n","export * as env from './env';\nexport * as step from './step';\nexport { createTrigger } from './trigger';\n","import type { Env } from '../types';\nimport type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for GCP Cloud Function source\n *\n * These environments provide standardized mock structures for testing\n * HTTP request handling without requiring actual cloud function deployment.\n */\n\n// Create a properly typed elb/push/command function that returns a promise with PushResult\nconst createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n// Simple no-op logger for demo purposes\nconst noopFn = () => {};\nconst noopLogger: Logger.Instance = {\n error: noopFn,\n warn: noopFn,\n info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noopFn,\n scope: () => noopLogger,\n};\n\n/**\n * Standard mock environment for testing cloud function source\n *\n * Use this for testing HTTP event ingestion and request/response handling\n * without requiring a real GCP Cloud Function environment.\n */\nexport const push: Env = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n logger: noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const postEvent: Flow.StepExample = {\n title: 'POST event',\n description:\n 'A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.',\n trigger: { type: 'POST' },\n in: {\n method: 'POST',\n body: {\n event: 'page view',\n data: { title: 'Home', url: 'https://example.com/' },\n },\n headers: { 'content-type': 'application/json' },\n },\n out: [\n [\n 'elb',\n {\n name: 'page view',\n data: { title: 'Home', url: 'https://example.com/' },\n },\n ],\n ],\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order POST',\n description:\n 'A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.',\n trigger: { type: 'POST' },\n in: {\n method: 'POST',\n body: {\n event: 'order complete',\n data: { id: 'ORD-700', total: 99.99, currency: 'EUR' },\n },\n headers: { 'content-type': 'application/json' },\n },\n out: [\n [\n 'elb',\n {\n name: 'order complete',\n data: { id: 'ORD-700', total: 99.99, currency: 'EUR' },\n },\n ],\n ],\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport type { CloudFunctionSource, Request, Response } from '../types';\nimport { startFlow } from '@walkeros/collector';\n\nexport interface Content {\n method: string;\n body: Record<string, unknown>;\n headers?: Record<string, string>;\n}\n\nexport interface Result {\n status: number;\n body: unknown;\n}\n\n/**\n * Find the cloudfunction source instance from collector.sources.\n */\nfunction findGcpSource(\n collector: Collector.Instance,\n): CloudFunctionSource | undefined {\n for (const source of Object.values(collector.sources || {})) {\n if ((source as { type?: string }).type === 'cloudfunction')\n return source as unknown as CloudFunctionSource;\n }\n return undefined;\n}\n\n/**\n * GCP CloudFunction source createTrigger.\n *\n * Boots a real collector via startFlow, then synthesizes mock req/res\n * (matching the GCP Functions Framework pattern) and calls source.push(req, res).\n * This is the realistic approach for GCP Cloud Functions - the Functions Framework\n * synthesizes these objects in production too.\n */\nconst createTrigger: Trigger.CreateFn<Content, Result> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Content, Result> =\n () =>\n async (content: Content): Promise<Result> => {\n // Lazy startFlow\n if (!flow) {\n const result = await startFlow(config);\n flow = { collector: result.collector, elb: result.elb };\n }\n\n const source = findGcpSource(flow.collector);\n if (!source)\n throw new Error(\n 'CloudFunction source not found in collector — ensure it is configured in sources',\n );\n\n // Adapt body: step examples use `name`, source expects `event`\n const body = { ...content.body };\n if (body.name && !body.event) {\n body.event = body.name;\n delete body.name;\n }\n\n const headers = content.headers || {\n 'content-type': 'application/json',\n };\n\n // Synthesize mock req matching GCP Functions Framework pattern\n const req = {\n method: content.method,\n body,\n headers,\n get: (h: string) => headers[h.toLowerCase()],\n } as Request;\n\n // Synthesize mock res that captures status and response body\n let statusCode = 200;\n let responseBody: unknown;\n const res = {\n status: (code: number) => {\n statusCode = code;\n return res;\n },\n json: (data: unknown) => {\n responseBody = data;\n return res;\n },\n send: (data: unknown) => {\n responseBody = data;\n return res;\n },\n set: () => res,\n } as unknown as Response;\n\n // GCP source awaits env.push() — no detached promises\n await source.push(req, res);\n\n return { status: statusCode, body: responseBody };\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\nexport { createTrigger };\n"],"mappings":"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","names":["import_dev","import_dev"]}
1
+ {"version":3,"sources":["../src/dev.ts","../src/cloudfunction/schemas/index.ts","../src/cloudfunction/schemas/settings.ts","../src/cloudfunction/schemas/primitives.ts","../src/cloudfunction/examples/index.ts","../src/cloudfunction/examples/env.ts","../src/cloudfunction/examples/step.ts","../src/cloudfunction/examples/trigger.ts","../src/pubsub/pull/schemas/index.ts","../src/pubsub/pull/schemas/settings.ts","../src/pubsub/pull/schemas/setup.ts","../src/pubsub/pull/examples/index.ts","../src/pubsub/pull/examples/env.ts","../src/pubsub/pull/examples/step.ts","../src/pubsub/pull/examples/trigger.ts","../src/pubsub/push/schemas/index.ts","../src/pubsub/push/schemas/settings.ts","../src/pubsub/push/examples/index.ts","../src/pubsub/push/examples/env.ts","../src/pubsub/push/examples/step.ts","../src/pubsub/push/examples/trigger.ts"],"sourcesContent":["export { schemas, examples } from './cloudfunction';\nexport * as pubsubPullSchemas from './pubsub/pull/schemas';\nexport * as pubsubPullExamples from './pubsub/pull/examples';\nexport * as pubsubPushSchemas from './pubsub/push/schemas';\nexport * as pubsubPushExamples from './pubsub/push/examples';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\n// Export primitives\nexport * from './primitives';\n\n// Export Zod schemas and types\nexport { SettingsSchema, type Settings } from './settings';\n\n// JSON Schema exports (for website PropertyTable and documentation tools)\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\nimport { CorsOptionsSchema } from './primitives';\n\n/**\n * GCP CloudFunction source settings schema\n */\nexport const SettingsSchema = z.object({\n cors: z\n .union([z.boolean(), CorsOptionsSchema])\n .describe(\n 'CORS configuration: false = disabled, true = allow all origins, object = custom configuration',\n )\n .optional(),\n\n timeout: z\n .number()\n .int()\n .positive()\n .max(540000) // GCP Cloud Functions max timeout: 9 minutes\n .describe('Request timeout in milliseconds (max: 540000 for GCP)')\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * HTTP methods enum\n */\nexport const HttpMethod = z.enum([\n 'GET',\n 'POST',\n 'PUT',\n 'PATCH',\n 'DELETE',\n 'OPTIONS',\n 'HEAD',\n]);\n\n/**\n * CORS origin configuration\n * Accepts:\n * - '*' for all origins\n * - Single URL string\n * - Array of URL strings\n */\nexport const CorsOrigin = z.union([\n z.string(),\n z.array(z.string()),\n z.literal('*'),\n]);\n\n/**\n * CORS options schema\n * Configuration for Cross-Origin Resource Sharing\n */\nexport const CorsOptionsSchema = z.object({\n origin: CorsOrigin.describe(\n 'Allowed origins (* for all, URL string, or array of URLs)',\n ).optional(),\n\n methods: z.array(HttpMethod).describe('Allowed HTTP methods').optional(),\n\n headers: z.array(z.string()).describe('Allowed request headers').optional(),\n\n credentials: z\n .boolean()\n .describe('Allow credentials (cookies, authorization headers)')\n .optional(),\n\n maxAge: z\n .number()\n .int()\n .positive()\n .describe('Preflight cache duration in seconds')\n .optional(),\n});\n\nexport type CorsOptions = z.infer<typeof CorsOptionsSchema>;\n","export * as env from './env';\nexport * as step from './step';\nexport { createTrigger } from './trigger';\n","import type { Env } from '../types';\nimport type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment configurations for GCP Cloud Function source\n *\n * These environments provide standardized mock structures for testing\n * HTTP request handling without requiring actual cloud function deployment.\n */\n\n// Create a properly typed elb/push/command function that returns a promise with PushResult\nconst createMockElbFn = (): Elb.Fn => {\n const fn = (() =>\n Promise.resolve({\n ok: true,\n })) as Elb.Fn;\n return fn;\n};\n\n// Simple no-op logger for demo purposes\nconst noopFn = () => {};\nconst noopLogger: Logger.Instance = {\n error: noopFn,\n warn: noopFn,\n info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noopFn,\n scope: () => noopLogger,\n};\n\n/**\n * Standard mock environment for testing cloud function source\n *\n * Use this for testing HTTP event ingestion and request/response handling\n * without requiring a real GCP Cloud Function environment.\n */\nexport const push: Env = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n logger: noopLogger,\n};\n","import type { Flow } from '@walkeros/core';\n\nexport const postEvent: Flow.StepExample = {\n title: 'POST event',\n description:\n 'A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.',\n trigger: { type: 'POST' },\n in: {\n method: 'POST',\n body: {\n event: 'page view',\n data: { title: 'Home', url: 'https://example.com/' },\n },\n headers: { 'content-type': 'application/json' },\n },\n out: [\n [\n 'elb',\n {\n name: 'page view',\n data: { title: 'Home', url: 'https://example.com/' },\n },\n ],\n ],\n};\n\nexport const orderEvent: Flow.StepExample = {\n title: 'Order POST',\n description:\n 'A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.',\n trigger: { type: 'POST' },\n in: {\n method: 'POST',\n body: {\n event: 'order complete',\n data: { id: 'ORD-700', total: 99.99, currency: 'EUR' },\n },\n headers: { 'content-type': 'application/json' },\n },\n out: [\n [\n 'elb',\n {\n name: 'order complete',\n data: { id: 'ORD-700', total: 99.99, currency: 'EUR' },\n },\n ],\n ],\n};\n","import type { Trigger, Collector } from '@walkeros/core';\nimport type { CloudFunctionSource, Request, Response } from '../types';\nimport { startFlow } from '@walkeros/collector';\n\nexport interface Content {\n method: string;\n body: Record<string, unknown>;\n headers?: Record<string, string>;\n}\n\nexport interface Result {\n status: number;\n body: unknown;\n}\n\n/**\n * Find the cloudfunction source instance from collector.sources.\n */\nfunction findGcpSource(\n collector: Collector.Instance,\n): CloudFunctionSource | undefined {\n for (const source of Object.values(collector.sources || {})) {\n if ((source as { type?: string }).type === 'cloudfunction')\n return source as unknown as CloudFunctionSource;\n }\n return undefined;\n}\n\n/**\n * GCP CloudFunction source createTrigger.\n *\n * Boots a real collector via startFlow, then synthesizes mock req/res\n * (matching the GCP Functions Framework pattern) and calls source.push(req, res).\n * This is the realistic approach for GCP Cloud Functions - the Functions Framework\n * synthesizes these objects in production too.\n */\nconst createTrigger: Trigger.CreateFn<Content, Result> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Content, Result> =\n () =>\n async (content: Content): Promise<Result> => {\n // Lazy startFlow\n if (!flow) {\n const result = await startFlow(config);\n flow = { collector: result.collector, elb: result.elb };\n }\n\n const source = findGcpSource(flow.collector);\n if (!source)\n throw new Error(\n 'CloudFunction source not found in collector — ensure it is configured in sources',\n );\n\n // Adapt body: step examples use `name`, source expects `event`\n const body = { ...content.body };\n if (body.name && !body.event) {\n body.event = body.name;\n delete body.name;\n }\n\n const headers = content.headers || {\n 'content-type': 'application/json',\n };\n\n // Synthesize mock req matching GCP Functions Framework pattern\n const req = {\n method: content.method,\n body,\n headers,\n get: (h: string) => headers[h.toLowerCase()],\n } as Request;\n\n // Synthesize mock res that captures status and response body\n let statusCode = 200;\n let responseBody: unknown;\n const res = {\n status: (code: number) => {\n statusCode = code;\n return res;\n },\n json: (data: unknown) => {\n responseBody = data;\n return res;\n },\n send: (data: unknown) => {\n responseBody = data;\n return res;\n },\n set: () => res,\n } as unknown as Response;\n\n // GCP source awaits env.push() — no detached promises\n await source.push(req, res);\n\n return { status: statusCode, body: responseBody };\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n\nexport { createTrigger };\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { SetupSchema, type Setup } from './setup';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub pull source settings schema.\n *\n * Required: projectId, subscription. All other fields optional with sensible\n * defaults applied at runtime by `getConfig`.\n */\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Pre-configured Google Cloud Pub/Sub client (like new PubSub({ projectId })). Bypasses credentials resolution when supplied.',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project).'),\n subscription: z\n .string()\n .min(1)\n .describe(\n 'Pub/Sub subscription short name (like events-sub). The full resource name projects/<projectId>/subscriptions/<subscription> is built by the SDK.',\n ),\n topic: z\n .string()\n .describe(\n 'Pub/Sub topic short name. Required when setup.createTopic is true; otherwise informational.',\n )\n .optional(),\n credentials: z\n .any()\n .describe(\n 'Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC).',\n )\n .optional(),\n apiEndpoint: z\n .string()\n .describe(\n 'Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).',\n )\n .optional(),\n decoder: z\n .enum(['json', 'text', 'raw'])\n .describe(\n 'Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.',\n )\n .optional(),\n flowControl: z\n .object({\n maxMessages: z\n .number()\n .describe('Maximum in-flight messages. Default: 100.')\n .optional(),\n maxBytes: z\n .number()\n .describe('Maximum in-flight bytes. Default: 10485760 (10 MB).')\n .optional(),\n })\n .describe('Subscriber flow control. Tightens the SDK defaults.')\n .optional(),\n ackDeadline: z\n .number()\n .describe('Subscriber ack deadline in seconds. Default: 60.')\n .optional(),\n shutdownTimeoutMs: z\n .number()\n .describe(\n 'Graceful shutdown timeout in milliseconds. Default: 30000. After this window, destroy() force-closes the subscriber.',\n )\n .optional(),\n onPushError: z\n .enum(['nack', 'ack'])\n .describe(\n 'Behavior when forwarding to the collector throws. nack (default) redelivers the message; ack drops it.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub pull source setup schema.\n *\n * Provisioning options for `walkeros setup source.<id>`. Idempotent\n * subscription creation, plus optional topic and dead-letter topic\n * auto-create. Triggered only by the explicit CLI command.\n */\nexport const SetupSchema = z.object({\n createTopic: z\n .boolean()\n .describe(\n 'Create the topic if it does not exist. Requires settings.topic. Default: false (require pre-existing topic).',\n )\n .optional(),\n ackDeadlineSeconds: z\n .number()\n .describe('Subscription ack deadline in seconds. Default: 60.')\n .optional(),\n messageRetentionDuration: z\n .object({\n seconds: z\n .number()\n .describe('Retention window in seconds. Default: project default.'),\n })\n .describe('Subscription-level retention configuration.')\n .optional(),\n filter: z\n .string()\n .describe(\n 'Subscription filter expression. Only messages matching this filter are delivered.',\n )\n .optional(),\n deadLetterPolicy: z\n .object({\n deadLetterTopic: z.string().describe('Dead-letter topic short name.'),\n maxDeliveryAttempts: z\n .number()\n .describe(\n 'Maximum delivery attempts before forwarding to the dead-letter topic.',\n ),\n createDeadLetterTopic: z\n .boolean()\n .describe(\n 'Auto-create the dead-letter topic if it does not exist. Default: false.',\n )\n .optional(),\n })\n .describe('Dead-letter policy. Strongly recommended for production.')\n .optional(),\n retryPolicy: z\n .object({\n minimumBackoff: z.object({\n seconds: z.number().describe('Minimum backoff in seconds.'),\n }),\n maximumBackoff: z.object({\n seconds: z.number().describe('Maximum backoff in seconds.'),\n }),\n })\n .describe('Subscription retry policy.')\n .optional(),\n enableMessageOrdering: z\n .boolean()\n .describe('Enable message ordering on the subscription. Default: false.')\n .optional(),\n labels: z\n .record(z.string(), z.string())\n .describe('Subscription labels for organization and billing.')\n .optional(),\n expirationPolicy: z\n .object({\n ttl: z\n .object({\n seconds: z\n .number()\n .describe('TTL in seconds. null means never expire.'),\n })\n .nullable()\n .optional(),\n })\n .describe('Subscription expiration policy.')\n .optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\n","export * as env from './env';\nexport * as step from './step';\nexport { createTrigger } from './trigger';\nexport type { Content, Result } from './trigger';\n","import type { Env } from '../types';\nimport type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment for the Pub/Sub pull source.\n *\n * Tests substitute the real SDK via `jest.mock('@google-cloud/pubsub')`,\n * which is the recommended pattern: imports of `@google-cloud/pubsub` get\n * replaced module-wide, no env-injection plumbing required at the call site.\n *\n * The `simulation` list documents which globals the source touches during a\n * simulated run, used by the simulator to know what to stub.\n */\n\nconst noopFn = (): void => undefined;\nconst noopLogger: Logger.Instance = {\n error: noopFn,\n warn: noopFn,\n info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noopFn,\n scope: () => noopLogger,\n};\n\nconst createMockElbFn = (): Elb.Fn => {\n const fn: Elb.Fn = () => Promise.resolve({ ok: true });\n return fn;\n};\n\n/**\n * Standard mock environment for the pull source.\n *\n * `PubSub` is intentionally absent: the canonical pattern is module-level\n * `jest.mock('@google-cloud/pubsub')`, not env-injection.\n */\nexport const push: Env = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n logger: noopLogger,\n};\n\nexport const simulation = ['PubSub'];\n","import type { Flow } from '@walkeros/core';\n\n/**\n * Pub/Sub pull step examples.\n *\n * Each example's `in` is a partial MessageLike (id, data Buffer, attributes,\n * publishTime). The trigger synthesizes the missing fields and invokes the\n * registered message handler. `out` is the array of recorded mock calls\n * produced by the handler. Recording shape is `[method, ...args]`.\n *\n * The `__triggerMessage` helper records each message's terminal state under\n * `message.ack` or `message.nack` so step examples can assert on that.\n */\n\nconst eventPayload = {\n name: 'page view',\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n};\n\nconst orderPayload = {\n name: 'order complete',\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n};\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A JSON-encoded page view event arrives on the subscription, decodes successfully, and is acked.',\n in: {\n id: 'msg-1',\n dataString: JSON.stringify(eventPayload),\n attributes: {},\n },\n out: [['message.ack', 'msg-1']],\n};\n\nexport const orderComplete: Flow.StepExample = {\n title: 'Order complete',\n description:\n 'A JSON-encoded order event arrives and is acked after successful collector forwarding.',\n in: {\n id: 'msg-2',\n dataString: JSON.stringify(orderPayload),\n attributes: { entity: 'order', action: 'complete' },\n },\n out: [['message.ack', 'msg-2']],\n};\n\nexport const decoderText: Flow.StepExample = {\n title: 'Text decoder',\n description:\n 'With decoder=text on the source settings, the message data is forwarded to the collector as a UTF-8 string and acked.',\n in: {\n id: 'msg-3',\n dataString: 'plain text payload',\n attributes: {},\n },\n out: [['message.ack', 'msg-3']],\n};\n\nexport const malformedJson: Flow.StepExample = {\n title: 'Malformed JSON nack',\n description:\n 'A non-JSON body with the default json decoder fails to decode; the message is nacked for redelivery.',\n in: {\n id: 'msg-4',\n dataString: 'not-json{',\n attributes: {},\n },\n out: [['message.nack', 'msg-4']],\n};\n\nexport const malformedJsonAck: Flow.StepExample = {\n title: 'Malformed JSON ack-and-drop',\n description:\n 'With onPushError=ack on the source settings, a malformed JSON message is acked-and-dropped instead of redelivered.',\n in: {\n id: 'msg-5',\n dataString: 'not-json{',\n attributes: {},\n },\n out: [['message.ack', 'msg-5']],\n};\n","import type { Collector, Trigger } from '@walkeros/core';\nimport { startFlow } from '@walkeros/collector';\nimport type { SyntheticMessage, SyntheticPushResult } from '../types';\n\n/**\n * Content shape for the pull-source trigger.\n *\n * The trigger synthesizes a message from this partial input and dispatches\n * it through the source's `push()` (the same pipeline the SDK subscriber\n * callback uses). `dataString` is the user-friendly way to provide the\n * message body; the trigger encodes it to a Buffer.\n */\nexport interface Content {\n id: string;\n dataString: string;\n attributes?: Record<string, string>;\n orderingKey?: string;\n}\n\n/**\n * Result shape for the pull-source trigger.\n *\n * Returns the recorded ack/nack as `[method, id]` entries, mirroring the\n * destination's `[method, ...args]` recording shape used elsewhere.\n */\nexport type Result = Array<[string, ...unknown[]]>;\n\ninterface PubSubPullSourceLike {\n type: string;\n push: (content?: SyntheticMessage) => Promise<SyntheticPushResult | void>;\n}\n\nfunction isPubSubPullSource(value: unknown): value is PubSubPullSourceLike {\n if (typeof value !== 'object' || value === null) return false;\n const candidate: { type?: unknown; push?: unknown } = value;\n return (\n candidate.type === 'pubsub-pull' && typeof candidate.push === 'function'\n );\n}\n\nfunction findSource(\n collector: Collector.Instance,\n): PubSubPullSourceLike | undefined {\n for (const source of Object.values(collector.sources ?? {})) {\n if (isPubSubPullSource(source)) return source;\n }\n return undefined;\n}\n\n/**\n * Pub/Sub pull source createTrigger.\n *\n * Boots the collector via startFlow, finds the registered pubsub-pull source,\n * and invokes its `push()` with a synthesized message. The source dispatches\n * the synthetic message through the same handler the SDK subscriber callback\n * uses, exercising the full decode / forward / ack-nack pipeline without\n * touching real Pub/Sub.\n *\n * Matches the convention used by other source triggers (express, lambda,\n * cloudfunction): find the source by type from the collector and call its\n * public `push()` interface.\n */\nexport const createTrigger: Trigger.CreateFn<Content, Result> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Content, Result> =\n () =>\n async (content: Content): Promise<Result> => {\n if (!flow) {\n const result = await startFlow(config);\n flow = { collector: result.collector, elb: result.elb };\n }\n\n const source = findSource(flow.collector);\n if (!source)\n throw new Error(\n 'pubsub-pull source not registered in collector — ensure it is configured in sources',\n );\n\n const synthetic: SyntheticMessage = {\n id: content.id,\n data: Buffer.from(content.dataString, 'utf8'),\n attributes: content.attributes,\n orderingKey: content.orderingKey,\n };\n\n const result = await source.push(synthetic);\n const recorded: Result = [];\n if (result && typeof result === 'object') {\n if (result.acked) recorded.push(['message.ack', content.id]);\n if (result.nacked) recorded.push(['message.nack', content.id]);\n }\n return recorded;\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\nexport { SettingsSchema, type Settings } from './settings';\n\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub push source settings schema.\n *\n * No required fields. The push source is a request-handler; configuration\n * tunables live here, but operators wire `source.push` into their own\n * express/lambda runtime.\n */\nexport const SettingsSchema = z.object({\n projectId: z\n .string()\n .describe(\n 'Google Cloud Project ID (informational, surfaced in error messages).',\n )\n .optional(),\n decoder: z\n .enum(['json', 'text', 'raw'])\n .describe(\n 'Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.',\n )\n .optional(),\n verifyOidc: z\n .boolean()\n .describe(\n 'Verify the OIDC bearer token Pub/Sub attaches to push requests. Default: false.',\n )\n .optional(),\n audience: z\n .string()\n .describe(\n 'OIDC audience (your endpoint URL or a custom audience). Required when verifyOidc is true.',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as env from './env';\nexport * as step from './step';\nexport { createTrigger } from './trigger';\nexport type { Content, Result } from './trigger';\n","import type { Env } from '../types';\nimport type { Elb, Logger } from '@walkeros/core';\n\n/**\n * Example environment for the Pub/Sub push source.\n *\n * Provides a no-op env compatible with `Source.Env` plus an optional\n * verifyOidcToken stub for tests that exercise OIDC verification.\n */\n\nconst noopFn = () => {};\nconst noopLogger: Logger.Instance = {\n error: noopFn,\n warn: noopFn,\n info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\n json: noopFn,\n scope: () => noopLogger,\n};\n\nconst createMockElbFn = (): Elb.Fn => {\n const fn = (() => Promise.resolve({ ok: true })) as Elb.Fn;\n return fn;\n};\n\nexport const push: Env = {\n get push() {\n return createMockElbFn();\n },\n get command() {\n return createMockElbFn();\n },\n get elb() {\n return createMockElbFn();\n },\n logger: noopLogger,\n};\n\nexport const simulation: string[] = [];\n","import type { Flow } from '@walkeros/core';\n\n/**\n * Pub/Sub push step examples.\n *\n * Each example's `in` is a partial Pub/Sub push envelope (with `message.data`\n * pre-encoded as base64). The trigger constructs an HTTP-like Request from\n * `in` and invokes the source handler. `out` is the recorded HTTP response\n * shape (statusCode + JSON body).\n */\n\nconst eventPayload = {\n name: 'page view',\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n};\n\nconst orderPayload = {\n name: 'order complete',\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n};\n\nfunction encodeData(value: unknown): string {\n return Buffer.from(JSON.stringify(value), 'utf8').toString('base64');\n}\n\nexport const validEnvelope: Flow.StepExample = {\n title: 'Valid push envelope',\n description:\n 'A well-formed Pub/Sub push envelope decodes the base64 data, parses JSON, and forwards the event to the collector with a 200 response.',\n in: {\n message: {\n messageId: 'push-1',\n data: encodeData(eventPayload),\n attributes: { source: 'analytics' },\n },\n subscription: 'projects/test/subscriptions/events-sub',\n },\n out: [['response', 200, { success: true, id: 'push-1' }]],\n};\n\nexport const orderEnvelope: Flow.StepExample = {\n title: 'Order envelope',\n description:\n 'A push envelope carrying an order event is decoded and forwarded to the collector.',\n in: {\n message: {\n messageId: 'push-2',\n data: encodeData(orderPayload),\n attributes: {},\n },\n subscription: 'projects/test/subscriptions/events-sub',\n },\n out: [['response', 200, { success: true, id: 'push-2' }]],\n};\n\nexport const malformedEnvelope: Flow.StepExample = {\n title: 'Malformed envelope',\n description:\n 'A POST body lacking message.messageId returns 400 Bad Request without forwarding to the collector.',\n in: {\n not_a: 'pubsub envelope',\n },\n out: [\n [\n 'response',\n 400,\n {\n success: false,\n error: 'Malformed Pub/Sub envelope (missing message.messageId).',\n },\n ],\n ],\n};\n","import type { Collector, Trigger } from '@walkeros/core';\nimport type { Request, Response } from '../types';\nimport { startFlow } from '@walkeros/collector';\n\n/** Content for the push trigger: a Pub/Sub envelope or any POST body. */\nexport type Content = Record<string, unknown>;\n\n/** Result: the recorded HTTP response (`status` + `json` body). */\nexport type Result = Array<[string, ...unknown[]]>;\n\ninterface RecordedResponse {\n statusCode?: number;\n body?: unknown;\n}\n\nfunction buildResponse(state: RecordedResponse): Response {\n const res: Response = {\n status(code: number) {\n state.statusCode = code;\n return res;\n },\n json(body: unknown) {\n state.body = body;\n return res;\n },\n send(body?: unknown) {\n state.body = body;\n return res;\n },\n set() {\n return res;\n },\n };\n return res;\n}\n\nfunction buildRequest(\n content: Content,\n headers: Record<string, string>,\n): Request {\n return {\n method: 'POST',\n body: content,\n headers,\n get(name: string) {\n const value = headers[name.toLowerCase()] ?? headers[name];\n return value;\n },\n };\n}\n\ninterface TriggerOptions {\n headers?: Record<string, string>;\n}\n\ninterface PushCapableSource {\n type: string;\n push: (req: Request, res: Response) => Promise<void>;\n}\n\nfunction isPushCapableSource(value: unknown): value is PushCapableSource {\n if (typeof value !== 'object' || value === null) return false;\n const candidate: { type?: unknown; push?: unknown } = value;\n return (\n typeof candidate.type === 'string' &&\n candidate.type === 'pubsub-push' &&\n typeof candidate.push === 'function'\n );\n}\n\nfunction findPushSource(\n collector: Collector.Instance,\n): PushCapableSource | undefined {\n for (const source of Object.values(collector.sources ?? {})) {\n if (isPushCapableSource(source)) return source;\n }\n return undefined;\n}\n\n/**\n * Pub/Sub push source createTrigger.\n *\n * Boots the collector via startFlow, builds a fake Request/Response pair\n * from the trigger Content, and invokes the source's HTTP handler. Returns\n * the recorded response as a Result entry.\n */\nexport const createTrigger: Trigger.CreateFn<Content, Result> = async (\n config: Collector.InitConfig,\n) => {\n let flow: Trigger.FlowHandle | undefined;\n\n const trigger: Trigger.Fn<Content, Result> =\n (_type, options) =>\n async (content: Content): Promise<Result> => {\n if (!flow) {\n const result = await startFlow(config);\n flow = { collector: result.collector, elb: result.elb };\n }\n\n const triggerOptions: TriggerOptions =\n typeof options === 'object' && options !== null\n ? (options as TriggerOptions)\n : {};\n const headers = triggerOptions.headers ?? {};\n\n const source = findPushSource(flow.collector);\n if (!source) throw new Error('pubsub-push source not registered');\n\n const state: RecordedResponse = {};\n const req = buildRequest(content, headers);\n const res = buildResponse(state);\n\n await source.push(req, res);\n\n const recorded: Result = [\n ['response', state.statusCode ?? 0, state.body ?? null],\n ];\n return recorded;\n };\n\n return {\n get flow() {\n return flow;\n },\n trigger,\n };\n};\n"],"mappings":"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","names":["examples_exports","schemas_exports","import_dev","import_dev","schemas_exports","SettingsSchema","settings","import_dev","import_dev","SettingsSchema","import_dev","settings","SettingsSchema","examples_exports","createTrigger","env_exports","step_exports","env_exports","push","noopFn","noopLogger","createMockElbFn","step_exports","import_collector","createTrigger","result","schemas_exports","SettingsSchema","settings","import_dev","import_dev","SettingsSchema","settings","SettingsSchema","examples_exports","createTrigger","env_exports","step_exports","env_exports","push","simulation","noopFn","noopLogger","createMockElbFn","step_exports","eventPayload","orderPayload","import_collector","createTrigger"]}
package/dist/dev.mjs CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,o=(o,t)=>{for(var r in t)e(o,r,{get:t[r],enumerable:!0})},t={};o(t,{CorsOptionsSchema:()=>l,CorsOrigin:()=>s,HttpMethod:()=>i,SettingsSchema:()=>c,settings:()=>d});import{zodToSchema as r}from"@walkeros/core/dev";import{z as n}from"@walkeros/core/dev";import{z as a}from"@walkeros/core/dev";var i=a.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),s=a.union([a.string(),a.array(a.string()),a.literal("*")]),l=a.object({origin:s.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:a.array(i).describe("Allowed HTTP methods").optional(),headers:a.array(a.string()).describe("Allowed request headers").optional(),credentials:a.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:a.number().int().positive().describe("Preflight cache duration in seconds").optional()}),c=n.object({cors:n.union([n.boolean(),l]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:n.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),d=r(c),u={};o(u,{createTrigger:()=>T,env:()=>p,step:()=>v});var p={};o(p,{push:()=>h});var m=()=>()=>Promise.resolve({ok:!0}),g=()=>{},b={error:g,warn:g,info:g,debug:g,throw:e=>{throw"string"==typeof e?new Error(e):e},json:g,scope:()=>b},h={get push(){return m()},get command(){return m()},get elb(){return m()},logger:b},v={};o(v,{orderEvent:()=>w,postEvent:()=>f});var f={title:"POST event",description:"A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"page view",data:{title:"Home",url:"https://example.com/"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"page view",data:{title:"Home",url:"https://example.com/"}}]]},w={title:"Order POST",description:"A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}}]]};import{startFlow as y}from"@walkeros/collector";var T=async e=>{let o;return{get flow(){return o},trigger:()=>async t=>{if(!o){const t=await y(e);o={collector:t.collector,elb:t.elb}}const r=function(e){for(const o of Object.values(e.sources||{}))if("cloudfunction"===o.type)return o}(o.collector);if(!r)throw new Error("CloudFunction source not found in collector — ensure it is configured in sources");const n={...t.body};n.name&&!n.event&&(n.event=n.name,delete n.name);const a=t.headers||{"content-type":"application/json"},i={method:t.method,body:n,headers:a,get:e=>a[e.toLowerCase()]};let s,l=200;const c={status:e=>(l=e,c),json:e=>(s=e,c),send:e=>(s=e,c),set:()=>c};return await r.push(i,c),{status:l,body:s}}}};export{u as examples,t as schemas};//# sourceMappingURL=dev.mjs.map
1
+ var e=Object.defineProperty,t=(t,o)=>{for(var r in o)e(t,r,{get:o[r],enumerable:!0})},o={};t(o,{CorsOptionsSchema:()=>c,CorsOrigin:()=>a,HttpMethod:()=>n,SettingsSchema:()=>l,settings:()=>d});import{zodToSchema as r}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";import{z as i}from"@walkeros/core/dev";var n=i.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),a=i.union([i.string(),i.array(i.string()),i.literal("*")]),c=i.object({origin:a.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:i.array(n).describe("Allowed HTTP methods").optional(),headers:i.array(i.string()).describe("Allowed request headers").optional(),credentials:i.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:i.number().int().positive().describe("Preflight cache duration in seconds").optional()}),l=s.object({cors:s.union([s.boolean(),c]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:s.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),d=r(l),u={};t(u,{createTrigger:()=>S,env:()=>p,step:()=>h});var p={};t(p,{push:()=>g});var m=()=>()=>Promise.resolve({ok:!0}),b=()=>{},f={error:b,warn:b,info:b,debug:b,throw:e=>{throw"string"==typeof e?new Error(e):e},json:b,scope:()=>f},g={get push(){return m()},get command(){return m()},get elb(){return m()},logger:f},h={};t(h,{orderEvent:()=>v,postEvent:()=>w});var w={title:"POST event",description:"A GCP Cloud Function HTTP POST with a JSON body becomes a single walker elb event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"page view",data:{title:"Home",url:"https://example.com/"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"page view",data:{title:"Home",url:"https://example.com/"}}]]},v={title:"Order POST",description:"A Cloud Function HTTP POST carrying an order payload becomes a walker order complete event.",trigger:{type:"POST"},in:{method:"POST",body:{event:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}},headers:{"content-type":"application/json"}},out:[["elb",{name:"order complete",data:{id:"ORD-700",total:99.99,currency:"EUR"}}]]};import{startFlow as y}from"@walkeros/collector";var S=async e=>{let t;return{get flow(){return t},trigger:()=>async o=>{if(!t){const o=await y(e);t={collector:o.collector,elb:o.elb}}const r=function(e){for(const t of Object.values(e.sources||{}))if("cloudfunction"===t.type)return t}(t.collector);if(!r)throw new Error("CloudFunction source not found in collector — ensure it is configured in sources");const s={...o.body};s.name&&!s.event&&(s.event=s.name,delete s.name);const i=o.headers||{"content-type":"application/json"},n={method:o.method,body:s,headers:i,get:e=>i[e.toLowerCase()]};let a,c=200;const l={status:e=>(c=e,l),json:e=>(a=e,l),send:e=>(a=e,l),set:()=>l};return await r.push(n,l),{status:c,body:a}}}},k={};t(k,{SettingsSchema:()=>P,SetupSchema:()=>D,settings:()=>x,setup:()=>E});import{zodToSchema as j}from"@walkeros/core/dev";import{z as O}from"@walkeros/core/dev";var P=O.object({client:O.any().describe("Pre-configured Google Cloud Pub/Sub client (like new PubSub({ projectId })). Bypasses credentials resolution when supplied.").optional(),projectId:O.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)."),subscription:O.string().min(1).describe("Pub/Sub subscription short name (like events-sub). The full resource name projects/<projectId>/subscriptions/<subscription> is built by the SDK."),topic:O.string().describe("Pub/Sub topic short name. Required when setup.createTopic is true; otherwise informational.").optional(),credentials:O.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC).").optional(),apiEndpoint:O.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),decoder:O.enum(["json","text","raw"]).describe("Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.").optional(),flowControl:O.object({maxMessages:O.number().describe("Maximum in-flight messages. Default: 100.").optional(),maxBytes:O.number().describe("Maximum in-flight bytes. Default: 10485760 (10 MB).").optional()}).describe("Subscriber flow control. Tightens the SDK defaults.").optional(),ackDeadline:O.number().describe("Subscriber ack deadline in seconds. Default: 60.").optional(),shutdownTimeoutMs:O.number().describe("Graceful shutdown timeout in milliseconds. Default: 30000. After this window, destroy() force-closes the subscriber.").optional(),onPushError:O.enum(["nack","ack"]).describe("Behavior when forwarding to the collector throws. nack (default) redelivers the message; ack drops it.").optional()});import{z as T}from"@walkeros/core/dev";var D=T.object({createTopic:T.boolean().describe("Create the topic if it does not exist. Requires settings.topic. Default: false (require pre-existing topic).").optional(),ackDeadlineSeconds:T.number().describe("Subscription ack deadline in seconds. Default: 60.").optional(),messageRetentionDuration:T.object({seconds:T.number().describe("Retention window in seconds. Default: project default.")}).describe("Subscription-level retention configuration.").optional(),filter:T.string().describe("Subscription filter expression. Only messages matching this filter are delivered.").optional(),deadLetterPolicy:T.object({deadLetterTopic:T.string().describe("Dead-letter topic short name."),maxDeliveryAttempts:T.number().describe("Maximum delivery attempts before forwarding to the dead-letter topic."),createDeadLetterTopic:T.boolean().describe("Auto-create the dead-letter topic if it does not exist. Default: false.").optional()}).describe("Dead-letter policy. Strongly recommended for production.").optional(),retryPolicy:T.object({minimumBackoff:T.object({seconds:T.number().describe("Minimum backoff in seconds.")}),maximumBackoff:T.object({seconds:T.number().describe("Maximum backoff in seconds.")})}).describe("Subscription retry policy.").optional(),enableMessageOrdering:T.boolean().describe("Enable message ordering on the subscription. Default: false.").optional(),labels:T.record(T.string(),T.string()).describe("Subscription labels for organization and billing.").optional(),expirationPolicy:T.object({ttl:T.object({seconds:T.number().describe("TTL in seconds. null means never expire.")}).nullable().optional()}).describe("Subscription expiration policy.").optional()}),x=j(P),E=j(D),C={};t(C,{createTrigger:()=>K,env:()=>A,step:()=>U});var A={};t(A,{push:()=>I,simulation:()=>M});var R=()=>{},J={error:R,warn:R,info:R,debug:R,throw:e=>{throw"string"==typeof e?new Error(e):e},json:R,scope:()=>J},N=()=>()=>Promise.resolve({ok:!0}),I={get push(){return N()},get command(){return N()},get elb(){return N()},logger:J},M=["PubSub"],U={};t(U,{decoderText:()=>q,malformedJson:()=>z,malformedJsonAck:()=>F,orderComplete:()=>L,pageView:()=>B});var B={title:"Page view",description:"A JSON-encoded page view event arrives on the subscription, decodes successfully, and is acked.",in:{id:"msg-1",dataString:JSON.stringify({name:"page view",data:{title:"Documentation",url:"https://example.com/docs"}}),attributes:{}},out:[["message.ack","msg-1"]]},L={title:"Order complete",description:"A JSON-encoded order event arrives and is acked after successful collector forwarding.",in:{id:"msg-2",dataString:JSON.stringify({name:"order complete",data:{id:"ORD-500",total:199.99,currency:"EUR"}}),attributes:{entity:"order",action:"complete"}},out:[["message.ack","msg-2"]]},q={title:"Text decoder",description:"With decoder=text on the source settings, the message data is forwarded to the collector as a UTF-8 string and acked.",in:{id:"msg-3",dataString:"plain text payload",attributes:{}},out:[["message.ack","msg-3"]]},z={title:"Malformed JSON nack",description:"A non-JSON body with the default json decoder fails to decode; the message is nacked for redelivery.",in:{id:"msg-4",dataString:"not-json{",attributes:{}},out:[["message.nack","msg-4"]]},F={title:"Malformed JSON ack-and-drop",description:"With onPushError=ack on the source settings, a malformed JSON message is acked-and-dropped instead of redelivered.",in:{id:"msg-5",dataString:"not-json{",attributes:{}},out:[["message.ack","msg-5"]]};import{startFlow as H}from"@walkeros/collector";function G(e){if("object"!=typeof e||null===e)return!1;const t=e;return"pubsub-pull"===t.type&&"function"==typeof t.push}var K=async e=>{let t;return{get flow(){return t},trigger:()=>async o=>{if(!t){const o=await H(e);t={collector:o.collector,elb:o.elb}}const r=function(e){for(const t of Object.values(e.sources??{}))if(G(t))return t}(t.collector);if(!r)throw new Error("pubsub-pull source not registered in collector — ensure it is configured in sources");const s={id:o.id,data:Buffer.from(o.dataString,"utf8"),attributes:o.attributes,orderingKey:o.orderingKey},i=await r.push(s),n=[];return i&&"object"==typeof i&&(i.acked&&n.push(["message.ack",o.id]),i.nacked&&n.push(["message.nack",o.id])),n}}},V={};t(V,{SettingsSchema:()=>Q,settings:()=>X});import{zodToSchema as _}from"@walkeros/core/dev";import{z as W}from"@walkeros/core/dev";var Q=W.object({projectId:W.string().describe("Google Cloud Project ID (informational, surfaced in error messages).").optional(),decoder:W.enum(["json","text","raw"]).describe("Decoder for the message data field. json (default) parses JSON, text decodes UTF-8, raw forwards the Buffer.").optional(),verifyOidc:W.boolean().describe("Verify the OIDC bearer token Pub/Sub attaches to push requests. Default: false.").optional(),audience:W.string().describe("OIDC audience (your endpoint URL or a custom audience). Required when verifyOidc is true.").optional()}),X=_(Q),Y={};t(Y,{createTrigger:()=>ue,env:()=>Z,step:()=>se});var Z={};t(Z,{push:()=>oe,simulation:()=>re});var $=()=>{},ee={error:$,warn:$,info:$,debug:$,throw:e=>{throw"string"==typeof e?new Error(e):e},json:$,scope:()=>ee},te=()=>()=>Promise.resolve({ok:!0}),oe={get push(){return te()},get command(){return te()},get elb(){return te()},logger:ee},re=[],se={};t(se,{malformedEnvelope:()=>ce,orderEnvelope:()=>ae,validEnvelope:()=>ne});function ie(e){return Buffer.from(JSON.stringify(e),"utf8").toString("base64")}var ne={title:"Valid push envelope",description:"A well-formed Pub/Sub push envelope decodes the base64 data, parses JSON, and forwards the event to the collector with a 200 response.",in:{message:{messageId:"push-1",data:ie({name:"page view",data:{title:"Documentation",url:"https://example.com/docs"}}),attributes:{source:"analytics"}},subscription:"projects/test/subscriptions/events-sub"},out:[["response",200,{success:!0,id:"push-1"}]]},ae={title:"Order envelope",description:"A push envelope carrying an order event is decoded and forwarded to the collector.",in:{message:{messageId:"push-2",data:ie({name:"order complete",data:{id:"ORD-500",total:199.99,currency:"EUR"}}),attributes:{}},subscription:"projects/test/subscriptions/events-sub"},out:[["response",200,{success:!0,id:"push-2"}]]},ce={title:"Malformed envelope",description:"A POST body lacking message.messageId returns 400 Bad Request without forwarding to the collector.",in:{not_a:"pubsub envelope"},out:[["response",400,{success:!1,error:"Malformed Pub/Sub envelope (missing message.messageId)."}]]};import{startFlow as le}from"@walkeros/collector";function de(e){if("object"!=typeof e||null===e)return!1;const t=e;return"string"==typeof t.type&&"pubsub-push"===t.type&&"function"==typeof t.push}var ue=async e=>{let t;return{get flow(){return t},trigger:(o,r)=>async o=>{if(!t){const o=await le(e);t={collector:o.collector,elb:o.elb}}const s=("object"==typeof r&&null!==r?r:{}).headers??{},i=function(e){for(const t of Object.values(e.sources??{}))if(de(t))return t}(t.collector);if(!i)throw new Error("pubsub-push source not registered");const n={},a=function(e,t){return{method:"POST",body:e,headers:t,get:e=>t[e.toLowerCase()]??t[e]}}(o,s),c=function(e){const t={status:o=>(e.statusCode=o,t),json:o=>(e.body=o,t),send:o=>(e.body=o,t),set:()=>t};return t}(n);await i.push(a,c);return[["response",n.statusCode??0,n.body??null]]}}};export{u as examples,C as pubsubPullExamples,k as pubsubPullSchemas,Y as pubsubPushExamples,V as pubsubPushSchemas,o as schemas};//# sourceMappingURL=dev.mjs.map