@walkeros/server-source-gcp 0.0.0-next-20251219153324

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 ADDED
@@ -0,0 +1,233 @@
1
+ # @walkeros/server-source-gcp
2
+
3
+ Google Cloud Platform server sources for walkerOS - lightweight, single-purpose
4
+ runtime adapters for GCP services.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ npm install @walkeros/server-source-gcp @google-cloud/functions-framework
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```typescript
15
+ import {
16
+ sourceCloudFunction,
17
+ type SourceCloudFunction,
18
+ } from '@walkeros/server-source-gcp';
19
+ import { startFlow } from '@walkeros/collector';
20
+ import { http } from '@google-cloud/functions-framework';
21
+
22
+ const { elb } = await startFlow<SourceCloudFunction.Push>({
23
+ sources: { api: { code: sourceCloudFunction } },
24
+ });
25
+
26
+ http('walkerHandler', elb);
27
+ ```
28
+
29
+ ---
30
+
31
+ ## Cloud Functions Source
32
+
33
+ The Cloud Functions source provides an HTTP handler that receives walker events
34
+ and forwards them to the walkerOS collector.
35
+
36
+ ### Basic Usage
37
+
38
+ ```typescript
39
+ import {
40
+ sourceCloudFunction,
41
+ type SourceCloudFunction,
42
+ } from '@walkeros/server-source-gcp';
43
+ import { startFlow } from '@walkeros/collector';
44
+ import { http } from '@google-cloud/functions-framework';
45
+
46
+ // Handler singleton - reused across warm invocations
47
+ let handler: SourceCloudFunction.Push;
48
+
49
+ async function setup() {
50
+ if (handler) return handler;
51
+
52
+ const { elb } = await startFlow<SourceCloudFunction.Push>({
53
+ sources: {
54
+ api: {
55
+ code: sourceCloudFunction,
56
+ config: {
57
+ settings: { cors: true },
58
+ },
59
+ },
60
+ },
61
+ destinations: {
62
+ // Your destinations
63
+ },
64
+ });
65
+
66
+ handler = elb;
67
+ return handler;
68
+ }
69
+
70
+ // Register with Cloud Functions framework
71
+ setup().then((h) => http('walkerHandler', h));
72
+ ```
73
+
74
+ ## Bundler Integration
75
+
76
+ Use with minimal config:
77
+
78
+ ```json
79
+ {
80
+ "sources": {
81
+ "api": { "type": "cloudfunction", "cors": true }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Bundler auto-generates deployable exports.
87
+
88
+ ### Configuration Options
89
+
90
+ ```typescript
91
+ interface Settings {
92
+ cors?: boolean | CorsOptions; // Enable CORS (default: true)
93
+ batch?: boolean; // Enable batch processing (default: true)
94
+ maxBatchSize?: number; // Max events per batch (default: 100)
95
+ timeout?: number; // Request timeout (default: 30000ms)
96
+ }
97
+
98
+ interface CorsOptions {
99
+ origin?: string | string[]; // Allowed origins
100
+ methods?: string[]; // Allowed methods
101
+ headers?: string[]; // Allowed headers
102
+ credentials?: boolean; // Allow credentials
103
+ maxAge?: number; // Preflight cache time
104
+ }
105
+ ```
106
+
107
+ ### Request Format
108
+
109
+ **Single Event:**
110
+
111
+ ```json
112
+ {
113
+ "event": "page view",
114
+ "data": {
115
+ "title": "Home Page",
116
+ "path": "/"
117
+ },
118
+ "context": {
119
+ "stage": ["prod", 1]
120
+ }
121
+ }
122
+ ```
123
+
124
+ **Batch Events:**
125
+
126
+ ```json
127
+ {
128
+ "events": [
129
+ {
130
+ "event": "page view",
131
+ "data": { "title": "Page 1" }
132
+ },
133
+ {
134
+ "event": "button click",
135
+ "data": { "id": "btn1" }
136
+ }
137
+ ]
138
+ }
139
+ ```
140
+
141
+ ### Response Format
142
+
143
+ **Success:**
144
+
145
+ ```json
146
+ {
147
+ "success": true,
148
+ "id": "event-id-123"
149
+ }
150
+ ```
151
+
152
+ **Batch Success:**
153
+
154
+ ```json
155
+ {
156
+ "success": true,
157
+ "processed": 2,
158
+ "errors": []
159
+ }
160
+ ```
161
+
162
+ **Error:**
163
+
164
+ ```json
165
+ {
166
+ "success": false,
167
+ "error": "Invalid event format"
168
+ }
169
+ ```
170
+
171
+ ### Deployment
172
+
173
+ The source is designed to work with the walkerOS deployment system:
174
+
175
+ ```json
176
+ {
177
+ "providers": [
178
+ {
179
+ "name": "api-endpoint",
180
+ "type": "gcp-functions",
181
+ "artifact": {
182
+ "source": "bundler",
183
+ "bundle": "api-collector"
184
+ },
185
+ "settings": {
186
+ "functionName": "walker-collector",
187
+ "runtime": "nodejs18",
188
+ "memory": 256
189
+ }
190
+ }
191
+ ]
192
+ }
193
+ ```
194
+
195
+ ### Testing
196
+
197
+ The source uses environment injection for testability:
198
+
199
+ ```typescript
200
+ import { sourceCloudFunction } from '@walkeros/server-source-gcp';
201
+
202
+ const mockElb = jest.fn().mockResolvedValue({
203
+ ok: true,
204
+ event: { id: 'test-id' },
205
+ });
206
+
207
+ const source = await sourceCloudFunction(
208
+ { settings: { cors: false } },
209
+ { elb: mockElb },
210
+ );
211
+
212
+ // Test the handler
213
+ const mockReq = { method: 'POST', body: { event: 'test' } };
214
+ const mockRes = { status: jest.fn().mockReturnThis(), json: jest.fn() };
215
+
216
+ await source.push(mockReq, mockRes);
217
+
218
+ expect(mockElb).toHaveBeenCalledWith('test', {});
219
+ expect(mockRes.status).toHaveBeenCalledWith(200);
220
+ ```
221
+
222
+ ## Architecture
223
+
224
+ This source follows the walkerOS patterns:
225
+
226
+ - **Stateless**: No collector references, communicates via elb function
227
+ - **Environment Injection**: All dependencies provided through environment
228
+ - **Lean Implementation**: Minimal required fields, focused on HTTP handling
229
+ - **Standard Interface**: The `push` function IS the Cloud Function handler
230
+ - **Plug-and-Play**: Direct assignment: `http('handler', source.push)`
231
+
232
+ The source's `push` function accepts HTTP requests, transforms them into walker
233
+ events, and forwards them to the collector for processing by destinations.
@@ -0,0 +1,164 @@
1
+ import { Source, WalkerOS } from '@walkeros/core';
2
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
3
+ import { z } from '@walkeros/core/dev';
4
+
5
+ /**
6
+ * HTTP methods enum
7
+ */
8
+ declare const HttpMethod: z.ZodEnum<{
9
+ GET: "GET";
10
+ POST: "POST";
11
+ PUT: "PUT";
12
+ PATCH: "PATCH";
13
+ DELETE: "DELETE";
14
+ OPTIONS: "OPTIONS";
15
+ HEAD: "HEAD";
16
+ }>;
17
+ /**
18
+ * CORS origin configuration
19
+ * Accepts:
20
+ * - '*' for all origins
21
+ * - Single URL string
22
+ * - Array of URL strings
23
+ */
24
+ declare const CorsOrigin: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>;
25
+ /**
26
+ * CORS options schema
27
+ * Configuration for Cross-Origin Resource Sharing
28
+ */
29
+ declare const CorsOptionsSchema: z.ZodObject<{
30
+ origin: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>>;
31
+ methods: z.ZodOptional<z.ZodArray<z.ZodEnum<{
32
+ GET: "GET";
33
+ POST: "POST";
34
+ PUT: "PUT";
35
+ PATCH: "PATCH";
36
+ DELETE: "DELETE";
37
+ OPTIONS: "OPTIONS";
38
+ HEAD: "HEAD";
39
+ }>>>;
40
+ headers: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ credentials: z.ZodOptional<z.ZodBoolean>;
42
+ maxAge: z.ZodOptional<z.ZodNumber>;
43
+ }, z.core.$strip>;
44
+ type CorsOptions$1 = z.infer<typeof CorsOptionsSchema>;
45
+
46
+ /**
47
+ * GCP CloudFunction source settings schema
48
+ */
49
+ declare const SettingsSchema: z.ZodObject<{
50
+ cors: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
51
+ origin: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>>;
52
+ methods: z.ZodOptional<z.ZodArray<z.ZodEnum<{
53
+ GET: "GET";
54
+ POST: "POST";
55
+ PUT: "PUT";
56
+ PATCH: "PATCH";
57
+ DELETE: "DELETE";
58
+ OPTIONS: "OPTIONS";
59
+ HEAD: "HEAD";
60
+ }>>>;
61
+ headers: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
+ credentials: z.ZodOptional<z.ZodBoolean>;
63
+ maxAge: z.ZodOptional<z.ZodNumber>;
64
+ }, z.core.$strip>]>>;
65
+ timeout: z.ZodOptional<z.ZodNumber>;
66
+ }, z.core.$strip>;
67
+ type Settings$1 = z.infer<typeof SettingsSchema>;
68
+
69
+ declare const settings: _walkeros_core_dev.JSONSchema;
70
+
71
+ declare const index$1_CorsOptionsSchema: typeof CorsOptionsSchema;
72
+ declare const index$1_CorsOrigin: typeof CorsOrigin;
73
+ declare const index$1_HttpMethod: typeof HttpMethod;
74
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
75
+ declare const index$1_settings: typeof settings;
76
+ declare namespace index$1 {
77
+ export { type CorsOptions$1 as CorsOptions, index$1_CorsOptionsSchema as CorsOptionsSchema, index$1_CorsOrigin as CorsOrigin, index$1_HttpMethod as HttpMethod, type Settings$1 as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
78
+ }
79
+
80
+ interface Request {
81
+ method: string;
82
+ body?: unknown;
83
+ headers: Record<string, string | string[]>;
84
+ get(name: string): string | undefined;
85
+ }
86
+ interface Response {
87
+ status(code: number): Response;
88
+ json(body: unknown): Response;
89
+ send(body?: unknown): Response;
90
+ set(key: string, value: string): Response;
91
+ }
92
+ type Settings = z.infer<typeof SettingsSchema>;
93
+ type CorsOptions = z.infer<typeof CorsOptionsSchema>;
94
+ type InitSettings = Partial<Settings>;
95
+ interface Mapping {
96
+ }
97
+ type Push = (req: Request, res: Response) => Promise<void>;
98
+ interface Env extends Source.Env {
99
+ req?: Request;
100
+ res?: Response;
101
+ }
102
+ type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;
103
+ interface CloudFunctionSource extends Omit<Source.Instance<Types>, 'push'> {
104
+ push: Push;
105
+ }
106
+ type Config = Source.Config<Types>;
107
+ type PartialConfig = Source.PartialConfig<Types>;
108
+ interface EventRequest {
109
+ event: string;
110
+ data?: WalkerOS.AnyObject;
111
+ context?: WalkerOS.AnyObject;
112
+ user?: WalkerOS.AnyObject;
113
+ globals?: WalkerOS.AnyObject;
114
+ consent?: WalkerOS.AnyObject;
115
+ }
116
+ interface EventResponse {
117
+ success: boolean;
118
+ id?: string;
119
+ error?: string;
120
+ }
121
+ type RequestBody = EventRequest;
122
+ type ResponseBody = EventResponse;
123
+
124
+ type types_CloudFunctionSource = CloudFunctionSource;
125
+ type types_Config = Config;
126
+ type types_CorsOptions = CorsOptions;
127
+ type types_Env = Env;
128
+ type types_EventRequest = EventRequest;
129
+ type types_EventResponse = EventResponse;
130
+ type types_InitSettings = InitSettings;
131
+ type types_Mapping = Mapping;
132
+ type types_PartialConfig = PartialConfig;
133
+ type types_Push = Push;
134
+ type types_Request = Request;
135
+ type types_RequestBody = RequestBody;
136
+ type types_Response = Response;
137
+ type types_ResponseBody = ResponseBody;
138
+ type types_Settings = Settings;
139
+ type types_Types = Types;
140
+ declare namespace types {
141
+ export type { types_CloudFunctionSource as CloudFunctionSource, types_Config as Config, types_CorsOptions as CorsOptions, types_Env as Env, types_EventRequest as EventRequest, types_EventResponse as EventResponse, types_InitSettings as InitSettings, types_Mapping as Mapping, types_PartialConfig as PartialConfig, types_Push as Push, types_Request as Request, types_RequestBody as RequestBody, types_Response as Response, types_ResponseBody as ResponseBody, types_Settings as Settings, types_Types as Types };
142
+ }
143
+
144
+ /**
145
+ * Standard mock environment for testing cloud function source
146
+ *
147
+ * Use this for testing HTTP event ingestion and request/response handling
148
+ * without requiring a real GCP Cloud Function environment.
149
+ */
150
+ declare const push: Env;
151
+
152
+ declare const env_push: typeof push;
153
+ declare namespace env {
154
+ export { env_push as push };
155
+ }
156
+
157
+ declare const index_env: typeof env;
158
+ declare namespace index {
159
+ export { index_env as env };
160
+ }
161
+
162
+ declare const sourceCloudFunction: (config: Partial<Source.Config<Types>> | undefined, env: Env) => Promise<CloudFunctionSource>;
163
+
164
+ export { types as SourceCloudFunction, index as examples, index$1 as schemas, sourceCloudFunction };
@@ -0,0 +1,164 @@
1
+ import { Source, WalkerOS } from '@walkeros/core';
2
+ import * as _walkeros_core_dev from '@walkeros/core/dev';
3
+ import { z } from '@walkeros/core/dev';
4
+
5
+ /**
6
+ * HTTP methods enum
7
+ */
8
+ declare const HttpMethod: z.ZodEnum<{
9
+ GET: "GET";
10
+ POST: "POST";
11
+ PUT: "PUT";
12
+ PATCH: "PATCH";
13
+ DELETE: "DELETE";
14
+ OPTIONS: "OPTIONS";
15
+ HEAD: "HEAD";
16
+ }>;
17
+ /**
18
+ * CORS origin configuration
19
+ * Accepts:
20
+ * - '*' for all origins
21
+ * - Single URL string
22
+ * - Array of URL strings
23
+ */
24
+ declare const CorsOrigin: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>;
25
+ /**
26
+ * CORS options schema
27
+ * Configuration for Cross-Origin Resource Sharing
28
+ */
29
+ declare const CorsOptionsSchema: z.ZodObject<{
30
+ origin: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>>;
31
+ methods: z.ZodOptional<z.ZodArray<z.ZodEnum<{
32
+ GET: "GET";
33
+ POST: "POST";
34
+ PUT: "PUT";
35
+ PATCH: "PATCH";
36
+ DELETE: "DELETE";
37
+ OPTIONS: "OPTIONS";
38
+ HEAD: "HEAD";
39
+ }>>>;
40
+ headers: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ credentials: z.ZodOptional<z.ZodBoolean>;
42
+ maxAge: z.ZodOptional<z.ZodNumber>;
43
+ }, z.core.$strip>;
44
+ type CorsOptions$1 = z.infer<typeof CorsOptionsSchema>;
45
+
46
+ /**
47
+ * GCP CloudFunction source settings schema
48
+ */
49
+ declare const SettingsSchema: z.ZodObject<{
50
+ cors: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
51
+ origin: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>, z.ZodLiteral<"*">]>>;
52
+ methods: z.ZodOptional<z.ZodArray<z.ZodEnum<{
53
+ GET: "GET";
54
+ POST: "POST";
55
+ PUT: "PUT";
56
+ PATCH: "PATCH";
57
+ DELETE: "DELETE";
58
+ OPTIONS: "OPTIONS";
59
+ HEAD: "HEAD";
60
+ }>>>;
61
+ headers: z.ZodOptional<z.ZodArray<z.ZodString>>;
62
+ credentials: z.ZodOptional<z.ZodBoolean>;
63
+ maxAge: z.ZodOptional<z.ZodNumber>;
64
+ }, z.core.$strip>]>>;
65
+ timeout: z.ZodOptional<z.ZodNumber>;
66
+ }, z.core.$strip>;
67
+ type Settings$1 = z.infer<typeof SettingsSchema>;
68
+
69
+ declare const settings: _walkeros_core_dev.JSONSchema;
70
+
71
+ declare const index$1_CorsOptionsSchema: typeof CorsOptionsSchema;
72
+ declare const index$1_CorsOrigin: typeof CorsOrigin;
73
+ declare const index$1_HttpMethod: typeof HttpMethod;
74
+ declare const index$1_SettingsSchema: typeof SettingsSchema;
75
+ declare const index$1_settings: typeof settings;
76
+ declare namespace index$1 {
77
+ export { type CorsOptions$1 as CorsOptions, index$1_CorsOptionsSchema as CorsOptionsSchema, index$1_CorsOrigin as CorsOrigin, index$1_HttpMethod as HttpMethod, type Settings$1 as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
78
+ }
79
+
80
+ interface Request {
81
+ method: string;
82
+ body?: unknown;
83
+ headers: Record<string, string | string[]>;
84
+ get(name: string): string | undefined;
85
+ }
86
+ interface Response {
87
+ status(code: number): Response;
88
+ json(body: unknown): Response;
89
+ send(body?: unknown): Response;
90
+ set(key: string, value: string): Response;
91
+ }
92
+ type Settings = z.infer<typeof SettingsSchema>;
93
+ type CorsOptions = z.infer<typeof CorsOptionsSchema>;
94
+ type InitSettings = Partial<Settings>;
95
+ interface Mapping {
96
+ }
97
+ type Push = (req: Request, res: Response) => Promise<void>;
98
+ interface Env extends Source.Env {
99
+ req?: Request;
100
+ res?: Response;
101
+ }
102
+ type Types = Source.Types<Settings, Mapping, Push, Env, InitSettings>;
103
+ interface CloudFunctionSource extends Omit<Source.Instance<Types>, 'push'> {
104
+ push: Push;
105
+ }
106
+ type Config = Source.Config<Types>;
107
+ type PartialConfig = Source.PartialConfig<Types>;
108
+ interface EventRequest {
109
+ event: string;
110
+ data?: WalkerOS.AnyObject;
111
+ context?: WalkerOS.AnyObject;
112
+ user?: WalkerOS.AnyObject;
113
+ globals?: WalkerOS.AnyObject;
114
+ consent?: WalkerOS.AnyObject;
115
+ }
116
+ interface EventResponse {
117
+ success: boolean;
118
+ id?: string;
119
+ error?: string;
120
+ }
121
+ type RequestBody = EventRequest;
122
+ type ResponseBody = EventResponse;
123
+
124
+ type types_CloudFunctionSource = CloudFunctionSource;
125
+ type types_Config = Config;
126
+ type types_CorsOptions = CorsOptions;
127
+ type types_Env = Env;
128
+ type types_EventRequest = EventRequest;
129
+ type types_EventResponse = EventResponse;
130
+ type types_InitSettings = InitSettings;
131
+ type types_Mapping = Mapping;
132
+ type types_PartialConfig = PartialConfig;
133
+ type types_Push = Push;
134
+ type types_Request = Request;
135
+ type types_RequestBody = RequestBody;
136
+ type types_Response = Response;
137
+ type types_ResponseBody = ResponseBody;
138
+ type types_Settings = Settings;
139
+ type types_Types = Types;
140
+ declare namespace types {
141
+ export type { types_CloudFunctionSource as CloudFunctionSource, types_Config as Config, types_CorsOptions as CorsOptions, types_Env as Env, types_EventRequest as EventRequest, types_EventResponse as EventResponse, types_InitSettings as InitSettings, types_Mapping as Mapping, types_PartialConfig as PartialConfig, types_Push as Push, types_Request as Request, types_RequestBody as RequestBody, types_Response as Response, types_ResponseBody as ResponseBody, types_Settings as Settings, types_Types as Types };
142
+ }
143
+
144
+ /**
145
+ * Standard mock environment for testing cloud function source
146
+ *
147
+ * Use this for testing HTTP event ingestion and request/response handling
148
+ * without requiring a real GCP Cloud Function environment.
149
+ */
150
+ declare const push: Env;
151
+
152
+ declare const env_push: typeof push;
153
+ declare namespace env {
154
+ export { env_push as push };
155
+ }
156
+
157
+ declare const index_env: typeof env;
158
+ declare namespace index {
159
+ export { index_env as env };
160
+ }
161
+
162
+ declare const sourceCloudFunction: (config: Partial<Source.Config<Types>> | undefined, env: Env) => Promise<CloudFunctionSource>;
163
+
164
+ export { types as SourceCloudFunction, index as examples, index$1 as schemas, sourceCloudFunction };
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ "use strict";var mod,__defProp=Object.defineProperty,__getOwnPropDesc=Object.getOwnPropertyDescriptor,__getOwnPropNames=Object.getOwnPropertyNames,__hasOwnProp=Object.prototype.hasOwnProperty,__export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},index_exports={};__export(index_exports,{SourceCloudFunction:()=>types_exports,examples:()=>examples_exports,schemas:()=>schemas_exports,sourceCloudFunction:()=>cloudfunction_default}),module.exports=(mod=index_exports,((to,from,except,desc)=>{if(from&&"object"==typeof from||"function"==typeof from)for(let key of __getOwnPropNames(from))__hasOwnProp.call(to,key)||key===except||__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to})(__defProp({},"__esModule",{value:!0}),mod));var types_exports={},schemas_exports={};__export(schemas_exports,{CorsOptionsSchema:()=>CorsOptionsSchema,CorsOrigin:()=>CorsOrigin,HttpMethod:()=>HttpMethod,SettingsSchema:()=>SettingsSchema,settings:()=>settings});var import_dev3=require("@walkeros/core/dev"),import_dev2=require("@walkeros/core/dev"),import_dev=require("@walkeros/core/dev"),HttpMethod=import_dev.z.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),CorsOrigin=import_dev.z.union([import_dev.z.string(),import_dev.z.array(import_dev.z.string()),import_dev.z.literal("*")]),CorsOptionsSchema=import_dev.z.object({origin:CorsOrigin.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:import_dev.z.array(HttpMethod).describe("Allowed HTTP methods").optional(),headers:import_dev.z.array(import_dev.z.string()).describe("Allowed request headers").optional(),credentials:import_dev.z.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:import_dev.z.number().int().positive().describe("Preflight cache duration in seconds").optional()}),SettingsSchema=import_dev2.z.object({cors:import_dev2.z.union([import_dev2.z.boolean(),CorsOptionsSchema]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:import_dev2.z.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),settings=(0,import_dev3.zodToSchema)(SettingsSchema),examples_exports={};__export(examples_exports,{env:()=>env_exports});var env_exports={};__export(env_exports,{push:()=>push});var createMockElbFn=()=>()=>Promise.resolve({ok:!0,successful:[],queued:[],failed:[]}),noopFn=()=>{},noopLogger={error:noopFn,info:noopFn,debug:noopFn,throw:message=>{throw"string"==typeof message?new Error(message):message},scope:()=>noopLogger},push={get push(){return createMockElbFn()},get command(){return createMockElbFn()},get elb(){return createMockElbFn()},logger:noopLogger},DEFAULT_SETTINGS={cors:!0,timeout:3e4},sourceCloudFunction=async(config={},env)=>{const{push:envPush}=env,settings2={...DEFAULT_SETTINGS,...config.settings||{}};return{type:"cloudfunction",config:{...config,settings:settings2},push:async(req,res)=>{try{if(function(res,corsOptions){if(corsOptions)if(!0===corsOptions)res.set("Access-Control-Allow-Origin","*"),res.set("Access-Control-Allow-Methods","POST, OPTIONS"),res.set("Access-Control-Allow-Headers","Content-Type, Authorization"),res.set("Access-Control-Max-Age","3600");else{if(corsOptions.origin){const origin=Array.isArray(corsOptions.origin)?corsOptions.origin.join(", "):corsOptions.origin;res.set("Access-Control-Allow-Origin",origin)}corsOptions.methods&&res.set("Access-Control-Allow-Methods",corsOptions.methods.join(", ")),corsOptions.headers&&res.set("Access-Control-Allow-Headers",corsOptions.headers.join(", ")),corsOptions.credentials&&res.set("Access-Control-Allow-Credentials","true"),void 0!==corsOptions.maxAge&&res.set("Access-Control-Max-Age",corsOptions.maxAge.toString())}}(res,settings2.cors||!1),"OPTIONS"===req.method)return void res.status(204).send();if("POST"!==req.method)return void res.status(405).json({success:!1,error:"Method not allowed. Use POST."});if(!req.body)return void res.status(400).json({success:!1,error:"Request body is required"});const body=req.body;if(function(body){return"event"in body&&"string"==typeof body.event}(body)){const result=await async function(eventReq,push2){var _a;try{const result=await push2({name:eventReq.event,data:eventReq.data||{},context:eventReq.context,user:eventReq.user,globals:eventReq.globals,consent:eventReq.consent});return{id:null==(_a=null==result?void 0:result.event)?void 0:_a.id}}catch(error){return{error:error instanceof Error?error.message:"Unknown error"}}}(body,envPush);result.error?res.status(400).json({success:!1,error:result.error}):res.status(200).json({success:!0,id:result.id})}else res.status(400).json({success:!1,error:"Invalid request format. Expected event object."})}catch(error){res.status(500).json({success:!1,error:error instanceof Error?error.message:"Internal server error"})}}}},cloudfunction_default=sourceCloudFunction;//# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/cloudfunction/utils.ts","../src/cloudfunction/push.ts","../src/cloudfunction/types.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/index.ts"],"sourcesContent":["export * from './cloudfunction';\nexport { default as sourceCloudFunction } from './cloudfunction';\n","import type { RequestBody, EventRequest, CorsOptions, Response } from './types';\n\nexport function isEventRequest(body: RequestBody): body is EventRequest {\n return 'event' in body && typeof body.event === 'string';\n}\n\nexport function setCorsHeaders(\n res: Response,\n corsOptions: boolean | CorsOptions,\n): void {\n if (!corsOptions) return;\n\n if (corsOptions === true) {\n res.set('Access-Control-Allow-Origin', '*');\n res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n res.set('Access-Control-Max-Age', '3600');\n } else {\n if (corsOptions.origin) {\n const origin = Array.isArray(corsOptions.origin)\n ? corsOptions.origin.join(', ')\n : corsOptions.origin;\n res.set('Access-Control-Allow-Origin', origin);\n }\n if (corsOptions.methods) {\n res.set('Access-Control-Allow-Methods', corsOptions.methods.join(', '));\n }\n if (corsOptions.headers) {\n res.set('Access-Control-Allow-Headers', corsOptions.headers.join(', '));\n }\n if (corsOptions.credentials) {\n res.set('Access-Control-Allow-Credentials', 'true');\n }\n if (corsOptions.maxAge !== undefined) {\n res.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n }\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport type { EventRequest } from './types';\n\nexport async function processEvent(\n eventReq: EventRequest,\n push: Collector.PushFn,\n): Promise<{ id?: string; error?: string }> {\n try {\n const result = await push({\n name: eventReq.event,\n data: (eventReq.data || {}) as WalkerOS.Properties,\n context: eventReq.context as WalkerOS.OrderedProperties | undefined,\n user: eventReq.user as WalkerOS.User | undefined,\n globals: eventReq.globals as WalkerOS.Properties | undefined,\n consent: eventReq.consent as WalkerOS.Consent | undefined,\n });\n\n return { id: result?.event?.id };\n } catch (error) {\n return { error: error instanceof Error ? error.message : 'Unknown error' };\n }\n}\n","import type { WalkerOS, Source as CoreSource } from '@walkeros/core';\nimport type { SettingsSchema, CorsOptionsSchema } from './schemas';\nimport { z } from '@walkeros/core/dev';\n\n// Minimal request/response interfaces\nexport interface Request {\n method: string;\n body?: unknown;\n headers: Record<string, string | string[]>;\n get(name: string): string | undefined;\n}\n\nexport interface Response {\n status(code: number): Response;\n json(body: unknown): Response;\n send(body?: unknown): Response;\n set(key: string, value: string): Response;\n}\n\n// Types inferred from Zod schemas\nexport type Settings = z.infer<typeof SettingsSchema>;\nexport type CorsOptions = z.infer<typeof CorsOptionsSchema>;\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n // Custom source event mapping properties\n}\n\n// CloudFunction-specific push type\nexport type Push = (req: Request, res: Response) => Promise<void>;\n\nexport interface Env extends CoreSource.Env {\n req?: Request;\n res?: Response;\n}\n\n// Type bundle (must be after Settings, Mapping, Push, Env are defined)\nexport type Types = CoreSource.Types<\n Settings,\n Mapping,\n Push,\n Env,\n InitSettings\n>;\n\nexport interface CloudFunctionSource\n extends Omit<CoreSource.Instance<Types>, 'push'> {\n push: Push;\n}\n\n// Convenience Config type\nexport type Config = CoreSource.Config<Types>;\nexport type PartialConfig = CoreSource.PartialConfig<Types>;\n\n// Cloud function source doesn't follow standard Source.Init pattern due to HTTP handler interface\n\nexport interface EventRequest {\n event: string;\n data?: WalkerOS.AnyObject;\n context?: WalkerOS.AnyObject;\n user?: WalkerOS.AnyObject;\n globals?: WalkerOS.AnyObject;\n consent?: WalkerOS.AnyObject;\n}\n\nexport interface EventResponse {\n success: boolean;\n id?: string;\n error?: string;\n}\n\nexport type RequestBody = EventRequest;\nexport type ResponseBody = EventResponse;\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';\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 successful: [],\n queued: [],\n failed: [],\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 info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\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 {\n Env,\n CloudFunctionSource,\n Settings,\n EventResponse,\n RequestBody,\n Request,\n Response,\n Mapping,\n Types,\n} from './types';\nimport type { Source } from '@walkeros/core';\nimport { isEventRequest, setCorsHeaders } from './utils';\nimport { processEvent } from './push';\n\nexport * as SourceCloudFunction from './types';\nexport * as schemas from './schemas';\n\n// Export examples\nexport * as examples from './examples';\n\nconst DEFAULT_SETTINGS: Settings = {\n cors: true,\n timeout: 30000,\n};\n\nexport const sourceCloudFunction = async (\n config: Partial<Source.Config<Types>> = {},\n env: Env,\n): Promise<CloudFunctionSource> => {\n const { push: envPush } = env;\n\n const settings: Settings = {\n ...DEFAULT_SETTINGS,\n ...(config.settings || {}),\n };\n\n const fullConfig: Source.Config<Types> = {\n ...config,\n settings,\n };\n\n const push = async (req: Request, res: Response): Promise<void> => {\n try {\n setCorsHeaders(res, settings.cors || false);\n\n if (req.method === 'OPTIONS') {\n res.status(204).send();\n return;\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({\n success: false,\n error: 'Method not allowed. Use POST.',\n });\n return;\n }\n\n if (!req.body) {\n res.status(400).json({\n success: false,\n error: 'Request body is required',\n });\n return;\n }\n\n const body = req.body as RequestBody;\n\n if (isEventRequest(body)) {\n const result = await processEvent(body, envPush);\n\n if (result.error) {\n res.status(400).json({\n success: false,\n error: result.error,\n } as EventResponse);\n } else {\n res.status(200).json({\n success: true,\n id: result.id,\n } as EventResponse);\n }\n } else {\n res.status(400).json({\n success: false,\n error: 'Invalid request format. Expected event object.',\n });\n }\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : 'Internal server error',\n });\n }\n };\n\n return {\n type: 'cloudfunction',\n config: fullConfig,\n push,\n };\n};\n\nexport default sourceCloudFunction;\n"],"mappings":"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","names":["push","import_dev","import_dev","settings","push"]}
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ var __defProp=Object.defineProperty,__export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})};var types_exports={},schemas_exports={};__export(schemas_exports,{CorsOptionsSchema:()=>CorsOptionsSchema,CorsOrigin:()=>CorsOrigin,HttpMethod:()=>HttpMethod,SettingsSchema:()=>SettingsSchema,settings:()=>settings});import{zodToSchema}from"@walkeros/core/dev";import{z as z2}from"@walkeros/core/dev";import{z}from"@walkeros/core/dev";var HttpMethod=z.enum(["GET","POST","PUT","PATCH","DELETE","OPTIONS","HEAD"]),CorsOrigin=z.union([z.string(),z.array(z.string()),z.literal("*")]),CorsOptionsSchema=z.object({origin:CorsOrigin.describe("Allowed origins (* for all, URL string, or array of URLs)").optional(),methods:z.array(HttpMethod).describe("Allowed HTTP methods").optional(),headers:z.array(z.string()).describe("Allowed request headers").optional(),credentials:z.boolean().describe("Allow credentials (cookies, authorization headers)").optional(),maxAge:z.number().int().positive().describe("Preflight cache duration in seconds").optional()}),SettingsSchema=z2.object({cors:z2.union([z2.boolean(),CorsOptionsSchema]).describe("CORS configuration: false = disabled, true = allow all origins, object = custom configuration").optional(),timeout:z2.number().int().positive().max(54e4).describe("Request timeout in milliseconds (max: 540000 for GCP)").optional()}),settings=zodToSchema(SettingsSchema),examples_exports={};__export(examples_exports,{env:()=>env_exports});var env_exports={};__export(env_exports,{push:()=>push});var createMockElbFn=()=>()=>Promise.resolve({ok:!0,successful:[],queued:[],failed:[]}),noopFn=()=>{},noopLogger={error:noopFn,info:noopFn,debug:noopFn,throw:message=>{throw"string"==typeof message?new Error(message):message},scope:()=>noopLogger},push={get push(){return createMockElbFn()},get command(){return createMockElbFn()},get elb(){return createMockElbFn()},logger:noopLogger},DEFAULT_SETTINGS={cors:!0,timeout:3e4},cloudfunction_default=async(config={},env)=>{const{push:envPush}=env,settings2={...DEFAULT_SETTINGS,...config.settings||{}};return{type:"cloudfunction",config:{...config,settings:settings2},push:async(req,res)=>{try{if(function(res,corsOptions){if(corsOptions)if(!0===corsOptions)res.set("Access-Control-Allow-Origin","*"),res.set("Access-Control-Allow-Methods","POST, OPTIONS"),res.set("Access-Control-Allow-Headers","Content-Type, Authorization"),res.set("Access-Control-Max-Age","3600");else{if(corsOptions.origin){const origin=Array.isArray(corsOptions.origin)?corsOptions.origin.join(", "):corsOptions.origin;res.set("Access-Control-Allow-Origin",origin)}corsOptions.methods&&res.set("Access-Control-Allow-Methods",corsOptions.methods.join(", ")),corsOptions.headers&&res.set("Access-Control-Allow-Headers",corsOptions.headers.join(", ")),corsOptions.credentials&&res.set("Access-Control-Allow-Credentials","true"),void 0!==corsOptions.maxAge&&res.set("Access-Control-Max-Age",corsOptions.maxAge.toString())}}(res,settings2.cors||!1),"OPTIONS"===req.method)return void res.status(204).send();if("POST"!==req.method)return void res.status(405).json({success:!1,error:"Method not allowed. Use POST."});if(!req.body)return void res.status(400).json({success:!1,error:"Request body is required"});const body=req.body;if(function(body){return"event"in body&&"string"==typeof body.event}(body)){const result=await async function(eventReq,push2){var _a;try{const result=await push2({name:eventReq.event,data:eventReq.data||{},context:eventReq.context,user:eventReq.user,globals:eventReq.globals,consent:eventReq.consent});return{id:null==(_a=null==result?void 0:result.event)?void 0:_a.id}}catch(error){return{error:error instanceof Error?error.message:"Unknown error"}}}(body,envPush);result.error?res.status(400).json({success:!1,error:result.error}):res.status(200).json({success:!0,id:result.id})}else res.status(400).json({success:!1,error:"Invalid request format. Expected event object."})}catch(error){res.status(500).json({success:!1,error:error instanceof Error?error.message:"Internal server error"})}}}};export{types_exports as SourceCloudFunction,examples_exports as examples,schemas_exports as schemas,cloudfunction_default as sourceCloudFunction};//# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cloudfunction/utils.ts","../src/cloudfunction/push.ts","../src/cloudfunction/types.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/index.ts"],"sourcesContent":["import type { RequestBody, EventRequest, CorsOptions, Response } from './types';\n\nexport function isEventRequest(body: RequestBody): body is EventRequest {\n return 'event' in body && typeof body.event === 'string';\n}\n\nexport function setCorsHeaders(\n res: Response,\n corsOptions: boolean | CorsOptions,\n): void {\n if (!corsOptions) return;\n\n if (corsOptions === true) {\n res.set('Access-Control-Allow-Origin', '*');\n res.set('Access-Control-Allow-Methods', 'POST, OPTIONS');\n res.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n res.set('Access-Control-Max-Age', '3600');\n } else {\n if (corsOptions.origin) {\n const origin = Array.isArray(corsOptions.origin)\n ? corsOptions.origin.join(', ')\n : corsOptions.origin;\n res.set('Access-Control-Allow-Origin', origin);\n }\n if (corsOptions.methods) {\n res.set('Access-Control-Allow-Methods', corsOptions.methods.join(', '));\n }\n if (corsOptions.headers) {\n res.set('Access-Control-Allow-Headers', corsOptions.headers.join(', '));\n }\n if (corsOptions.credentials) {\n res.set('Access-Control-Allow-Credentials', 'true');\n }\n if (corsOptions.maxAge !== undefined) {\n res.set('Access-Control-Max-Age', corsOptions.maxAge.toString());\n }\n }\n}\n","import type { Collector, WalkerOS } from '@walkeros/core';\nimport type { EventRequest } from './types';\n\nexport async function processEvent(\n eventReq: EventRequest,\n push: Collector.PushFn,\n): Promise<{ id?: string; error?: string }> {\n try {\n const result = await push({\n name: eventReq.event,\n data: (eventReq.data || {}) as WalkerOS.Properties,\n context: eventReq.context as WalkerOS.OrderedProperties | undefined,\n user: eventReq.user as WalkerOS.User | undefined,\n globals: eventReq.globals as WalkerOS.Properties | undefined,\n consent: eventReq.consent as WalkerOS.Consent | undefined,\n });\n\n return { id: result?.event?.id };\n } catch (error) {\n return { error: error instanceof Error ? error.message : 'Unknown error' };\n }\n}\n","import type { WalkerOS, Source as CoreSource } from '@walkeros/core';\nimport type { SettingsSchema, CorsOptionsSchema } from './schemas';\nimport { z } from '@walkeros/core/dev';\n\n// Minimal request/response interfaces\nexport interface Request {\n method: string;\n body?: unknown;\n headers: Record<string, string | string[]>;\n get(name: string): string | undefined;\n}\n\nexport interface Response {\n status(code: number): Response;\n json(body: unknown): Response;\n send(body?: unknown): Response;\n set(key: string, value: string): Response;\n}\n\n// Types inferred from Zod schemas\nexport type Settings = z.infer<typeof SettingsSchema>;\nexport type CorsOptions = z.infer<typeof CorsOptionsSchema>;\n\n// InitSettings: user input (all optional)\nexport type InitSettings = Partial<Settings>;\n\nexport interface Mapping {\n // Custom source event mapping properties\n}\n\n// CloudFunction-specific push type\nexport type Push = (req: Request, res: Response) => Promise<void>;\n\nexport interface Env extends CoreSource.Env {\n req?: Request;\n res?: Response;\n}\n\n// Type bundle (must be after Settings, Mapping, Push, Env are defined)\nexport type Types = CoreSource.Types<\n Settings,\n Mapping,\n Push,\n Env,\n InitSettings\n>;\n\nexport interface CloudFunctionSource\n extends Omit<CoreSource.Instance<Types>, 'push'> {\n push: Push;\n}\n\n// Convenience Config type\nexport type Config = CoreSource.Config<Types>;\nexport type PartialConfig = CoreSource.PartialConfig<Types>;\n\n// Cloud function source doesn't follow standard Source.Init pattern due to HTTP handler interface\n\nexport interface EventRequest {\n event: string;\n data?: WalkerOS.AnyObject;\n context?: WalkerOS.AnyObject;\n user?: WalkerOS.AnyObject;\n globals?: WalkerOS.AnyObject;\n consent?: WalkerOS.AnyObject;\n}\n\nexport interface EventResponse {\n success: boolean;\n id?: string;\n error?: string;\n}\n\nexport type RequestBody = EventRequest;\nexport type ResponseBody = EventResponse;\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';\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 successful: [],\n queued: [],\n failed: [],\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 info: noopFn,\n debug: noopFn,\n throw: (message: string | Error) => {\n throw typeof message === 'string' ? new Error(message) : message;\n },\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 {\n Env,\n CloudFunctionSource,\n Settings,\n EventResponse,\n RequestBody,\n Request,\n Response,\n Mapping,\n Types,\n} from './types';\nimport type { Source } from '@walkeros/core';\nimport { isEventRequest, setCorsHeaders } from './utils';\nimport { processEvent } from './push';\n\nexport * as SourceCloudFunction from './types';\nexport * as schemas from './schemas';\n\n// Export examples\nexport * as examples from './examples';\n\nconst DEFAULT_SETTINGS: Settings = {\n cors: true,\n timeout: 30000,\n};\n\nexport const sourceCloudFunction = async (\n config: Partial<Source.Config<Types>> = {},\n env: Env,\n): Promise<CloudFunctionSource> => {\n const { push: envPush } = env;\n\n const settings: Settings = {\n ...DEFAULT_SETTINGS,\n ...(config.settings || {}),\n };\n\n const fullConfig: Source.Config<Types> = {\n ...config,\n settings,\n };\n\n const push = async (req: Request, res: Response): Promise<void> => {\n try {\n setCorsHeaders(res, settings.cors || false);\n\n if (req.method === 'OPTIONS') {\n res.status(204).send();\n return;\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({\n success: false,\n error: 'Method not allowed. Use POST.',\n });\n return;\n }\n\n if (!req.body) {\n res.status(400).json({\n success: false,\n error: 'Request body is required',\n });\n return;\n }\n\n const body = req.body as RequestBody;\n\n if (isEventRequest(body)) {\n const result = await processEvent(body, envPush);\n\n if (result.error) {\n res.status(400).json({\n success: false,\n error: result.error,\n } as EventResponse);\n } else {\n res.status(200).json({\n success: true,\n id: result.id,\n } as EventResponse);\n }\n } else {\n res.status(400).json({\n success: false,\n error: 'Invalid request format. Expected event object.',\n });\n }\n } catch (error) {\n res.status(500).json({\n success: false,\n error: error instanceof Error ? error.message : 'Internal server error',\n });\n }\n };\n\n return {\n type: 'cloudfunction',\n config: fullConfig,\n push,\n };\n};\n\nexport default sourceCloudFunction;\n"],"mappings":";;;;;;;AAEO,SAAS,eAAe,MAAyC;AACtE,SAAO,WAAW,QAAQ,OAAO,KAAK,UAAU;AAClD;AAEO,SAAS,eACd,KACA,aACM;AACN,MAAI,CAAC,YAAa;AAElB,MAAI,gBAAgB,MAAM;AACxB,QAAI,IAAI,+BAA+B,GAAG;AAC1C,QAAI,IAAI,gCAAgC,eAAe;AACvD,QAAI,IAAI,gCAAgC,6BAA6B;AACrE,QAAI,IAAI,0BAA0B,MAAM;AAAA,EAC1C,OAAO;AACL,QAAI,YAAY,QAAQ;AACtB,YAAM,SAAS,MAAM,QAAQ,YAAY,MAAM,IAC3C,YAAY,OAAO,KAAK,IAAI,IAC5B,YAAY;AAChB,UAAI,IAAI,+BAA+B,MAAM;AAAA,IAC/C;AACA,QAAI,YAAY,SAAS;AACvB,UAAI,IAAI,gCAAgC,YAAY,QAAQ,KAAK,IAAI,CAAC;AAAA,IACxE;AACA,QAAI,YAAY,SAAS;AACvB,UAAI,IAAI,gCAAgC,YAAY,QAAQ,KAAK,IAAI,CAAC;AAAA,IACxE;AACA,QAAI,YAAY,aAAa;AAC3B,UAAI,IAAI,oCAAoC,MAAM;AAAA,IACpD;AACA,QAAI,YAAY,WAAW,QAAW;AACpC,UAAI,IAAI,0BAA0B,YAAY,OAAO,SAAS,CAAC;AAAA,IACjE;AAAA,EACF;AACF;;;AClCA,eAAsB,aACpB,UACAA,OAC0C;AAN5C;AAOE,MAAI;AACF,UAAM,SAAS,MAAMA,MAAK;AAAA,MACxB,MAAM,SAAS;AAAA,MACf,MAAO,SAAS,QAAQ,CAAC;AAAA,MACzB,SAAS,SAAS;AAAA,MAClB,MAAM,SAAS;AAAA,MACf,SAAS,SAAS;AAAA,MAClB,SAAS,SAAS;AAAA,IACpB,CAAC;AAED,WAAO,EAAE,KAAI,sCAAQ,UAAR,mBAAe,GAAG;AAAA,EACjC,SAAS,OAAO;AACd,WAAO,EAAE,OAAO,iBAAiB,QAAQ,MAAM,UAAU,gBAAgB;AAAA,EAC3E;AACF;;;ACrBA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,KAAAC,UAAS;;;ACAlB,SAAS,SAAS;AAKX,IAAM,aAAa,EAAE,KAAK;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,IAAM,aAAa,EAAE,MAAM;AAAA,EAChC,EAAE,OAAO;AAAA,EACT,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAClB,EAAE,QAAQ,GAAG;AACf,CAAC;AAMM,IAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,QAAQ,WAAW;AAAA,IACjB;AAAA,EACF,EAAE,SAAS;AAAA,EAEX,SAAS,EAAE,MAAM,UAAU,EAAE,SAAS,sBAAsB,EAAE,SAAS;AAAA,EAEvE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,yBAAyB,EAAE,SAAS;AAAA,EAE1E,aAAa,EACV,QAAQ,EACR,SAAS,oDAAoD,EAC7D,SAAS;AAAA,EAEZ,QAAQ,EACL,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,qCAAqC,EAC9C,SAAS;AACd,CAAC;;;AD9CM,IAAM,iBAAiBC,GAAE,OAAO;AAAA,EACrC,MAAMA,GACH,MAAM,CAACA,GAAE,QAAQ,GAAG,iBAAiB,CAAC,EACtC;AAAA,IACC;AAAA,EACF,EACC,SAAS;AAAA,EAEZ,SAASA,GACN,OAAO,EACP,IAAI,EACJ,SAAS,EACT,IAAI,IAAM,EACV,SAAS,uDAAuD,EAChE,SAAS;AACd,CAAC;;;ADXM,IAAM,WAAW,YAAY,cAAc;;;AGVlD;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAWA,IAAM,kBAAkB,MAAc;AACpC,QAAM,MAAM,MACV,QAAQ,QAAQ;AAAA,IACd,IAAI;AAAA,IACJ,YAAY,CAAC;AAAA,IACb,QAAQ,CAAC;AAAA,IACT,QAAQ,CAAC;AAAA,EACX,CAAC;AACH,SAAO;AACT;AAGA,IAAM,SAAS,MAAM;AAAC;AACtB,IAAM,aAA8B;AAAA,EAClC,OAAO;AAAA,EACP,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO,CAAC,YAA4B;AAClC,UAAM,OAAO,YAAY,WAAW,IAAI,MAAM,OAAO,IAAI;AAAA,EAC3D;AAAA,EACA,OAAO,MAAM;AACf;AAQO,IAAM,OAAY;AAAA,EACvB,IAAI,OAAO;AACT,WAAO,gBAAgB;AAAA,EACzB;AAAA,EACA,IAAI,UAAU;AACZ,WAAO,gBAAgB;AAAA,EACzB;AAAA,EACA,IAAI,MAAM;AACR,WAAO,gBAAgB;AAAA,EACzB;AAAA,EACA,QAAQ;AACV;;;AC9BA,IAAM,mBAA6B;AAAA,EACjC,MAAM;AAAA,EACN,SAAS;AACX;AAEO,IAAM,sBAAsB,OACjC,SAAwC,CAAC,GACzC,QACiC;AACjC,QAAM,EAAE,MAAM,QAAQ,IAAI;AAE1B,QAAMC,YAAqB;AAAA,IACzB,GAAG;AAAA,IACH,GAAI,OAAO,YAAY,CAAC;AAAA,EAC1B;AAEA,QAAM,aAAmC;AAAA,IACvC,GAAG;AAAA,IACH,UAAAA;AAAA,EACF;AAEA,QAAMC,QAAO,OAAO,KAAc,QAAiC;AACjE,QAAI;AACF,qBAAe,KAAKD,UAAS,QAAQ,KAAK;AAE1C,UAAI,IAAI,WAAW,WAAW;AAC5B,YAAI,OAAO,GAAG,EAAE,KAAK;AACrB;AAAA,MACF;AAEA,UAAI,IAAI,WAAW,QAAQ;AACzB,YAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UACnB,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AACD;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,MAAM;AACb,YAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UACnB,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AACD;AAAA,MACF;AAEA,YAAM,OAAO,IAAI;AAEjB,UAAI,eAAe,IAAI,GAAG;AACxB,cAAM,SAAS,MAAM,aAAa,MAAM,OAAO;AAE/C,YAAI,OAAO,OAAO;AAChB,cAAI,OAAO,GAAG,EAAE,KAAK;AAAA,YACnB,SAAS;AAAA,YACT,OAAO,OAAO;AAAA,UAChB,CAAkB;AAAA,QACpB,OAAO;AACL,cAAI,OAAO,GAAG,EAAE,KAAK;AAAA,YACnB,SAAS;AAAA,YACT,IAAI,OAAO;AAAA,UACb,CAAkB;AAAA,QACpB;AAAA,MACF,OAAO;AACL,YAAI,OAAO,GAAG,EAAE,KAAK;AAAA,UACnB,SAAS;AAAA,UACT,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,UAAI,OAAO,GAAG,EAAE,KAAK;AAAA,QACnB,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,MAAAC;AAAA,EACF;AACF;AAEA,IAAO,wBAAQ;","names":["push","z","z","settings","push"]}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@walkeros/server-source-gcp",
3
+ "description": "Google Cloud Platform server sources for walkerOS (Cloud Functions)",
4
+ "version": "0.0.0-next-20251219153324",
5
+ "license": "MIT",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.mjs",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist/**"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsup --silent",
14
+ "clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
15
+ "dev": "jest --watchAll --colors",
16
+ "lint": "tsc && eslint \"**/*.ts*\"",
17
+ "test": "jest",
18
+ "update": "npx npm-check-updates -u && npm update"
19
+ },
20
+ "dependencies": {
21
+ "@walkeros/core": "0.0.0-next-20251219153324"
22
+ },
23
+ "peerDependencies": {
24
+ "@google-cloud/functions-framework": "^3.0.0"
25
+ },
26
+ "devDependencies": {},
27
+ "repository": {
28
+ "url": "git+https://github.com/elbwalker/walkerOS.git",
29
+ "directory": "packages/server/sources/gcp"
30
+ },
31
+ "author": "elbwalker <hello@elbwalker.com>",
32
+ "homepage": "https://github.com/elbwalker/walkerOS#readme",
33
+ "bugs": {
34
+ "url": "https://github.com/elbwalker/walkerOS/issues"
35
+ },
36
+ "keywords": [
37
+ "walker",
38
+ "walkerOS",
39
+ "source",
40
+ "server",
41
+ "gcp",
42
+ "cloud functions"
43
+ ],
44
+ "funding": [
45
+ {
46
+ "type": "GitHub Sponsors",
47
+ "url": "https://github.com/sponsors/elbwalker"
48
+ }
49
+ ]
50
+ }