@walkeros/server-destination-gcp 4.2.1-next-1781682752679 → 4.2.1
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/CHANGELOG.md +11 -3
- package/dist/dev.js +1 -1
- package/dist/dev.js.map +1 -1
- package/dist/dev.mjs +1 -1
- package/dist/dev.mjs.map +1 -1
- package/dist/index.d.mts +9 -1
- package/dist/index.d.ts +9 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +11 -7
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
# @walkeros/server-destination-gcp
|
|
2
2
|
|
|
3
|
-
## 4.2.1
|
|
3
|
+
## 4.2.1
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
+
- 96c791a: The BigQuery destination now applies `config.credentials` to the
|
|
8
|
+
Storage Write client that performs event writes, not just the query client.
|
|
9
|
+
Event writes from the configured service account now succeed on non-Google
|
|
10
|
+
Cloud runtimes instead of failing with a credentials error. Both clients
|
|
11
|
+
resolve credentials the same way, so a destination always authenticates as a
|
|
12
|
+
single identity.
|
|
7
13
|
- 8afb7cc: Capture BigQuery Storage Write stream errors so a broken writer
|
|
8
14
|
routes events to the dead-letter queue instead of crashing the process, and
|
|
9
15
|
re-open a broken writer automatically on the next event.
|
|
10
16
|
- Updated dependencies [5cbcd23]
|
|
17
|
+
- Updated dependencies [31c6858]
|
|
18
|
+
- Updated dependencies [d1b41ca]
|
|
11
19
|
- Updated dependencies [0a8a08b]
|
|
12
20
|
- Updated dependencies [8afb7cc]
|
|
13
|
-
- @walkeros/core@4.2.1
|
|
14
|
-
- @walkeros/server-core@4.2.1
|
|
21
|
+
- @walkeros/core@4.2.1
|
|
22
|
+
- @walkeros/server-core@4.2.1
|
|
15
23
|
|
|
16
24
|
## 4.2.0
|
|
17
25
|
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,o=(e,r)=>{for(var i in r)t(e,i,{get:r[i],enumerable:!0})},a={};o(a,{examples:()=>O,hints:()=>ne,pubsubExamples:()=>L,schemas:()=>n}),module.exports=(e=a,((e,o,a,n)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let l of i(o))s.call(e,l)||l===a||t(e,l,{get:()=>o[l],enumerable:!(n=r(o,l))||n.enumerable});return e})(t({},"__esModule",{value:!0}),e));var n={};o(n,{mapping:()=>g,pubsubMapping:()=>k,pubsubSettings:()=>w,pubsubSetup:()=>j,settings:()=>p});var l=require("@walkeros/core/dev"),c=require("@walkeros/core/dev"),d=c.z.object({client:c.z.any().describe("Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))").optional(),projectId:c.z.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),datasetId:c.z.string().min(1).default("walkerOS").describe("BigQuery dataset ID where events will be stored (like walker_events)"),tableId:c.z.string().min(1).default("events").describe("BigQuery table ID for event storage (like events)"),location:c.z.string().default("EU").describe("Geographic location for the BigQuery dataset (like US)"),bigquery:c.z.any().describe('Additional BigQuery client configuration options (like { keyFilename: "path/to/key.json" })').optional()}),u=require("@walkeros/core/dev").z.object({}),p=(0,l.zodToSchema)(d),g=(0,l.zodToSchema)(u),m=require("@walkeros/core/dev"),b=require("@walkeros/core/dev"),h=b.z.object({client:b.z.any().describe("Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))").optional(),projectId:b.z.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),topic:b.z.string().min(1).describe("Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK."),credentials:b.z.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC). (deprecated: use config.credentials)").optional(),apiEndpoint:b.z.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),orderingKey:b.z.any().describe("Mapping value resolved per-event. Truthy enables per-key ordering for the publish.").optional(),attributes:b.z.any().describe("Default per-event attribute map merged into every published message. Mapping.Map shape.").optional()}),y=require("@walkeros/core/dev"),v=y.z.object({topic:y.z.string().describe("Per-rule topic override. Falls back to settings.topic if absent.").optional(),orderingKey:y.z.any().describe("Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.").optional(),attributes:y.z.any().describe("Per-rule attribute Mapping.Map merged on top of settings.attributes.").optional()}),f=require("@walkeros/core/dev"),S=f.z.object({messageStoragePolicy:f.z.object({allowedPersistenceRegions:f.z.array(f.z.string()).describe("Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).")}).describe("Topic-level message storage policy.").optional(),messageRetentionDuration:f.z.object({seconds:f.z.number().describe("Retention window in seconds. Default: project default.")}).describe("Topic-level retention configuration.").optional(),kmsKeyName:f.z.string().describe("Customer-managed encryption key (CMEK) resource name. Optional.").optional(),labels:f.z.record(f.z.string(),f.z.string()).describe("Topic labels for organization and billing.").optional()}),w=(0,m.zodToSchema)(h),k=(0,m.zodToSchema)(v),j=(0,m.zodToSchema)(S),O={};o(O,{env:()=>z,step:()=>W});var z={};o(z,{push:()=>J,simulation:()=>M});var A=require("events"),C=[],P=null,D=null,E=null,T=null,I=class extends A.EventEmitter{streamId;constructor(e){super(),this.streamId=e}getStreamId(){return this.streamId}onConnectionError(e){return C.push({method:"onConnectionError",args:[]}),this.on("error",e),{off:()=>{this.off("error",e)}}}__emitConnectionError(e){this.emit("error",e)}},N=[],R={convertStorageSchemaToProto2Descriptor:(e,t)=>(C.push({method:"adapt.convertStorageSchemaToProto2Descriptor",args:[e,t]}),{name:"root",field:[]})},q={WriterClient:class{constructor(e){C.push({method:"WriterClient.ctor",args:[e]})}async createStreamConnection(e,t){if("DEFAULT"!==e.streamId)throw new Error(`mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(e)}`);C.push({method:"createStreamConnection",args:[e,t]});const r=T;if(null!==r)throw T=null,r;const i=new I(`${e.destinationTable}/streams/_default`);return N.push(i),i}async getWriteStream(e,t){return C.push({method:"getWriteStream",args:[e,t]}),{tableSchema:{fields:[]}}}close(){C.push({method:"WriterClient.close",args:[]})}},JSONWriter:class{constructor(e){C.push({method:"JSONWriter.ctor",args:[e]})}appendRows(e,t){C.push({method:"appendRows",args:[e,t]});const r=D;if(null!==r)throw D=null,r;const i=P;P=null;const s=E;return E=null,{getResult:async()=>{if(null!==s)throw s;return{appendResult:{offset:{value:"0"}},rowErrors:i??[],writeStream:"projects/p/datasets/d/tables/t/streams/_default"}}}}close(){C.push({method:"JSONWriter.close",args:[]})}},DefaultStream:"DEFAULT"},x=()=>{};var J={get BigQuery(){return class{calls;options;constructor(e){this.options=e,this.calls=[]}dataset(e){return this.calls.push({method:"dataset",args:[e]}),this}table(e){return this.calls.push({method:"table",args:[e]}),this}async insert(e){return this.calls.push({method:"insert",args:[e]}),Promise.resolve()}get mockFn(){return x}}},get WriterClient(){return q.WriterClient},get JSONWriter(){return q.JSONWriter},get adapt(){return R},get managedwriterModule(){return q}},M=["BigQuery","WriterClient","JSONWriter","adapt"],W={};o(W,{pageView:()=>U,purchase:()=>G});var _=require("@walkeros/core");function B(e){return null==e?null:"object"==typeof e?Array.isArray(e)&&0===e.length?null:Array.isArray(e)||0!==Object.keys(e).length?JSON.stringify(e):null:JSON.stringify(e)}function Q(e){return function(e){return{name:e.name,data:B(e.data),context:B(e.context),globals:B(e.globals),custom:B(e.custom),user:B(e.user),nested:B(e.nested),consent:B(e.consent),id:e.id,trigger:e.trigger,entity:e.entity,action:e.action,timestamp:1e3*new Date(e.timestamp).getTime(),timing:e.timing,source:B(e.source)}}(e)}var F=(0,_.getEvent)("page view",{timestamp:1700001100,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}}),U={title:"Page view",description:"A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.",in:F,mapping:void 0,out:[["appendRows",[Q(F)]]]},K=(0,_.getEvent)("order complete",{timestamp:1700001101,data:{id:"ORD-500",total:199.99,items:[{sku:"SKU-1",qty:2}]},source:{type:"express",platform:"server"}}),G={title:"Purchase",description:"An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().",in:K,mapping:void 0,out:[["appendRows",[Q(K)]]]},L={};o(L,{env:()=>V,step:()=>X});var V={};o(V,{simulation:()=>$});var $=["PubSub"],X={};o(X,{defaultPush:()=>te,mappedAttributes:()=>se,mappedData:()=>oe,mappedOrderingKey:()=>ie,mappedTopic:()=>re,pageView:()=>ae});var H=require("@walkeros/core"),Y=(0,H.getEvent)("order complete",{timestamp:1700001100,data:{id:"ORD-500",total:199.99,currency:"EUR"},user:{id:"usr-789"},source:{type:"express",platform:"server"}}),Z=(0,H.getEvent)("page view",{timestamp:1700001101,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}});function ee(e){return Buffer.from(JSON.stringify(e))}var te={title:"Default publish",description:"An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.",in:Y,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Y)}]]},re={title:"Topic override",description:"A mapping rule overrides the destination default topic so order events are published to a dedicated topic.",in:Y,mapping:{settings:{topic:"orders"}},out:[["topic","orders",{messageOrdering:!1}],["publishMessage","orders",{data:ee(Y)}]]},ie={title:"Ordering key from user",description:"A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.",in:Y,mapping:{settings:{orderingKey:"user.id"}},out:[["topic","events",{messageOrdering:!0}],["publishMessage","events",{data:ee(Y),orderingKey:"usr-789"}]]},se={title:"Mapped attributes",description:"A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.",in:Y,mapping:{settings:{attributes:{entity:"entity",action:"action"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Y),attributes:{entity:"order",action:"complete"}}]]},oe={title:"Mapped payload",description:"A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.",in:Y,mapping:{data:{map:{order_id:"data.id",revenue:"data.total",currency:"data.currency"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee({order_id:"ORD-500",revenue:199.99,currency:"EUR"})}]]},ae={title:"Page view",description:"A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.",in:Z,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Z)}]]},ne={"auth-methods":{text:'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: "./sa.json" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',code:[{lang:"json",code:'{ "settings": { "projectId": "my-project", "bigquery": { "keyFilename": "./sa.json" } } }'},{lang:"json",code:'{ "settings": { "projectId": "my-project" } }'}]},"storage-format":{text:'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset "walkeros", table "events", location "EU" — all overridable via settings.'},"query-json-columns":{text:"Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.",code:[{lang:"sql",code:"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'"}]},"troubleshoot-empty-table":{text:"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK."}};//# sourceMappingURL=dev.js.map
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,r=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,o=(e,r)=>{for(var i in r)t(e,i,{get:r[i],enumerable:!0})},a={};o(a,{examples:()=>O,hints:()=>ne,pubsubExamples:()=>L,schemas:()=>n}),module.exports=(e=a,((e,o,a,n)=>{if(o&&"object"==typeof o||"function"==typeof o)for(let l of i(o))s.call(e,l)||l===a||t(e,l,{get:()=>o[l],enumerable:!(n=r(o,l))||n.enumerable});return e})(t({},"__esModule",{value:!0}),e));var n={};o(n,{mapping:()=>g,pubsubMapping:()=>k,pubsubSettings:()=>w,pubsubSetup:()=>j,settings:()=>p});var l=require("@walkeros/core/dev"),c=require("@walkeros/core/dev"),d=c.z.object({client:c.z.any().describe("Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))").optional(),projectId:c.z.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),datasetId:c.z.string().min(1).default("walkerOS").describe("BigQuery dataset ID where events will be stored (like walker_events)"),tableId:c.z.string().min(1).default("events").describe("BigQuery table ID for event storage (like events)"),location:c.z.string().default("EU").describe("Geographic location for the BigQuery dataset (like US)"),bigquery:c.z.any().describe('Additional BigQuery client configuration options (like { keyFilename: "path/to/key.json" })').optional()}),u=require("@walkeros/core/dev").z.object({}),p=(0,l.zodToSchema)(d),g=(0,l.zodToSchema)(u),m=require("@walkeros/core/dev"),b=require("@walkeros/core/dev"),h=b.z.object({client:b.z.any().describe("Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))").optional(),projectId:b.z.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),topic:b.z.string().min(1).describe("Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK."),credentials:b.z.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC). (deprecated: use config.credentials)").optional(),apiEndpoint:b.z.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),orderingKey:b.z.any().describe("Mapping value resolved per-event. Truthy enables per-key ordering for the publish.").optional(),attributes:b.z.any().describe("Default per-event attribute map merged into every published message. Mapping.Map shape.").optional()}),y=require("@walkeros/core/dev"),v=y.z.object({topic:y.z.string().describe("Per-rule topic override. Falls back to settings.topic if absent.").optional(),orderingKey:y.z.any().describe("Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.").optional(),attributes:y.z.any().describe("Per-rule attribute Mapping.Map merged on top of settings.attributes.").optional()}),f=require("@walkeros/core/dev"),S=f.z.object({messageStoragePolicy:f.z.object({allowedPersistenceRegions:f.z.array(f.z.string()).describe("Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).")}).describe("Topic-level message storage policy.").optional(),messageRetentionDuration:f.z.object({seconds:f.z.number().describe("Retention window in seconds. Default: project default.")}).describe("Topic-level retention configuration.").optional(),kmsKeyName:f.z.string().describe("Customer-managed encryption key (CMEK) resource name. Optional.").optional(),labels:f.z.record(f.z.string(),f.z.string()).describe("Topic labels for organization and billing.").optional()}),w=(0,m.zodToSchema)(h),k=(0,m.zodToSchema)(v),j=(0,m.zodToSchema)(S),O={};o(O,{env:()=>z,step:()=>W});var z={};o(z,{push:()=>J,simulation:()=>M});var A=require("events"),C=[],P=null,D=null,E=null,T=null,I=class extends A.EventEmitter{streamId;constructor(e){super(),this.streamId=e}getStreamId(){return this.streamId}onConnectionError(e){return C.push({method:"onConnectionError",args:[]}),this.on("error",e),{off:()=>{this.off("error",e)}}}__emitConnectionError(e){this.emit("error",e)}},N=[],R={convertStorageSchemaToProto2Descriptor:(e,t)=>(C.push({method:"adapt.convertStorageSchemaToProto2Descriptor",args:[e,t]}),{name:"root",field:[]})},q={WriterClient:class{constructor(e){C.push({method:"WriterClient.ctor",args:[e]})}async createStreamConnection(e,t){if("DEFAULT"!==e.streamId)throw new Error(`mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(e)}`);C.push({method:"createStreamConnection",args:[e,t]});const r=T;if(null!==r)throw T=null,r;const i=new I(`${e.destinationTable}/streams/_default`);return N.push(i),i}async getWriteStream(e,t){return C.push({method:"getWriteStream",args:[e,t]}),{tableSchema:{fields:[]}}}close(){C.push({method:"WriterClient.close",args:[]})}},JSONWriter:class{constructor(e){C.push({method:"JSONWriter.ctor",args:[e]})}appendRows(e,t){C.push({method:"appendRows",args:[e,t]});const r=D;if(null!==r)throw D=null,r;const i=P;P=null;const s=E;return E=null,{getResult:async()=>{if(null!==s)throw s;return{appendResult:{offset:{value:"0"}},rowErrors:i??[],writeStream:"projects/p/datasets/d/tables/t/streams/_default"}}}}close(){C.push({method:"JSONWriter.close",args:[]})}},DefaultStream:"DEFAULT"},x=()=>{};var J={get BigQuery(){return class{calls;options;constructor(e){this.options=e,this.calls=[]}dataset(e){return this.calls.push({method:"dataset",args:[e]}),this}table(e){return this.calls.push({method:"table",args:[e]}),this}async insert(e){return this.calls.push({method:"insert",args:[e]}),Promise.resolve()}get mockFn(){return x}}},get WriterClient(){return q.WriterClient},get JSONWriter(){return q.JSONWriter},get adapt(){return R},get managedwriterModule(){return q}},M=["BigQuery","WriterClient","JSONWriter","adapt"],W={};o(W,{pageView:()=>U,purchase:()=>G});var _=require("@walkeros/core");function B(e){return null==e?null:"object"==typeof e?Array.isArray(e)&&0===e.length?null:Array.isArray(e)||0!==Object.keys(e).length?JSON.stringify(e):null:JSON.stringify(e)}function Q(e){return function(e){return{name:e.name,data:B(e.data),context:B(e.context),globals:B(e.globals),custom:B(e.custom),user:B(e.user),nested:B(e.nested),consent:B(e.consent),id:e.id,trigger:e.trigger,entity:e.entity,action:e.action,timestamp:1e3*new Date(e.timestamp).getTime(),timing:e.timing,source:B(e.source)}}(e)}var F=(0,_.getEvent)("page view",{timestamp:1700001100,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}}),U={title:"Page view",description:"A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.",in:F,mapping:void 0,out:[["appendRows",[Q(F)]]]},K=(0,_.getEvent)("order complete",{timestamp:1700001101,data:{id:"ORD-500",total:199.99,items:[{sku:"SKU-1",qty:2}]},source:{type:"express",platform:"server"}}),G={title:"Purchase",description:"An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().",in:K,mapping:void 0,out:[["appendRows",[Q(K)]]]},L={};o(L,{env:()=>V,step:()=>X});var V={};o(V,{simulation:()=>$});var $=["PubSub"],X={};o(X,{defaultPush:()=>te,mappedAttributes:()=>se,mappedData:()=>oe,mappedOrderingKey:()=>ie,mappedTopic:()=>re,pageView:()=>ae});var H=require("@walkeros/core"),Y=(0,H.getEvent)("order complete",{timestamp:1700001100,data:{id:"ORD-500",total:199.99,currency:"EUR"},user:{id:"usr-789"},source:{type:"express",platform:"server",trace:"1a2b3c4d5e6f70819a2b3c4d5e6f7081",count:1}}),Z=(0,H.getEvent)("page view",{timestamp:1700001101,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server",trace:"9f8e7d6c5b4a39281706f5e4d3c2b1a0",count:1}});function ee(e){return Buffer.from(JSON.stringify(e))}var te={title:"Default publish",description:"An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.",in:Y,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Y)}]]},re={title:"Topic override",description:"A mapping rule overrides the destination default topic so order events are published to a dedicated topic.",in:Y,mapping:{settings:{topic:"orders"}},out:[["topic","orders",{messageOrdering:!1}],["publishMessage","orders",{data:ee(Y)}]]},ie={title:"Ordering key from user",description:"A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.",in:Y,mapping:{settings:{orderingKey:"user.id"}},out:[["topic","events",{messageOrdering:!0}],["publishMessage","events",{data:ee(Y),orderingKey:"usr-789"}]]},se={title:"Mapped attributes",description:"A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.",in:Y,mapping:{settings:{attributes:{entity:"entity",action:"action"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Y),attributes:{entity:"order",action:"complete"}}]]},oe={title:"Mapped payload",description:"A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.",in:Y,mapping:{data:{map:{order_id:"data.id",revenue:"data.total",currency:"data.currency"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee({order_id:"ORD-500",revenue:199.99,currency:"EUR"})}]]},ae={title:"Page view",description:"A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.",in:Z,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:ee(Z)}]]},ne={"auth-methods":{text:'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: "./sa.json" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',code:[{lang:"json",code:'{ "settings": { "projectId": "my-project", "bigquery": { "keyFilename": "./sa.json" } } }'},{lang:"json",code:'{ "settings": { "projectId": "my-project" } }'}]},"storage-format":{text:'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset "walkeros", table "events", location "EU" — all overridable via settings.'},"query-json-columns":{text:"Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.",code:[{lang:"sql",code:"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'"}]},"troubleshoot-empty-table":{text:"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK."}};//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dev.ts","../src/schemas.ts","../src/bigquery/schemas/index.ts","../src/bigquery/schemas/settings.ts","../src/bigquery/schemas/mapping.ts","../src/pubsub/schemas/index.ts","../src/pubsub/schemas/settings.ts","../src/pubsub/schemas/mapping.ts","../src/pubsub/schemas/setup.ts","../src/bigquery/examples/index.ts","../src/bigquery/examples/env.ts","../src/bigquery/__mocks__/@google-cloud/bigquery-storage.ts","../src/bigquery/examples/step.ts","../src/bigquery/eventToRow.ts","../src/pubsub/examples/index.ts","../src/pubsub/examples/env.ts","../src/pubsub/examples/step.ts","../src/hints.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './bigquery/examples';\nexport * as pubsubExamples from './pubsub/examples';\nexport { hints } from './hints';\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './bigquery/schemas';\nexport {\n settings as pubsubSettings,\n mapping as pubsubMapping,\n setup as pubsubSetup,\n} from './pubsub/schemas';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n datasetId: z\n .string()\n .min(1)\n .default('walkerOS')\n .describe(\n 'BigQuery dataset ID where events will be stored (like walker_events)',\n ),\n tableId: z\n .string()\n .min(1)\n .default('events')\n .describe('BigQuery table ID for event storage (like events)'),\n location: z\n .string()\n .default('EU')\n .describe('Geographic location for the BigQuery dataset (like US)'),\n bigquery: z\n .any()\n .describe(\n 'Additional BigQuery client configuration options (like { keyFilename: \"path/to/key.json\" })',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP BigQuery Mapping Schema\n * BigQuery has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport { SetupSchema, type Setup } from './setup';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n topic: z\n .string()\n .min(1)\n .describe(\n 'Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK.',\n ),\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). (deprecated: use config.credentials)',\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 orderingKey: z\n .any()\n .describe(\n 'Mapping value resolved per-event. Truthy enables per-key ordering for the publish.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Default per-event attribute map merged into every published message. Mapping.Map shape.',\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 Mapping Schema\n *\n * Per-rule overrides for topic, orderingKey, and attributes.\n */\nexport const MappingSchema = z.object({\n topic: z\n .string()\n .describe(\n 'Per-rule topic override. Falls back to settings.topic if absent.',\n )\n .optional(),\n orderingKey: z\n .any()\n .describe(\n 'Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Per-rule attribute Mapping.Map merged on top of settings.attributes.',\n )\n .optional(),\n});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub Setup Schema\n *\n * Provisioning options for `walkeros setup destination.<id>`. Idempotent topic\n * creation. Subscription provisioning is owned by the source side.\n */\nexport const SetupSchema = z.object({\n messageStoragePolicy: z\n .object({\n allowedPersistenceRegions: z\n .array(z.string())\n .describe(\n 'Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).',\n ),\n })\n .describe('Topic-level message storage policy.')\n .optional(),\n messageRetentionDuration: z\n .object({\n seconds: z\n .number()\n .describe('Retention window in seconds. Default: project default.'),\n })\n .describe('Topic-level retention configuration.')\n .optional(),\n kmsKeyName: z\n .string()\n .describe('Customer-managed encryption key (CMEK) resource name. Optional.')\n .optional(),\n labels: z\n .record(z.string(), z.string())\n .describe('Topic labels for organization and billing.')\n .optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env } from '../types';\nimport {\n managedwriter as mockManagedwriter,\n adapt as mockAdapt,\n} from '../__mocks__/@google-cloud/bigquery-storage';\n\n/**\n * Example environment configurations for GCP BigQuery destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual BigQuery SDK dependencies.\n *\n * The Storage Write API mocks (WriterClient, JSONWriter, adapt) are\n * re-exported from the package-local __mocks__ folder so example/test\n * code shares a single source of truth with the jest auto-mock.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Mock BigQuery client class that simulates dataset/table operations\n */\nfunction createMockBigQuery() {\n return class MockBigQuery {\n calls: Array<{ method: string; args: unknown[] }>;\n options: unknown;\n\n constructor(options?: unknown) {\n this.options = options;\n this.calls = [];\n }\n\n dataset(datasetId: string) {\n this.calls.push({ method: 'dataset', args: [datasetId] });\n return this;\n }\n\n table(tableId: string) {\n this.calls.push({ method: 'table', args: [tableId] });\n return this;\n }\n\n async insert(rows: unknown[]) {\n this.calls.push({ method: 'insert', args: [rows] });\n return Promise.resolve();\n }\n\n // For backwards compatibility with tests that might check mockFn\n get mockFn() {\n return noop;\n }\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing BigQuery insert operations without connecting\n * to actual GCP infrastructure.\n */\nexport const push: Env = {\n get BigQuery() {\n return createMockBigQuery() as unknown as Env['BigQuery'];\n },\n get WriterClient() {\n return mockManagedwriter.WriterClient as unknown as Env['WriterClient'];\n },\n get JSONWriter() {\n return mockManagedwriter.JSONWriter as unknown as Env['JSONWriter'];\n },\n get adapt() {\n return mockAdapt as unknown as Env['adapt'];\n },\n get managedwriterModule() {\n return mockManagedwriter as unknown as Env['managedwriterModule'];\n },\n};\n\nexport const simulation = ['BigQuery', 'WriterClient', 'JSONWriter', 'adapt'];\n","import { EventEmitter } from 'events';\n\nconst calls: Array<{ method: string; args: unknown[] }> = [];\n\ninterface MockRowError {\n index: number;\n code: number;\n message: string;\n}\n\nlet nextAppendRowErrors: MockRowError[] | null = null;\nlet nextAppendThrow: unknown = null;\nlet nextGetResultReject: unknown = null;\nlet nextCreateStreamConnectionError: unknown = null;\n\n/**\n * Honest stand-in for the SDK's StreamConnection: a REAL Node EventEmitter so\n * `emit('error', …)` with no listener throws exactly like the real one (Node's\n * special-cased `'error'` event). `onConnectionError` mirrors the SDK surface:\n * it registers an `'error'` listener and returns an `{ off }` disposable.\n */\nclass MockStreamConnection extends EventEmitter {\n private readonly streamId: string;\n constructor(streamId: string) {\n super();\n this.streamId = streamId;\n }\n getStreamId(): string {\n return this.streamId;\n }\n onConnectionError(listener: (err: unknown) => void): { off: () => void } {\n calls.push({ method: 'onConnectionError', args: [] });\n this.on('error', listener);\n return {\n off: () => {\n this.off('error', listener);\n },\n };\n }\n /**\n * Test-only: literally `this.emit('error', err)` with NO internal\n * listener-count guard, so before a listener is attached this reproduces\n * Node's real \"throw if no 'error' listener\" behavior. A fake that silently\n * swallowed would mask the very crash this listener exists to contain.\n */\n __emitConnectionError(err: unknown): void {\n this.emit('error', err);\n }\n}\n\n// The most recently created connection, so tests can emit on it and assert the\n// listener was registered.\nlet lastConnection: MockStreamConnection | null = null;\n\n// Every connection ever created (this reset cycle), so tests can assert that a\n// concurrent re-open did not orphan a connection still carrying an 'error'\n// listener.\nconst allConnections: MockStreamConnection[] = [];\n\nclass MockJSONWriter {\n constructor(_args: { connection: unknown; protoDescriptor: unknown }) {\n calls.push({ method: 'JSONWriter.ctor', args: [_args] });\n }\n appendRows(rows: unknown[], offsetValue?: unknown) {\n calls.push({ method: 'appendRows', args: [rows, offsetValue] });\n const queuedThrow = nextAppendThrow;\n if (queuedThrow !== null) {\n nextAppendThrow = null;\n throw queuedThrow;\n }\n const queuedErrors = nextAppendRowErrors;\n nextAppendRowErrors = null;\n const queuedReject = nextGetResultReject;\n nextGetResultReject = null;\n return {\n getResult: async () => {\n // Models a gRPC deadline-exceeded (or any stream error): the append is\n // accepted but getResult() rejects when the stream's deadline fires.\n if (queuedReject !== null) throw queuedReject;\n return {\n appendResult: { offset: { value: '0' } },\n rowErrors: queuedErrors ?? [],\n writeStream: 'projects/p/datasets/d/tables/t/streams/_default',\n };\n },\n };\n }\n close(): void {\n calls.push({ method: 'JSONWriter.close', args: [] });\n }\n}\n\nclass MockWriterClient {\n constructor(args: {\n projectId?: string;\n keyFilename?: string;\n credentials?: unknown;\n scopes?: string | string[];\n }) {\n calls.push({ method: 'WriterClient.ctor', args: [args] });\n }\n async createStreamConnection(\n args: {\n destinationTable: string;\n streamId: string;\n },\n options?: unknown,\n ) {\n // Match the real SDK: callers must pass streamId=DefaultStream (not streamType)\n // for default-stream use. Passing streamType triggers a CreateWriteStream\n // call with type='DEFAULT', which BQ rejects as TYPE_UNSPECIFIED.\n if (args.streamId !== 'DEFAULT') {\n throw new Error(\n `mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(args)}`,\n );\n }\n // args[1] captures the gax CallOptions (e.g. { timeout }) so tests can\n // assert the request deadline is forwarded to the appendRows stream.\n calls.push({ method: 'createStreamConnection', args: [args, options] });\n const queuedError = nextCreateStreamConnectionError;\n if (queuedError !== null) {\n nextCreateStreamConnectionError = null;\n throw queuedError;\n }\n const connection = new MockStreamConnection(\n `${args.destinationTable}/streams/_default`,\n );\n lastConnection = connection;\n allConnections.push(connection);\n return connection;\n }\n async getWriteStream(\n args: { streamId: string; view?: number },\n options?: unknown,\n ) {\n // args[1] captures the gax CallOptions so tests can assert the deadline\n // is forwarded to the unary schema fetch.\n calls.push({ method: 'getWriteStream', args: [args, options] });\n // Minimal tableSchema shape consumed by adapt.convertStorageSchemaToProto2Descriptor\n return {\n tableSchema: { fields: [] },\n };\n }\n close(): void {\n calls.push({ method: 'WriterClient.close', args: [] });\n }\n}\n\nconst adapt = {\n convertStorageSchemaToProto2Descriptor: (_schema: unknown, _root: string) => {\n calls.push({\n method: 'adapt.convertStorageSchemaToProto2Descriptor',\n args: [_schema, _root],\n });\n return { name: 'root', field: [] };\n },\n};\n\nconst managedwriter = {\n WriterClient: MockWriterClient,\n JSONWriter: MockJSONWriter,\n DefaultStream: 'DEFAULT',\n};\n\nconst protos = {\n google: {\n cloud: {\n bigquery: {\n storage: {\n v1: {\n WriteStreamView: {\n WRITE_STREAM_VIEW_UNSPECIFIED: 0,\n BASIC: 1,\n FULL: 2,\n },\n },\n },\n },\n },\n },\n};\n\n// Test-only helper. Not part of the real SDK.\nfunction __getMockCalls() {\n return calls;\n}\n\nfunction __resetMockCalls() {\n calls.length = 0;\n nextAppendRowErrors = null;\n nextAppendThrow = null;\n nextGetResultReject = null;\n nextCreateStreamConnectionError = null;\n lastConnection = null;\n allConnections.length = 0;\n}\n\n/**\n * Test-only: the most recently created StreamConnection, so a test can emit an\n * out-of-band `'error'` on it (via `__emitConnectionError`) and assert the\n * destination attached a listener.\n */\nfunction __getLastConnection(): MockStreamConnection {\n if (!lastConnection) throw new Error('mock: no StreamConnection created yet');\n return lastConnection;\n}\n\n/**\n * Test-only: every StreamConnection created since the last reset, so a test can\n * assert that a concurrent re-open did not orphan a connection that still\n * carries an 'error' listener (a leak).\n */\nfunction __getAllConnections(): MockStreamConnection[] {\n return allConnections.slice();\n}\n\n/**\n * Test-only: queue rowErrors for the next appendRows().getResult() call.\n * Auto-resets after one use.\n */\nfunction __setNextAppendRowErrors(errors: MockRowError[]): void {\n nextAppendRowErrors = errors;\n}\n\n/**\n * Test-only: make the next appendRows() throw synchronously, simulating a\n * Storage Write API call failure. Auto-resets after one use.\n */\nfunction __setNextAppendThrow(err: unknown): void {\n nextAppendThrow = err;\n}\n\n/**\n * Test-only: make the next appendRows().getResult() reject, simulating a gRPC\n * deadline-exceeded (or any stream error) surfacing through the pending write.\n * Auto-resets after one use.\n */\nfunction __setNextGetResultReject(err: unknown): void {\n nextGetResultReject = err;\n}\n\n/**\n * Test-only: queue an error for the next createStreamConnection() call so\n * tests can simulate openWriter failures (NotFound, INVALID_ARGUMENT, etc.).\n * Auto-resets after one use.\n */\nfunction __setNextOpenWriterError(err: unknown): void {\n nextCreateStreamConnectionError = err;\n}\n\nexport {\n managedwriter,\n adapt,\n protos,\n MockStreamConnection,\n __getMockCalls,\n __resetMockCalls,\n __getLastConnection,\n __getAllConnections,\n __setNextAppendRowErrors,\n __setNextAppendThrow,\n __setNextGetResultReject,\n __setNextOpenWriterError,\n};\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport { eventToRow } from '../eventToRow';\n\n/**\n * Mirror of push.ts via eventToRow() -- produces a flat 15-column row\n * with nested object/array values JSON-stringified. Imported directly\n * from the runtime helper so the step examples stay in sync with what\n * push.ts actually emits to JSONWriter.appendRows.\n */\nfunction expectedRow(event: WalkerOS.Event) {\n return eventToRow(event);\n}\n\n/**\n * Page view -- one row appended through JSONWriter.appendRows([row]).\n * Captured as a single intent-level call: ['appendRows', [row]].\n */\nconst pageViewEvent = getEvent('page view', {\n timestamp: 1700001100,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.',\n in: pageViewEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(pageViewEvent)]]],\n};\n\n/**\n * Purchase -- nested array in data.items is JSON.stringified into the\n * data column of the appended row.\n */\nconst purchaseEvent = getEvent('order complete', {\n timestamp: 1700001101,\n data: {\n id: 'ORD-500',\n total: 199.99,\n items: [{ sku: 'SKU-1', qty: 2 }],\n },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().',\n in: purchaseEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(purchaseEvent)]]],\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/** Row shape passed to JSONWriter.appendRows. Values are JSON-serializable scalars or strings. */\nexport interface BigQueryRow {\n [key: string]: string | number | null;\n name: string;\n data: string | null;\n context: string | null;\n globals: string | null;\n custom: string | null;\n user: string | null;\n nested: string | null;\n consent: string | null;\n id: string;\n trigger: string;\n entity: string;\n action: string;\n timestamp: number;\n timing: number;\n source: string | null;\n}\n\nfunction jsonOrNull(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n if (typeof value === 'object') {\n if (Array.isArray(value) && value.length === 0) return null;\n if (!Array.isArray(value) && Object.keys(value).length === 0) return null;\n return JSON.stringify(value);\n }\n return JSON.stringify(value);\n}\n\n/** Convert a walkerOS Event v4 into a 15-column BigQuery row in canonical order.\n *\n * Note: BQ Storage Write API encodes TIMESTAMP fields as INT64 microseconds\n * since epoch (the SDK calls Long.fromString on the value). ISO strings fail\n * with \"interior hyphen\" because Long.fromString sees the date hyphens as\n * non-numeric. Pass microseconds directly.\n */\nexport function eventToRow(event: WalkerOS.Event): BigQueryRow {\n return {\n name: event.name,\n data: jsonOrNull(event.data),\n context: jsonOrNull(event.context),\n globals: jsonOrNull(event.globals),\n custom: jsonOrNull(event.custom),\n user: jsonOrNull(event.user),\n nested: jsonOrNull(event.nested),\n consent: jsonOrNull(event.consent),\n id: event.id,\n trigger: event.trigger,\n entity: event.entity,\n action: event.action,\n timestamp: new Date(event.timestamp).getTime() * 1000, // microseconds since epoch\n timing: event.timing,\n source: jsonOrNull(event.source),\n };\n}\n","export * as env from './env';\nexport * as step from './step';\n","/**\n * Example environment metadata for GCP Pub/Sub destination.\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 destination touches\n * during a simulated run, used by the simulator to know what to stub.\n */\n\nexport const simulation = ['PubSub'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Pub/Sub step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['topic', topicName, topicOptions] // implicit topic-handle creation\n * ['publishMessage', topicName, messageOptions]\n * ['resumePublishing', topicName, orderingKey] // only on publish failure\n */\n\nconst orderEvent = getEvent('order complete', {\n timestamp: 1700001100,\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst pageEvent = getEvent('page view', {\n timestamp: 1700001101,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nfunction expectedPayload(event: unknown): Buffer {\n return Buffer.from(JSON.stringify(event));\n}\n\n/**\n * Default publish, no mapping. Settings.topic = 'events'. The destination\n * constructs a topic handle inline with messageOrdering=false (no ordering\n * key resolved) and publishes the full event JSON as the message body.\n */\nexport const defaultPush: Flow.StepExample = {\n title: 'Default publish',\n description:\n 'An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.',\n in: orderEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule topic override. Mapping carries `settings.topic = 'orders'`\n * which routes this rule to a dedicated topic.\n */\nexport const mappedTopic: Flow.StepExample = {\n title: 'Topic override',\n description:\n 'A mapping rule overrides the destination default topic so order events are published to a dedicated topic.',\n in: orderEvent,\n mapping: {\n settings: {\n topic: 'orders',\n },\n },\n out: [\n ['topic', 'orders', { messageOrdering: false }],\n ['publishMessage', 'orders', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule ordering key resolved from the event. `mapping.orderingKey =\n * 'user.id'` is a Mapping.Value that resolves to the event's user.id. The\n * topic handle is constructed with messageOrdering=true and the publish\n * carries the resolved orderingKey.\n */\nexport const mappedOrderingKey: Flow.StepExample = {\n title: 'Ordering key from user',\n description:\n 'A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.',\n in: orderEvent,\n mapping: {\n settings: {\n orderingKey: 'user.id',\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: true }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n orderingKey: 'usr-789',\n },\n ],\n ],\n};\n\n/**\n * Per-rule attributes. `mapping.attributes = { entity: 'entity', action:\n * 'action' }` is a Mapping.Map resolved per event. Each value is a path\n * resolved against the event.\n */\nexport const mappedAttributes: Flow.StepExample = {\n title: 'Mapped attributes',\n description:\n 'A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.',\n in: orderEvent,\n mapping: {\n settings: {\n attributes: {\n entity: 'entity',\n action: 'action',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n attributes: { entity: 'order', action: 'complete' },\n },\n ],\n ],\n};\n\n/**\n * Mapped data. `mapping.data` rewrites the publish body. The rewritten\n * object replaces the event as the message data.\n */\nexport const mappedData: Flow.StepExample = {\n title: 'Mapped payload',\n description:\n 'A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.',\n in: orderEvent,\n mapping: {\n data: {\n map: {\n order_id: 'data.id',\n revenue: 'data.total',\n currency: 'data.currency',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload({\n order_id: 'ORD-500',\n revenue: 199.99,\n currency: 'EUR',\n }),\n },\n ],\n ],\n};\n\n/**\n * Page view, no rule. Verifies free-form publish on a non-ordered topic\n * for an event with no special mapping.\n */\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.',\n in: pageEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(pageEvent) }],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'auth-methods': {\n text: 'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: \"./sa.json\" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\", \"bigquery\": { \"keyFilename\": \"./sa.json\" } } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\" } }',\n },\n ],\n },\n 'storage-format': {\n text: 'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset \"walkeros\", table \"events\", location \"EU\" — all overridable via settings.',\n },\n 'query-json-columns': {\n text: 'Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.',\n code: [\n {\n lang: 'sql',\n code: \"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'\",\n },\n ],\n },\n 'troubleshoot-empty-table': {\n text: \"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK.\",\n },\n};\n"],"mappings":"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","names":["examples_exports","mapping","settings","import_dev","import_dev","import_dev","import_dev","SettingsSchema","import_dev","MappingSchema","import_dev","settings","SettingsSchema","mapping","MappingSchema","examples_exports","env_exports","step_exports","env_exports","simulation","step_exports","pageView","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas.ts","../src/bigquery/schemas/index.ts","../src/bigquery/schemas/settings.ts","../src/bigquery/schemas/mapping.ts","../src/pubsub/schemas/index.ts","../src/pubsub/schemas/settings.ts","../src/pubsub/schemas/mapping.ts","../src/pubsub/schemas/setup.ts","../src/bigquery/examples/index.ts","../src/bigquery/examples/env.ts","../src/bigquery/__mocks__/@google-cloud/bigquery-storage.ts","../src/bigquery/examples/step.ts","../src/bigquery/eventToRow.ts","../src/pubsub/examples/index.ts","../src/pubsub/examples/env.ts","../src/pubsub/examples/step.ts","../src/hints.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './bigquery/examples';\nexport * as pubsubExamples from './pubsub/examples';\nexport { hints } from './hints';\n","// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './bigquery/schemas';\nexport {\n settings as pubsubSettings,\n mapping as pubsubMapping,\n setup as pubsubSetup,\n} from './pubsub/schemas';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n datasetId: z\n .string()\n .min(1)\n .default('walkerOS')\n .describe(\n 'BigQuery dataset ID where events will be stored (like walker_events)',\n ),\n tableId: z\n .string()\n .min(1)\n .default('events')\n .describe('BigQuery table ID for event storage (like events)'),\n location: z\n .string()\n .default('EU')\n .describe('Geographic location for the BigQuery dataset (like US)'),\n bigquery: z\n .any()\n .describe(\n 'Additional BigQuery client configuration options (like { keyFilename: \"path/to/key.json\" })',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP BigQuery Mapping Schema\n * BigQuery has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport { SetupSchema, type Setup } from './setup';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n topic: z\n .string()\n .min(1)\n .describe(\n 'Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK.',\n ),\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). (deprecated: use config.credentials)',\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 orderingKey: z\n .any()\n .describe(\n 'Mapping value resolved per-event. Truthy enables per-key ordering for the publish.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Default per-event attribute map merged into every published message. Mapping.Map shape.',\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 Mapping Schema\n *\n * Per-rule overrides for topic, orderingKey, and attributes.\n */\nexport const MappingSchema = z.object({\n topic: z\n .string()\n .describe(\n 'Per-rule topic override. Falls back to settings.topic if absent.',\n )\n .optional(),\n orderingKey: z\n .any()\n .describe(\n 'Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Per-rule attribute Mapping.Map merged on top of settings.attributes.',\n )\n .optional(),\n});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub Setup Schema\n *\n * Provisioning options for `walkeros setup destination.<id>`. Idempotent topic\n * creation. Subscription provisioning is owned by the source side.\n */\nexport const SetupSchema = z.object({\n messageStoragePolicy: z\n .object({\n allowedPersistenceRegions: z\n .array(z.string())\n .describe(\n 'Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).',\n ),\n })\n .describe('Topic-level message storage policy.')\n .optional(),\n messageRetentionDuration: z\n .object({\n seconds: z\n .number()\n .describe('Retention window in seconds. Default: project default.'),\n })\n .describe('Topic-level retention configuration.')\n .optional(),\n kmsKeyName: z\n .string()\n .describe('Customer-managed encryption key (CMEK) resource name. Optional.')\n .optional(),\n labels: z\n .record(z.string(), z.string())\n .describe('Topic labels for organization and billing.')\n .optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env } from '../types';\nimport {\n managedwriter as mockManagedwriter,\n adapt as mockAdapt,\n} from '../__mocks__/@google-cloud/bigquery-storage';\n\n/**\n * Example environment configurations for GCP BigQuery destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual BigQuery SDK dependencies.\n *\n * The Storage Write API mocks (WriterClient, JSONWriter, adapt) are\n * re-exported from the package-local __mocks__ folder so example/test\n * code shares a single source of truth with the jest auto-mock.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Mock BigQuery client class that simulates dataset/table operations\n */\nfunction createMockBigQuery() {\n return class MockBigQuery {\n calls: Array<{ method: string; args: unknown[] }>;\n options: unknown;\n\n constructor(options?: unknown) {\n this.options = options;\n this.calls = [];\n }\n\n dataset(datasetId: string) {\n this.calls.push({ method: 'dataset', args: [datasetId] });\n return this;\n }\n\n table(tableId: string) {\n this.calls.push({ method: 'table', args: [tableId] });\n return this;\n }\n\n async insert(rows: unknown[]) {\n this.calls.push({ method: 'insert', args: [rows] });\n return Promise.resolve();\n }\n\n // For backwards compatibility with tests that might check mockFn\n get mockFn() {\n return noop;\n }\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing BigQuery insert operations without connecting\n * to actual GCP infrastructure.\n */\nexport const push: Env = {\n get BigQuery() {\n return createMockBigQuery() as unknown as Env['BigQuery'];\n },\n get WriterClient() {\n return mockManagedwriter.WriterClient as unknown as Env['WriterClient'];\n },\n get JSONWriter() {\n return mockManagedwriter.JSONWriter as unknown as Env['JSONWriter'];\n },\n get adapt() {\n return mockAdapt as unknown as Env['adapt'];\n },\n get managedwriterModule() {\n return mockManagedwriter as unknown as Env['managedwriterModule'];\n },\n};\n\nexport const simulation = ['BigQuery', 'WriterClient', 'JSONWriter', 'adapt'];\n","import { EventEmitter } from 'events';\n\nconst calls: Array<{ method: string; args: unknown[] }> = [];\n\ninterface MockRowError {\n index: number;\n code: number;\n message: string;\n}\n\nlet nextAppendRowErrors: MockRowError[] | null = null;\nlet nextAppendThrow: unknown = null;\nlet nextGetResultReject: unknown = null;\nlet nextCreateStreamConnectionError: unknown = null;\n\n/**\n * Honest stand-in for the SDK's StreamConnection: a REAL Node EventEmitter so\n * `emit('error', …)` with no listener throws exactly like the real one (Node's\n * special-cased `'error'` event). `onConnectionError` mirrors the SDK surface:\n * it registers an `'error'` listener and returns an `{ off }` disposable.\n */\nclass MockStreamConnection extends EventEmitter {\n private readonly streamId: string;\n constructor(streamId: string) {\n super();\n this.streamId = streamId;\n }\n getStreamId(): string {\n return this.streamId;\n }\n onConnectionError(listener: (err: unknown) => void): { off: () => void } {\n calls.push({ method: 'onConnectionError', args: [] });\n this.on('error', listener);\n return {\n off: () => {\n this.off('error', listener);\n },\n };\n }\n /**\n * Test-only: literally `this.emit('error', err)` with NO internal\n * listener-count guard, so before a listener is attached this reproduces\n * Node's real \"throw if no 'error' listener\" behavior. A fake that silently\n * swallowed would mask the very crash this listener exists to contain.\n */\n __emitConnectionError(err: unknown): void {\n this.emit('error', err);\n }\n}\n\n// The most recently created connection, so tests can emit on it and assert the\n// listener was registered.\nlet lastConnection: MockStreamConnection | null = null;\n\n// Every connection ever created (this reset cycle), so tests can assert that a\n// concurrent re-open did not orphan a connection still carrying an 'error'\n// listener.\nconst allConnections: MockStreamConnection[] = [];\n\nclass MockJSONWriter {\n constructor(_args: { connection: unknown; protoDescriptor: unknown }) {\n calls.push({ method: 'JSONWriter.ctor', args: [_args] });\n }\n appendRows(rows: unknown[], offsetValue?: unknown) {\n calls.push({ method: 'appendRows', args: [rows, offsetValue] });\n const queuedThrow = nextAppendThrow;\n if (queuedThrow !== null) {\n nextAppendThrow = null;\n throw queuedThrow;\n }\n const queuedErrors = nextAppendRowErrors;\n nextAppendRowErrors = null;\n const queuedReject = nextGetResultReject;\n nextGetResultReject = null;\n return {\n getResult: async () => {\n // Models a gRPC deadline-exceeded (or any stream error): the append is\n // accepted but getResult() rejects when the stream's deadline fires.\n if (queuedReject !== null) throw queuedReject;\n return {\n appendResult: { offset: { value: '0' } },\n rowErrors: queuedErrors ?? [],\n writeStream: 'projects/p/datasets/d/tables/t/streams/_default',\n };\n },\n };\n }\n close(): void {\n calls.push({ method: 'JSONWriter.close', args: [] });\n }\n}\n\nclass MockWriterClient {\n constructor(args: {\n projectId?: string;\n keyFilename?: string;\n credentials?: unknown;\n scopes?: string | string[];\n }) {\n calls.push({ method: 'WriterClient.ctor', args: [args] });\n }\n async createStreamConnection(\n args: {\n destinationTable: string;\n streamId: string;\n },\n options?: unknown,\n ) {\n // Match the real SDK: callers must pass streamId=DefaultStream (not streamType)\n // for default-stream use. Passing streamType triggers a CreateWriteStream\n // call with type='DEFAULT', which BQ rejects as TYPE_UNSPECIFIED.\n if (args.streamId !== 'DEFAULT') {\n throw new Error(\n `mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(args)}`,\n );\n }\n // args[1] captures the gax CallOptions (e.g. { timeout }) so tests can\n // assert the request deadline is forwarded to the appendRows stream.\n calls.push({ method: 'createStreamConnection', args: [args, options] });\n const queuedError = nextCreateStreamConnectionError;\n if (queuedError !== null) {\n nextCreateStreamConnectionError = null;\n throw queuedError;\n }\n const connection = new MockStreamConnection(\n `${args.destinationTable}/streams/_default`,\n );\n lastConnection = connection;\n allConnections.push(connection);\n return connection;\n }\n async getWriteStream(\n args: { streamId: string; view?: number },\n options?: unknown,\n ) {\n // args[1] captures the gax CallOptions so tests can assert the deadline\n // is forwarded to the unary schema fetch.\n calls.push({ method: 'getWriteStream', args: [args, options] });\n // Minimal tableSchema shape consumed by adapt.convertStorageSchemaToProto2Descriptor\n return {\n tableSchema: { fields: [] },\n };\n }\n close(): void {\n calls.push({ method: 'WriterClient.close', args: [] });\n }\n}\n\nconst adapt = {\n convertStorageSchemaToProto2Descriptor: (_schema: unknown, _root: string) => {\n calls.push({\n method: 'adapt.convertStorageSchemaToProto2Descriptor',\n args: [_schema, _root],\n });\n return { name: 'root', field: [] };\n },\n};\n\nconst managedwriter = {\n WriterClient: MockWriterClient,\n JSONWriter: MockJSONWriter,\n DefaultStream: 'DEFAULT',\n};\n\nconst protos = {\n google: {\n cloud: {\n bigquery: {\n storage: {\n v1: {\n WriteStreamView: {\n WRITE_STREAM_VIEW_UNSPECIFIED: 0,\n BASIC: 1,\n FULL: 2,\n },\n },\n },\n },\n },\n },\n};\n\n// Test-only helper. Not part of the real SDK.\nfunction __getMockCalls() {\n return calls;\n}\n\nfunction __resetMockCalls() {\n calls.length = 0;\n nextAppendRowErrors = null;\n nextAppendThrow = null;\n nextGetResultReject = null;\n nextCreateStreamConnectionError = null;\n lastConnection = null;\n allConnections.length = 0;\n}\n\n/**\n * Test-only: the most recently created StreamConnection, so a test can emit an\n * out-of-band `'error'` on it (via `__emitConnectionError`) and assert the\n * destination attached a listener.\n */\nfunction __getLastConnection(): MockStreamConnection {\n if (!lastConnection) throw new Error('mock: no StreamConnection created yet');\n return lastConnection;\n}\n\n/**\n * Test-only: every StreamConnection created since the last reset, so a test can\n * assert that a concurrent re-open did not orphan a connection that still\n * carries an 'error' listener (a leak).\n */\nfunction __getAllConnections(): MockStreamConnection[] {\n return allConnections.slice();\n}\n\n/**\n * Test-only: queue rowErrors for the next appendRows().getResult() call.\n * Auto-resets after one use.\n */\nfunction __setNextAppendRowErrors(errors: MockRowError[]): void {\n nextAppendRowErrors = errors;\n}\n\n/**\n * Test-only: make the next appendRows() throw synchronously, simulating a\n * Storage Write API call failure. Auto-resets after one use.\n */\nfunction __setNextAppendThrow(err: unknown): void {\n nextAppendThrow = err;\n}\n\n/**\n * Test-only: make the next appendRows().getResult() reject, simulating a gRPC\n * deadline-exceeded (or any stream error) surfacing through the pending write.\n * Auto-resets after one use.\n */\nfunction __setNextGetResultReject(err: unknown): void {\n nextGetResultReject = err;\n}\n\n/**\n * Test-only: queue an error for the next createStreamConnection() call so\n * tests can simulate openWriter failures (NotFound, INVALID_ARGUMENT, etc.).\n * Auto-resets after one use.\n */\nfunction __setNextOpenWriterError(err: unknown): void {\n nextCreateStreamConnectionError = err;\n}\n\nexport {\n managedwriter,\n adapt,\n protos,\n MockStreamConnection,\n __getMockCalls,\n __resetMockCalls,\n __getLastConnection,\n __getAllConnections,\n __setNextAppendRowErrors,\n __setNextAppendThrow,\n __setNextGetResultReject,\n __setNextOpenWriterError,\n};\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport { eventToRow } from '../eventToRow';\n\n/**\n * Mirror of push.ts via eventToRow() -- produces a flat 15-column row\n * with nested object/array values JSON-stringified. Imported directly\n * from the runtime helper so the step examples stay in sync with what\n * push.ts actually emits to JSONWriter.appendRows.\n */\nfunction expectedRow(event: WalkerOS.Event) {\n return eventToRow(event);\n}\n\n/**\n * Page view -- one row appended through JSONWriter.appendRows([row]).\n * Captured as a single intent-level call: ['appendRows', [row]].\n */\nconst pageViewEvent = getEvent('page view', {\n timestamp: 1700001100,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.',\n in: pageViewEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(pageViewEvent)]]],\n};\n\n/**\n * Purchase -- nested array in data.items is JSON.stringified into the\n * data column of the appended row.\n */\nconst purchaseEvent = getEvent('order complete', {\n timestamp: 1700001101,\n data: {\n id: 'ORD-500',\n total: 199.99,\n items: [{ sku: 'SKU-1', qty: 2 }],\n },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().',\n in: purchaseEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(purchaseEvent)]]],\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/** Row shape passed to JSONWriter.appendRows. Values are JSON-serializable scalars or strings. */\nexport interface BigQueryRow {\n [key: string]: string | number | null;\n name: string;\n data: string | null;\n context: string | null;\n globals: string | null;\n custom: string | null;\n user: string | null;\n nested: string | null;\n consent: string | null;\n id: string;\n trigger: string;\n entity: string;\n action: string;\n timestamp: number;\n timing: number;\n source: string | null;\n}\n\nfunction jsonOrNull(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n if (typeof value === 'object') {\n if (Array.isArray(value) && value.length === 0) return null;\n if (!Array.isArray(value) && Object.keys(value).length === 0) return null;\n return JSON.stringify(value);\n }\n return JSON.stringify(value);\n}\n\n/** Convert a walkerOS Event v4 into a 15-column BigQuery row in canonical order.\n *\n * Note: BQ Storage Write API encodes TIMESTAMP fields as INT64 microseconds\n * since epoch (the SDK calls Long.fromString on the value). ISO strings fail\n * with \"interior hyphen\" because Long.fromString sees the date hyphens as\n * non-numeric. Pass microseconds directly.\n */\nexport function eventToRow(event: WalkerOS.Event): BigQueryRow {\n return {\n name: event.name,\n data: jsonOrNull(event.data),\n context: jsonOrNull(event.context),\n globals: jsonOrNull(event.globals),\n custom: jsonOrNull(event.custom),\n user: jsonOrNull(event.user),\n nested: jsonOrNull(event.nested),\n consent: jsonOrNull(event.consent),\n id: event.id,\n trigger: event.trigger,\n entity: event.entity,\n action: event.action,\n timestamp: new Date(event.timestamp).getTime() * 1000, // microseconds since epoch\n timing: event.timing,\n source: jsonOrNull(event.source),\n };\n}\n","export * as env from './env';\nexport * as step from './step';\n","/**\n * Example environment metadata for GCP Pub/Sub destination.\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 destination touches\n * during a simulated run, used by the simulator to know what to stub.\n */\n\nexport const simulation = ['PubSub'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Pub/Sub step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['topic', topicName, topicOptions] // implicit topic-handle creation\n * ['publishMessage', topicName, messageOptions]\n * ['resumePublishing', topicName, orderingKey] // only on publish failure\n */\n\n// Events reaching a server destination arrive already enriched by the upstream\n// collector, so they carry the run trace and per-run count. The collector\n// preserves these (stamp-if-absent), keeping the example deterministic.\nconst orderEvent = getEvent('order complete', {\n timestamp: 1700001100,\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: {\n type: 'express',\n platform: 'server',\n trace: '1a2b3c4d5e6f70819a2b3c4d5e6f7081',\n count: 1,\n },\n});\n\nconst pageEvent = getEvent('page view', {\n timestamp: 1700001101,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: {\n type: 'express',\n platform: 'server',\n trace: '9f8e7d6c5b4a39281706f5e4d3c2b1a0',\n count: 1,\n },\n});\n\nfunction expectedPayload(event: unknown): Buffer {\n return Buffer.from(JSON.stringify(event));\n}\n\n/**\n * Default publish, no mapping. Settings.topic = 'events'. The destination\n * constructs a topic handle inline with messageOrdering=false (no ordering\n * key resolved) and publishes the full event JSON as the message body.\n */\nexport const defaultPush: Flow.StepExample = {\n title: 'Default publish',\n description:\n 'An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.',\n in: orderEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule topic override. Mapping carries `settings.topic = 'orders'`\n * which routes this rule to a dedicated topic.\n */\nexport const mappedTopic: Flow.StepExample = {\n title: 'Topic override',\n description:\n 'A mapping rule overrides the destination default topic so order events are published to a dedicated topic.',\n in: orderEvent,\n mapping: {\n settings: {\n topic: 'orders',\n },\n },\n out: [\n ['topic', 'orders', { messageOrdering: false }],\n ['publishMessage', 'orders', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule ordering key resolved from the event. `mapping.orderingKey =\n * 'user.id'` is a Mapping.Value that resolves to the event's user.id. The\n * topic handle is constructed with messageOrdering=true and the publish\n * carries the resolved orderingKey.\n */\nexport const mappedOrderingKey: Flow.StepExample = {\n title: 'Ordering key from user',\n description:\n 'A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.',\n in: orderEvent,\n mapping: {\n settings: {\n orderingKey: 'user.id',\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: true }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n orderingKey: 'usr-789',\n },\n ],\n ],\n};\n\n/**\n * Per-rule attributes. `mapping.attributes = { entity: 'entity', action:\n * 'action' }` is a Mapping.Map resolved per event. Each value is a path\n * resolved against the event.\n */\nexport const mappedAttributes: Flow.StepExample = {\n title: 'Mapped attributes',\n description:\n 'A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.',\n in: orderEvent,\n mapping: {\n settings: {\n attributes: {\n entity: 'entity',\n action: 'action',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n attributes: { entity: 'order', action: 'complete' },\n },\n ],\n ],\n};\n\n/**\n * Mapped data. `mapping.data` rewrites the publish body. The rewritten\n * object replaces the event as the message data.\n */\nexport const mappedData: Flow.StepExample = {\n title: 'Mapped payload',\n description:\n 'A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.',\n in: orderEvent,\n mapping: {\n data: {\n map: {\n order_id: 'data.id',\n revenue: 'data.total',\n currency: 'data.currency',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload({\n order_id: 'ORD-500',\n revenue: 199.99,\n currency: 'EUR',\n }),\n },\n ],\n ],\n};\n\n/**\n * Page view, no rule. Verifies free-form publish on a non-ordered topic\n * for an event with no special mapping.\n */\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.',\n in: pageEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(pageEvent) }],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'auth-methods': {\n text: 'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: \"./sa.json\" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\", \"bigquery\": { \"keyFilename\": \"./sa.json\" } } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\" } }',\n },\n ],\n },\n 'storage-format': {\n text: 'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset \"walkeros\", table \"events\", location \"EU\" — all overridable via settings.',\n },\n 'query-json-columns': {\n text: 'Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.',\n code: [\n {\n lang: 'sql',\n code: \"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'\",\n },\n ],\n },\n 'troubleshoot-empty-table': {\n text: \"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK.\",\n },\n};\n"],"mappings":"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","names":["examples_exports","mapping","settings","import_dev","import_dev","import_dev","import_dev","SettingsSchema","import_dev","MappingSchema","import_dev","settings","SettingsSchema","mapping","MappingSchema","examples_exports","env_exports","step_exports","env_exports","simulation","step_exports","pageView","import_core"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,t=(t,r)=>{for(var i in r)e(t,i,{get:r[i],enumerable:!0})},r={};t(r,{mapping:()=>p,pubsubMapping:()=>v,pubsubSettings:()=>y,pubsubSetup:()=>f,settings:()=>l});import{zodToSchema as i}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";var o=s.object({client:s.any().describe("Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))").optional(),projectId:s.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),datasetId:s.string().min(1).default("walkerOS").describe("BigQuery dataset ID where events will be stored (like walker_events)"),tableId:s.string().min(1).default("events").describe("BigQuery table ID for event storage (like events)"),location:s.string().default("EU").describe("Geographic location for the BigQuery dataset (like US)"),bigquery:s.any().describe('Additional BigQuery client configuration options (like { keyFilename: "path/to/key.json" })').optional()});import{z as a}from"@walkeros/core/dev";var n=a.object({}),l=i(o),p=i(n);import{zodToSchema as c}from"@walkeros/core/dev";import{z as d}from"@walkeros/core/dev";var u=d.object({client:d.any().describe("Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))").optional(),projectId:d.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),topic:d.string().min(1).describe("Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK."),credentials:d.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC). (deprecated: use config.credentials)").optional(),apiEndpoint:d.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),orderingKey:d.any().describe("Mapping value resolved per-event. Truthy enables per-key ordering for the publish.").optional(),attributes:d.any().describe("Default per-event attribute map merged into every published message. Mapping.Map shape.").optional()});import{z as g}from"@walkeros/core/dev";var m=g.object({topic:g.string().describe("Per-rule topic override. Falls back to settings.topic if absent.").optional(),orderingKey:g.any().describe("Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.").optional(),attributes:g.any().describe("Per-rule attribute Mapping.Map merged on top of settings.attributes.").optional()});import{z as b}from"@walkeros/core/dev";var h=b.object({messageStoragePolicy:b.object({allowedPersistenceRegions:b.array(b.string()).describe("Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).")}).describe("Topic-level message storage policy.").optional(),messageRetentionDuration:b.object({seconds:b.number().describe("Retention window in seconds. Default: project default.")}).describe("Topic-level retention configuration.").optional(),kmsKeyName:b.string().describe("Customer-managed encryption key (CMEK) resource name. Optional.").optional(),labels:b.record(b.string(),b.string()).describe("Topic labels for organization and billing.").optional()}),y=c(u),v=c(m),f=c(h),S={};t(S,{env:()=>w,step:()=>J});var w={};t(w,{push:()=>R,simulation:()=>x});import{EventEmitter as k}from"events";var j=[],O=null,A=null,C=null,D=null,P=class extends k{streamId;constructor(e){super(),this.streamId=e}getStreamId(){return this.streamId}onConnectionError(e){return j.push({method:"onConnectionError",args:[]}),this.on("error",e),{off:()=>{this.off("error",e)}}}__emitConnectionError(e){this.emit("error",e)}},I=[],E={convertStorageSchemaToProto2Descriptor:(e,t)=>(j.push({method:"adapt.convertStorageSchemaToProto2Descriptor",args:[e,t]}),{name:"root",field:[]})},T={WriterClient:class{constructor(e){j.push({method:"WriterClient.ctor",args:[e]})}async createStreamConnection(e,t){if("DEFAULT"!==e.streamId)throw new Error(`mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(e)}`);j.push({method:"createStreamConnection",args:[e,t]});const r=D;if(null!==r)throw D=null,r;const i=new P(`${e.destinationTable}/streams/_default`);return I.push(i),i}async getWriteStream(e,t){return j.push({method:"getWriteStream",args:[e,t]}),{tableSchema:{fields:[]}}}close(){j.push({method:"WriterClient.close",args:[]})}},JSONWriter:class{constructor(e){j.push({method:"JSONWriter.ctor",args:[e]})}appendRows(e,t){j.push({method:"appendRows",args:[e,t]});const r=A;if(null!==r)throw A=null,r;const i=O;O=null;const s=C;return C=null,{getResult:async()=>{if(null!==s)throw s;return{appendResult:{offset:{value:"0"}},rowErrors:i??[],writeStream:"projects/p/datasets/d/tables/t/streams/_default"}}}}close(){j.push({method:"JSONWriter.close",args:[]})}},DefaultStream:"DEFAULT"},N=()=>{};var R={get BigQuery(){return class{calls;options;constructor(e){this.options=e,this.calls=[]}dataset(e){return this.calls.push({method:"dataset",args:[e]}),this}table(e){return this.calls.push({method:"table",args:[e]}),this}async insert(e){return this.calls.push({method:"insert",args:[e]}),Promise.resolve()}get mockFn(){return N}}},get WriterClient(){return T.WriterClient},get JSONWriter(){return T.JSONWriter},get adapt(){return E},get managedwriterModule(){return T}},x=["BigQuery","WriterClient","JSONWriter","adapt"],J={};t(J,{pageView:()=>_,purchase:()=>U});import{getEvent as M}from"@walkeros/core";function W(e){return null==e?null:"object"==typeof e?Array.isArray(e)&&0===e.length?null:Array.isArray(e)||0!==Object.keys(e).length?JSON.stringify(e):null:JSON.stringify(e)}function B(e){return function(e){return{name:e.name,data:W(e.data),context:W(e.context),globals:W(e.globals),custom:W(e.custom),user:W(e.user),nested:W(e.nested),consent:W(e.consent),id:e.id,trigger:e.trigger,entity:e.entity,action:e.action,timestamp:1e3*new Date(e.timestamp).getTime(),timing:e.timing,source:W(e.source)}}(e)}var Q=M("page view",{timestamp:1700001100,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}}),_={title:"Page view",description:"A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.",in:Q,mapping:void 0,out:[["appendRows",[B(Q)]]]},F=M("order complete",{timestamp:1700001101,data:{id:"ORD-500",total:199.99,items:[{sku:"SKU-1",qty:2}]},source:{type:"express",platform:"server"}}),U={title:"Purchase",description:"An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().",in:F,mapping:void 0,out:[["appendRows",[B(F)]]]},K={};t(K,{env:()=>q,step:()=>L});var q={};t(q,{simulation:()=>G});var G=["PubSub"],L={};t(L,{defaultPush:()=>H,mappedAttributes:()=>ee,mappedData:()=>te,mappedOrderingKey:()=>Z,mappedTopic:()=>Y,pageView:()=>re});import{getEvent as z}from"@walkeros/core";var V=z("order complete",{timestamp:1700001100,data:{id:"ORD-500",total:199.99,currency:"EUR"},user:{id:"usr-789"},source:{type:"express",platform:"server"}}),$=z("page view",{timestamp:1700001101,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}});function X(e){return Buffer.from(JSON.stringify(e))}var H={title:"Default publish",description:"An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.",in:V,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X(V)}]]},Y={title:"Topic override",description:"A mapping rule overrides the destination default topic so order events are published to a dedicated topic.",in:V,mapping:{settings:{topic:"orders"}},out:[["topic","orders",{messageOrdering:!1}],["publishMessage","orders",{data:X(V)}]]},Z={title:"Ordering key from user",description:"A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.",in:V,mapping:{settings:{orderingKey:"user.id"}},out:[["topic","events",{messageOrdering:!0}],["publishMessage","events",{data:X(V),orderingKey:"usr-789"}]]},ee={title:"Mapped attributes",description:"A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.",in:V,mapping:{settings:{attributes:{entity:"entity",action:"action"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X(V),attributes:{entity:"order",action:"complete"}}]]},te={title:"Mapped payload",description:"A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.",in:V,mapping:{data:{map:{order_id:"data.id",revenue:"data.total",currency:"data.currency"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X({order_id:"ORD-500",revenue:199.99,currency:"EUR"})}]]},re={title:"Page view",description:"A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.",in:$,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X($)}]]},ie={"auth-methods":{text:'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: "./sa.json" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',code:[{lang:"json",code:'{ "settings": { "projectId": "my-project", "bigquery": { "keyFilename": "./sa.json" } } }'},{lang:"json",code:'{ "settings": { "projectId": "my-project" } }'}]},"storage-format":{text:'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset "walkeros", table "events", location "EU" — all overridable via settings.'},"query-json-columns":{text:"Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.",code:[{lang:"sql",code:"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'"}]},"troubleshoot-empty-table":{text:"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK."}};export{S as examples,ie as hints,K as pubsubExamples,r as schemas};//# sourceMappingURL=dev.mjs.map
|
|
1
|
+
var e=Object.defineProperty,t=(t,r)=>{for(var i in r)e(t,i,{get:r[i],enumerable:!0})},r={};t(r,{mapping:()=>c,pubsubMapping:()=>f,pubsubSettings:()=>y,pubsubSetup:()=>v,settings:()=>l});import{zodToSchema as i}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";var o=s.object({client:s.any().describe("Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))").optional(),projectId:s.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),datasetId:s.string().min(1).default("walkerOS").describe("BigQuery dataset ID where events will be stored (like walker_events)"),tableId:s.string().min(1).default("events").describe("BigQuery table ID for event storage (like events)"),location:s.string().default("EU").describe("Geographic location for the BigQuery dataset (like US)"),bigquery:s.any().describe('Additional BigQuery client configuration options (like { keyFilename: "path/to/key.json" })').optional()});import{z as a}from"@walkeros/core/dev";var n=a.object({}),l=i(o),c=i(n);import{zodToSchema as d}from"@walkeros/core/dev";import{z as p}from"@walkeros/core/dev";var u=p.object({client:p.any().describe("Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))").optional(),projectId:p.string().min(1).describe("Google Cloud Project ID (like my-gcp-project)"),topic:p.string().min(1).describe("Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK."),credentials:p.any().describe("Service account credentials as a JSON string or an object with client_email and private_key. Default: Application Default Credentials (ADC). (deprecated: use config.credentials)").optional(),apiEndpoint:p.string().describe("Override Pub/Sub API endpoint. Useful for the local emulator (like localhost:8085).").optional(),orderingKey:p.any().describe("Mapping value resolved per-event. Truthy enables per-key ordering for the publish.").optional(),attributes:p.any().describe("Default per-event attribute map merged into every published message. Mapping.Map shape.").optional()});import{z as g}from"@walkeros/core/dev";var m=g.object({topic:g.string().describe("Per-rule topic override. Falls back to settings.topic if absent.").optional(),orderingKey:g.any().describe("Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.").optional(),attributes:g.any().describe("Per-rule attribute Mapping.Map merged on top of settings.attributes.").optional()});import{z as b}from"@walkeros/core/dev";var h=b.object({messageStoragePolicy:b.object({allowedPersistenceRegions:b.array(b.string()).describe("Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).")}).describe("Topic-level message storage policy.").optional(),messageRetentionDuration:b.object({seconds:b.number().describe("Retention window in seconds. Default: project default.")}).describe("Topic-level retention configuration.").optional(),kmsKeyName:b.string().describe("Customer-managed encryption key (CMEK) resource name. Optional.").optional(),labels:b.record(b.string(),b.string()).describe("Topic labels for organization and billing.").optional()}),y=d(u),f=d(m),v=d(h),S={};t(S,{env:()=>w,step:()=>J});var w={};t(w,{push:()=>R,simulation:()=>x});import{EventEmitter as k}from"events";var j=[],O=null,A=null,C=null,D=null,P=class extends k{streamId;constructor(e){super(),this.streamId=e}getStreamId(){return this.streamId}onConnectionError(e){return j.push({method:"onConnectionError",args:[]}),this.on("error",e),{off:()=>{this.off("error",e)}}}__emitConnectionError(e){this.emit("error",e)}},I=[],E={convertStorageSchemaToProto2Descriptor:(e,t)=>(j.push({method:"adapt.convertStorageSchemaToProto2Descriptor",args:[e,t]}),{name:"root",field:[]})},T={WriterClient:class{constructor(e){j.push({method:"WriterClient.ctor",args:[e]})}async createStreamConnection(e,t){if("DEFAULT"!==e.streamId)throw new Error(`mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(e)}`);j.push({method:"createStreamConnection",args:[e,t]});const r=D;if(null!==r)throw D=null,r;const i=new P(`${e.destinationTable}/streams/_default`);return I.push(i),i}async getWriteStream(e,t){return j.push({method:"getWriteStream",args:[e,t]}),{tableSchema:{fields:[]}}}close(){j.push({method:"WriterClient.close",args:[]})}},JSONWriter:class{constructor(e){j.push({method:"JSONWriter.ctor",args:[e]})}appendRows(e,t){j.push({method:"appendRows",args:[e,t]});const r=A;if(null!==r)throw A=null,r;const i=O;O=null;const s=C;return C=null,{getResult:async()=>{if(null!==s)throw s;return{appendResult:{offset:{value:"0"}},rowErrors:i??[],writeStream:"projects/p/datasets/d/tables/t/streams/_default"}}}}close(){j.push({method:"JSONWriter.close",args:[]})}},DefaultStream:"DEFAULT"},N=()=>{};var R={get BigQuery(){return class{calls;options;constructor(e){this.options=e,this.calls=[]}dataset(e){return this.calls.push({method:"dataset",args:[e]}),this}table(e){return this.calls.push({method:"table",args:[e]}),this}async insert(e){return this.calls.push({method:"insert",args:[e]}),Promise.resolve()}get mockFn(){return N}}},get WriterClient(){return T.WriterClient},get JSONWriter(){return T.JSONWriter},get adapt(){return E},get managedwriterModule(){return T}},x=["BigQuery","WriterClient","JSONWriter","adapt"],J={};t(J,{pageView:()=>_,purchase:()=>U});import{getEvent as M}from"@walkeros/core";function W(e){return null==e?null:"object"==typeof e?Array.isArray(e)&&0===e.length?null:Array.isArray(e)||0!==Object.keys(e).length?JSON.stringify(e):null:JSON.stringify(e)}function B(e){return function(e){return{name:e.name,data:W(e.data),context:W(e.context),globals:W(e.globals),custom:W(e.custom),user:W(e.user),nested:W(e.nested),consent:W(e.consent),id:e.id,trigger:e.trigger,entity:e.entity,action:e.action,timestamp:1e3*new Date(e.timestamp).getTime(),timing:e.timing,source:W(e.source)}}(e)}var Q=M("page view",{timestamp:1700001100,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server"}}),_={title:"Page view",description:"A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.",in:Q,mapping:void 0,out:[["appendRows",[B(Q)]]]},F=M("order complete",{timestamp:1700001101,data:{id:"ORD-500",total:199.99,items:[{sku:"SKU-1",qty:2}]},source:{type:"express",platform:"server"}}),U={title:"Purchase",description:"An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().",in:F,mapping:void 0,out:[["appendRows",[B(F)]]]},K={};t(K,{env:()=>q,step:()=>L});var q={};t(q,{simulation:()=>G});var G=["PubSub"],L={};t(L,{defaultPush:()=>H,mappedAttributes:()=>ee,mappedData:()=>te,mappedOrderingKey:()=>Z,mappedTopic:()=>Y,pageView:()=>re});import{getEvent as z}from"@walkeros/core";var V=z("order complete",{timestamp:1700001100,data:{id:"ORD-500",total:199.99,currency:"EUR"},user:{id:"usr-789"},source:{type:"express",platform:"server",trace:"1a2b3c4d5e6f70819a2b3c4d5e6f7081",count:1}}),$=z("page view",{timestamp:1700001101,data:{title:"Documentation",url:"https://example.com/docs"},source:{type:"express",platform:"server",trace:"9f8e7d6c5b4a39281706f5e4d3c2b1a0",count:1}});function X(e){return Buffer.from(JSON.stringify(e))}var H={title:"Default publish",description:"An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.",in:V,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X(V)}]]},Y={title:"Topic override",description:"A mapping rule overrides the destination default topic so order events are published to a dedicated topic.",in:V,mapping:{settings:{topic:"orders"}},out:[["topic","orders",{messageOrdering:!1}],["publishMessage","orders",{data:X(V)}]]},Z={title:"Ordering key from user",description:"A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.",in:V,mapping:{settings:{orderingKey:"user.id"}},out:[["topic","events",{messageOrdering:!0}],["publishMessage","events",{data:X(V),orderingKey:"usr-789"}]]},ee={title:"Mapped attributes",description:"A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.",in:V,mapping:{settings:{attributes:{entity:"entity",action:"action"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X(V),attributes:{entity:"order",action:"complete"}}]]},te={title:"Mapped payload",description:"A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.",in:V,mapping:{data:{map:{order_id:"data.id",revenue:"data.total",currency:"data.currency"}}},out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X({order_id:"ORD-500",revenue:199.99,currency:"EUR"})}]]},re={title:"Page view",description:"A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.",in:$,out:[["topic","events",{messageOrdering:!1}],["publishMessage","events",{data:X($)}]]},ie={"auth-methods":{text:'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: "./sa.json" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',code:[{lang:"json",code:'{ "settings": { "projectId": "my-project", "bigquery": { "keyFilename": "./sa.json" } } }'},{lang:"json",code:'{ "settings": { "projectId": "my-project" } }'}]},"storage-format":{text:'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset "walkeros", table "events", location "EU" — all overridable via settings.'},"query-json-columns":{text:"Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.",code:[{lang:"sql",code:"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'"}]},"troubleshoot-empty-table":{text:"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK."}};export{S as examples,ie as hints,K as pubsubExamples,r as schemas};//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas.ts","../src/bigquery/schemas/index.ts","../src/bigquery/schemas/settings.ts","../src/bigquery/schemas/mapping.ts","../src/pubsub/schemas/index.ts","../src/pubsub/schemas/settings.ts","../src/pubsub/schemas/mapping.ts","../src/pubsub/schemas/setup.ts","../src/bigquery/examples/index.ts","../src/bigquery/examples/env.ts","../src/bigquery/__mocks__/@google-cloud/bigquery-storage.ts","../src/bigquery/examples/step.ts","../src/bigquery/eventToRow.ts","../src/pubsub/examples/index.ts","../src/pubsub/examples/env.ts","../src/pubsub/examples/step.ts","../src/hints.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './bigquery/schemas';\nexport {\n settings as pubsubSettings,\n mapping as pubsubMapping,\n setup as pubsubSetup,\n} from './pubsub/schemas';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n datasetId: z\n .string()\n .min(1)\n .default('walkerOS')\n .describe(\n 'BigQuery dataset ID where events will be stored (like walker_events)',\n ),\n tableId: z\n .string()\n .min(1)\n .default('events')\n .describe('BigQuery table ID for event storage (like events)'),\n location: z\n .string()\n .default('EU')\n .describe('Geographic location for the BigQuery dataset (like US)'),\n bigquery: z\n .any()\n .describe(\n 'Additional BigQuery client configuration options (like { keyFilename: \"path/to/key.json\" })',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP BigQuery Mapping Schema\n * BigQuery has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport { SetupSchema, type Setup } from './setup';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n topic: z\n .string()\n .min(1)\n .describe(\n 'Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK.',\n ),\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). (deprecated: use config.credentials)',\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 orderingKey: z\n .any()\n .describe(\n 'Mapping value resolved per-event. Truthy enables per-key ordering for the publish.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Default per-event attribute map merged into every published message. Mapping.Map shape.',\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 Mapping Schema\n *\n * Per-rule overrides for topic, orderingKey, and attributes.\n */\nexport const MappingSchema = z.object({\n topic: z\n .string()\n .describe(\n 'Per-rule topic override. Falls back to settings.topic if absent.',\n )\n .optional(),\n orderingKey: z\n .any()\n .describe(\n 'Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Per-rule attribute Mapping.Map merged on top of settings.attributes.',\n )\n .optional(),\n});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub Setup Schema\n *\n * Provisioning options for `walkeros setup destination.<id>`. Idempotent topic\n * creation. Subscription provisioning is owned by the source side.\n */\nexport const SetupSchema = z.object({\n messageStoragePolicy: z\n .object({\n allowedPersistenceRegions: z\n .array(z.string())\n .describe(\n 'Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).',\n ),\n })\n .describe('Topic-level message storage policy.')\n .optional(),\n messageRetentionDuration: z\n .object({\n seconds: z\n .number()\n .describe('Retention window in seconds. Default: project default.'),\n })\n .describe('Topic-level retention configuration.')\n .optional(),\n kmsKeyName: z\n .string()\n .describe('Customer-managed encryption key (CMEK) resource name. Optional.')\n .optional(),\n labels: z\n .record(z.string(), z.string())\n .describe('Topic labels for organization and billing.')\n .optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env } from '../types';\nimport {\n managedwriter as mockManagedwriter,\n adapt as mockAdapt,\n} from '../__mocks__/@google-cloud/bigquery-storage';\n\n/**\n * Example environment configurations for GCP BigQuery destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual BigQuery SDK dependencies.\n *\n * The Storage Write API mocks (WriterClient, JSONWriter, adapt) are\n * re-exported from the package-local __mocks__ folder so example/test\n * code shares a single source of truth with the jest auto-mock.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Mock BigQuery client class that simulates dataset/table operations\n */\nfunction createMockBigQuery() {\n return class MockBigQuery {\n calls: Array<{ method: string; args: unknown[] }>;\n options: unknown;\n\n constructor(options?: unknown) {\n this.options = options;\n this.calls = [];\n }\n\n dataset(datasetId: string) {\n this.calls.push({ method: 'dataset', args: [datasetId] });\n return this;\n }\n\n table(tableId: string) {\n this.calls.push({ method: 'table', args: [tableId] });\n return this;\n }\n\n async insert(rows: unknown[]) {\n this.calls.push({ method: 'insert', args: [rows] });\n return Promise.resolve();\n }\n\n // For backwards compatibility with tests that might check mockFn\n get mockFn() {\n return noop;\n }\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing BigQuery insert operations without connecting\n * to actual GCP infrastructure.\n */\nexport const push: Env = {\n get BigQuery() {\n return createMockBigQuery() as unknown as Env['BigQuery'];\n },\n get WriterClient() {\n return mockManagedwriter.WriterClient as unknown as Env['WriterClient'];\n },\n get JSONWriter() {\n return mockManagedwriter.JSONWriter as unknown as Env['JSONWriter'];\n },\n get adapt() {\n return mockAdapt as unknown as Env['adapt'];\n },\n get managedwriterModule() {\n return mockManagedwriter as unknown as Env['managedwriterModule'];\n },\n};\n\nexport const simulation = ['BigQuery', 'WriterClient', 'JSONWriter', 'adapt'];\n","import { EventEmitter } from 'events';\n\nconst calls: Array<{ method: string; args: unknown[] }> = [];\n\ninterface MockRowError {\n index: number;\n code: number;\n message: string;\n}\n\nlet nextAppendRowErrors: MockRowError[] | null = null;\nlet nextAppendThrow: unknown = null;\nlet nextGetResultReject: unknown = null;\nlet nextCreateStreamConnectionError: unknown = null;\n\n/**\n * Honest stand-in for the SDK's StreamConnection: a REAL Node EventEmitter so\n * `emit('error', …)` with no listener throws exactly like the real one (Node's\n * special-cased `'error'` event). `onConnectionError` mirrors the SDK surface:\n * it registers an `'error'` listener and returns an `{ off }` disposable.\n */\nclass MockStreamConnection extends EventEmitter {\n private readonly streamId: string;\n constructor(streamId: string) {\n super();\n this.streamId = streamId;\n }\n getStreamId(): string {\n return this.streamId;\n }\n onConnectionError(listener: (err: unknown) => void): { off: () => void } {\n calls.push({ method: 'onConnectionError', args: [] });\n this.on('error', listener);\n return {\n off: () => {\n this.off('error', listener);\n },\n };\n }\n /**\n * Test-only: literally `this.emit('error', err)` with NO internal\n * listener-count guard, so before a listener is attached this reproduces\n * Node's real \"throw if no 'error' listener\" behavior. A fake that silently\n * swallowed would mask the very crash this listener exists to contain.\n */\n __emitConnectionError(err: unknown): void {\n this.emit('error', err);\n }\n}\n\n// The most recently created connection, so tests can emit on it and assert the\n// listener was registered.\nlet lastConnection: MockStreamConnection | null = null;\n\n// Every connection ever created (this reset cycle), so tests can assert that a\n// concurrent re-open did not orphan a connection still carrying an 'error'\n// listener.\nconst allConnections: MockStreamConnection[] = [];\n\nclass MockJSONWriter {\n constructor(_args: { connection: unknown; protoDescriptor: unknown }) {\n calls.push({ method: 'JSONWriter.ctor', args: [_args] });\n }\n appendRows(rows: unknown[], offsetValue?: unknown) {\n calls.push({ method: 'appendRows', args: [rows, offsetValue] });\n const queuedThrow = nextAppendThrow;\n if (queuedThrow !== null) {\n nextAppendThrow = null;\n throw queuedThrow;\n }\n const queuedErrors = nextAppendRowErrors;\n nextAppendRowErrors = null;\n const queuedReject = nextGetResultReject;\n nextGetResultReject = null;\n return {\n getResult: async () => {\n // Models a gRPC deadline-exceeded (or any stream error): the append is\n // accepted but getResult() rejects when the stream's deadline fires.\n if (queuedReject !== null) throw queuedReject;\n return {\n appendResult: { offset: { value: '0' } },\n rowErrors: queuedErrors ?? [],\n writeStream: 'projects/p/datasets/d/tables/t/streams/_default',\n };\n },\n };\n }\n close(): void {\n calls.push({ method: 'JSONWriter.close', args: [] });\n }\n}\n\nclass MockWriterClient {\n constructor(args: {\n projectId?: string;\n keyFilename?: string;\n credentials?: unknown;\n scopes?: string | string[];\n }) {\n calls.push({ method: 'WriterClient.ctor', args: [args] });\n }\n async createStreamConnection(\n args: {\n destinationTable: string;\n streamId: string;\n },\n options?: unknown,\n ) {\n // Match the real SDK: callers must pass streamId=DefaultStream (not streamType)\n // for default-stream use. Passing streamType triggers a CreateWriteStream\n // call with type='DEFAULT', which BQ rejects as TYPE_UNSPECIFIED.\n if (args.streamId !== 'DEFAULT') {\n throw new Error(\n `mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(args)}`,\n );\n }\n // args[1] captures the gax CallOptions (e.g. { timeout }) so tests can\n // assert the request deadline is forwarded to the appendRows stream.\n calls.push({ method: 'createStreamConnection', args: [args, options] });\n const queuedError = nextCreateStreamConnectionError;\n if (queuedError !== null) {\n nextCreateStreamConnectionError = null;\n throw queuedError;\n }\n const connection = new MockStreamConnection(\n `${args.destinationTable}/streams/_default`,\n );\n lastConnection = connection;\n allConnections.push(connection);\n return connection;\n }\n async getWriteStream(\n args: { streamId: string; view?: number },\n options?: unknown,\n ) {\n // args[1] captures the gax CallOptions so tests can assert the deadline\n // is forwarded to the unary schema fetch.\n calls.push({ method: 'getWriteStream', args: [args, options] });\n // Minimal tableSchema shape consumed by adapt.convertStorageSchemaToProto2Descriptor\n return {\n tableSchema: { fields: [] },\n };\n }\n close(): void {\n calls.push({ method: 'WriterClient.close', args: [] });\n }\n}\n\nconst adapt = {\n convertStorageSchemaToProto2Descriptor: (_schema: unknown, _root: string) => {\n calls.push({\n method: 'adapt.convertStorageSchemaToProto2Descriptor',\n args: [_schema, _root],\n });\n return { name: 'root', field: [] };\n },\n};\n\nconst managedwriter = {\n WriterClient: MockWriterClient,\n JSONWriter: MockJSONWriter,\n DefaultStream: 'DEFAULT',\n};\n\nconst protos = {\n google: {\n cloud: {\n bigquery: {\n storage: {\n v1: {\n WriteStreamView: {\n WRITE_STREAM_VIEW_UNSPECIFIED: 0,\n BASIC: 1,\n FULL: 2,\n },\n },\n },\n },\n },\n },\n};\n\n// Test-only helper. Not part of the real SDK.\nfunction __getMockCalls() {\n return calls;\n}\n\nfunction __resetMockCalls() {\n calls.length = 0;\n nextAppendRowErrors = null;\n nextAppendThrow = null;\n nextGetResultReject = null;\n nextCreateStreamConnectionError = null;\n lastConnection = null;\n allConnections.length = 0;\n}\n\n/**\n * Test-only: the most recently created StreamConnection, so a test can emit an\n * out-of-band `'error'` on it (via `__emitConnectionError`) and assert the\n * destination attached a listener.\n */\nfunction __getLastConnection(): MockStreamConnection {\n if (!lastConnection) throw new Error('mock: no StreamConnection created yet');\n return lastConnection;\n}\n\n/**\n * Test-only: every StreamConnection created since the last reset, so a test can\n * assert that a concurrent re-open did not orphan a connection that still\n * carries an 'error' listener (a leak).\n */\nfunction __getAllConnections(): MockStreamConnection[] {\n return allConnections.slice();\n}\n\n/**\n * Test-only: queue rowErrors for the next appendRows().getResult() call.\n * Auto-resets after one use.\n */\nfunction __setNextAppendRowErrors(errors: MockRowError[]): void {\n nextAppendRowErrors = errors;\n}\n\n/**\n * Test-only: make the next appendRows() throw synchronously, simulating a\n * Storage Write API call failure. Auto-resets after one use.\n */\nfunction __setNextAppendThrow(err: unknown): void {\n nextAppendThrow = err;\n}\n\n/**\n * Test-only: make the next appendRows().getResult() reject, simulating a gRPC\n * deadline-exceeded (or any stream error) surfacing through the pending write.\n * Auto-resets after one use.\n */\nfunction __setNextGetResultReject(err: unknown): void {\n nextGetResultReject = err;\n}\n\n/**\n * Test-only: queue an error for the next createStreamConnection() call so\n * tests can simulate openWriter failures (NotFound, INVALID_ARGUMENT, etc.).\n * Auto-resets after one use.\n */\nfunction __setNextOpenWriterError(err: unknown): void {\n nextCreateStreamConnectionError = err;\n}\n\nexport {\n managedwriter,\n adapt,\n protos,\n MockStreamConnection,\n __getMockCalls,\n __resetMockCalls,\n __getLastConnection,\n __getAllConnections,\n __setNextAppendRowErrors,\n __setNextAppendThrow,\n __setNextGetResultReject,\n __setNextOpenWriterError,\n};\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport { eventToRow } from '../eventToRow';\n\n/**\n * Mirror of push.ts via eventToRow() -- produces a flat 15-column row\n * with nested object/array values JSON-stringified. Imported directly\n * from the runtime helper so the step examples stay in sync with what\n * push.ts actually emits to JSONWriter.appendRows.\n */\nfunction expectedRow(event: WalkerOS.Event) {\n return eventToRow(event);\n}\n\n/**\n * Page view -- one row appended through JSONWriter.appendRows([row]).\n * Captured as a single intent-level call: ['appendRows', [row]].\n */\nconst pageViewEvent = getEvent('page view', {\n timestamp: 1700001100,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.',\n in: pageViewEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(pageViewEvent)]]],\n};\n\n/**\n * Purchase -- nested array in data.items is JSON.stringified into the\n * data column of the appended row.\n */\nconst purchaseEvent = getEvent('order complete', {\n timestamp: 1700001101,\n data: {\n id: 'ORD-500',\n total: 199.99,\n items: [{ sku: 'SKU-1', qty: 2 }],\n },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().',\n in: purchaseEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(purchaseEvent)]]],\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/** Row shape passed to JSONWriter.appendRows. Values are JSON-serializable scalars or strings. */\nexport interface BigQueryRow {\n [key: string]: string | number | null;\n name: string;\n data: string | null;\n context: string | null;\n globals: string | null;\n custom: string | null;\n user: string | null;\n nested: string | null;\n consent: string | null;\n id: string;\n trigger: string;\n entity: string;\n action: string;\n timestamp: number;\n timing: number;\n source: string | null;\n}\n\nfunction jsonOrNull(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n if (typeof value === 'object') {\n if (Array.isArray(value) && value.length === 0) return null;\n if (!Array.isArray(value) && Object.keys(value).length === 0) return null;\n return JSON.stringify(value);\n }\n return JSON.stringify(value);\n}\n\n/** Convert a walkerOS Event v4 into a 15-column BigQuery row in canonical order.\n *\n * Note: BQ Storage Write API encodes TIMESTAMP fields as INT64 microseconds\n * since epoch (the SDK calls Long.fromString on the value). ISO strings fail\n * with \"interior hyphen\" because Long.fromString sees the date hyphens as\n * non-numeric. Pass microseconds directly.\n */\nexport function eventToRow(event: WalkerOS.Event): BigQueryRow {\n return {\n name: event.name,\n data: jsonOrNull(event.data),\n context: jsonOrNull(event.context),\n globals: jsonOrNull(event.globals),\n custom: jsonOrNull(event.custom),\n user: jsonOrNull(event.user),\n nested: jsonOrNull(event.nested),\n consent: jsonOrNull(event.consent),\n id: event.id,\n trigger: event.trigger,\n entity: event.entity,\n action: event.action,\n timestamp: new Date(event.timestamp).getTime() * 1000, // microseconds since epoch\n timing: event.timing,\n source: jsonOrNull(event.source),\n };\n}\n","export * as env from './env';\nexport * as step from './step';\n","/**\n * Example environment metadata for GCP Pub/Sub destination.\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 destination touches\n * during a simulated run, used by the simulator to know what to stub.\n */\n\nexport const simulation = ['PubSub'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Pub/Sub step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['topic', topicName, topicOptions] // implicit topic-handle creation\n * ['publishMessage', topicName, messageOptions]\n * ['resumePublishing', topicName, orderingKey] // only on publish failure\n */\n\nconst orderEvent = getEvent('order complete', {\n timestamp: 1700001100,\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: { type: 'express', platform: 'server' },\n});\n\nconst pageEvent = getEvent('page view', {\n timestamp: 1700001101,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nfunction expectedPayload(event: unknown): Buffer {\n return Buffer.from(JSON.stringify(event));\n}\n\n/**\n * Default publish, no mapping. Settings.topic = 'events'. The destination\n * constructs a topic handle inline with messageOrdering=false (no ordering\n * key resolved) and publishes the full event JSON as the message body.\n */\nexport const defaultPush: Flow.StepExample = {\n title: 'Default publish',\n description:\n 'An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.',\n in: orderEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule topic override. Mapping carries `settings.topic = 'orders'`\n * which routes this rule to a dedicated topic.\n */\nexport const mappedTopic: Flow.StepExample = {\n title: 'Topic override',\n description:\n 'A mapping rule overrides the destination default topic so order events are published to a dedicated topic.',\n in: orderEvent,\n mapping: {\n settings: {\n topic: 'orders',\n },\n },\n out: [\n ['topic', 'orders', { messageOrdering: false }],\n ['publishMessage', 'orders', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule ordering key resolved from the event. `mapping.orderingKey =\n * 'user.id'` is a Mapping.Value that resolves to the event's user.id. The\n * topic handle is constructed with messageOrdering=true and the publish\n * carries the resolved orderingKey.\n */\nexport const mappedOrderingKey: Flow.StepExample = {\n title: 'Ordering key from user',\n description:\n 'A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.',\n in: orderEvent,\n mapping: {\n settings: {\n orderingKey: 'user.id',\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: true }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n orderingKey: 'usr-789',\n },\n ],\n ],\n};\n\n/**\n * Per-rule attributes. `mapping.attributes = { entity: 'entity', action:\n * 'action' }` is a Mapping.Map resolved per event. Each value is a path\n * resolved against the event.\n */\nexport const mappedAttributes: Flow.StepExample = {\n title: 'Mapped attributes',\n description:\n 'A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.',\n in: orderEvent,\n mapping: {\n settings: {\n attributes: {\n entity: 'entity',\n action: 'action',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n attributes: { entity: 'order', action: 'complete' },\n },\n ],\n ],\n};\n\n/**\n * Mapped data. `mapping.data` rewrites the publish body. The rewritten\n * object replaces the event as the message data.\n */\nexport const mappedData: Flow.StepExample = {\n title: 'Mapped payload',\n description:\n 'A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.',\n in: orderEvent,\n mapping: {\n data: {\n map: {\n order_id: 'data.id',\n revenue: 'data.total',\n currency: 'data.currency',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload({\n order_id: 'ORD-500',\n revenue: 199.99,\n currency: 'EUR',\n }),\n },\n ],\n ],\n};\n\n/**\n * Page view, no rule. Verifies free-form publish on a non-ordered topic\n * for an event with no special mapping.\n */\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.',\n in: pageEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(pageEvent) }],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'auth-methods': {\n text: 'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: \"./sa.json\" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\", \"bigquery\": { \"keyFilename\": \"./sa.json\" } } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\" } }',\n },\n ],\n },\n 'storage-format': {\n text: 'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset \"walkeros\", table \"events\", location \"EU\" — all overridable via settings.',\n },\n 'query-json-columns': {\n text: 'Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.',\n code: [\n {\n lang: 'sql',\n code: \"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'\",\n },\n ],\n },\n 'troubleshoot-empty-table': {\n text: \"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK.\",\n },\n};\n"],"mappings":"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","names":["mapping","settings","z","zodToSchema","z","SettingsSchema","z","MappingSchema","z","settings","zodToSchema","SettingsSchema","mapping","MappingSchema","examples_exports","env_exports","step_exports","env_exports","simulation","step_exports","pageView","getEvent"]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas.ts","../src/bigquery/schemas/index.ts","../src/bigquery/schemas/settings.ts","../src/bigquery/schemas/mapping.ts","../src/pubsub/schemas/index.ts","../src/pubsub/schemas/settings.ts","../src/pubsub/schemas/mapping.ts","../src/pubsub/schemas/setup.ts","../src/bigquery/examples/index.ts","../src/bigquery/examples/env.ts","../src/bigquery/__mocks__/@google-cloud/bigquery-storage.ts","../src/bigquery/examples/step.ts","../src/bigquery/eventToRow.ts","../src/pubsub/examples/index.ts","../src/pubsub/examples/env.ts","../src/pubsub/examples/step.ts","../src/hints.ts"],"sourcesContent":["// Browser-safe schema-only exports\n// This file exports ONLY schemas without any Node.js dependencies\nexport { settings, mapping } from './bigquery/schemas';\nexport {\n settings as pubsubSettings,\n mapping as pubsubMapping,\n setup as pubsubSetup,\n} from './pubsub/schemas';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud BigQuery client instance (like new BigQuery({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n datasetId: z\n .string()\n .min(1)\n .default('walkerOS')\n .describe(\n 'BigQuery dataset ID where events will be stored (like walker_events)',\n ),\n tableId: z\n .string()\n .min(1)\n .default('events')\n .describe('BigQuery table ID for event storage (like events)'),\n location: z\n .string()\n .default('EU')\n .describe('Geographic location for the BigQuery dataset (like US)'),\n bigquery: z\n .any()\n .describe(\n 'Additional BigQuery client configuration options (like { keyFilename: \"path/to/key.json\" })',\n )\n .optional(),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP BigQuery Mapping Schema\n * BigQuery has no event-level mapping configuration\n */\nexport const MappingSchema = z.object({});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\nimport { MappingSchema } from './mapping';\nimport { SetupSchema } from './setup';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport { MappingSchema, type Mapping } from './mapping';\nexport { SetupSchema, type Setup } from './setup';\n\n// JSON Schema\nexport const settings = zodToSchema(SettingsSchema);\nexport const mapping = zodToSchema(MappingSchema);\nexport const setup = zodToSchema(SetupSchema);\n","import { z } from '@walkeros/core/dev';\n\nexport const SettingsSchema = z.object({\n client: z\n .any()\n .describe(\n 'Google Cloud Pub/Sub client instance (like new PubSub({ projectId, keyFilename }))',\n )\n .optional(),\n projectId: z\n .string()\n .min(1)\n .describe('Google Cloud Project ID (like my-gcp-project)'),\n topic: z\n .string()\n .min(1)\n .describe(\n 'Pub/Sub topic short name (like events). The full resource name projects/<projectId>/topics/<topic> is built by the SDK.',\n ),\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). (deprecated: use config.credentials)',\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 orderingKey: z\n .any()\n .describe(\n 'Mapping value resolved per-event. Truthy enables per-key ordering for the publish.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Default per-event attribute map merged into every published message. Mapping.Map shape.',\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 Mapping Schema\n *\n * Per-rule overrides for topic, orderingKey, and attributes.\n */\nexport const MappingSchema = z.object({\n topic: z\n .string()\n .describe(\n 'Per-rule topic override. Falls back to settings.topic if absent.',\n )\n .optional(),\n orderingKey: z\n .any()\n .describe(\n 'Per-rule ordering-key Mapping.Value. Overrides settings.orderingKey when set.',\n )\n .optional(),\n attributes: z\n .any()\n .describe(\n 'Per-rule attribute Mapping.Map merged on top of settings.attributes.',\n )\n .optional(),\n});\n\n/**\n * Type inference from MappingSchema\n */\nexport type Mapping = z.infer<typeof MappingSchema>;\n","import { z } from '@walkeros/core/dev';\n\n/**\n * GCP Pub/Sub Setup Schema\n *\n * Provisioning options for `walkeros setup destination.<id>`. Idempotent topic\n * creation. Subscription provisioning is owned by the source side.\n */\nexport const SetupSchema = z.object({\n messageStoragePolicy: z\n .object({\n allowedPersistenceRegions: z\n .array(z.string())\n .describe(\n 'Geographic regions for at-rest message storage. Default: EU multi-region (eu-west1, eu-west3, eu-west4).',\n ),\n })\n .describe('Topic-level message storage policy.')\n .optional(),\n messageRetentionDuration: z\n .object({\n seconds: z\n .number()\n .describe('Retention window in seconds. Default: project default.'),\n })\n .describe('Topic-level retention configuration.')\n .optional(),\n kmsKeyName: z\n .string()\n .describe('Customer-managed encryption key (CMEK) resource name. Optional.')\n .optional(),\n labels: z\n .record(z.string(), z.string())\n .describe('Topic labels for organization and billing.')\n .optional(),\n});\n\nexport type Setup = z.infer<typeof SetupSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env } from '../types';\nimport {\n managedwriter as mockManagedwriter,\n adapt as mockAdapt,\n} from '../__mocks__/@google-cloud/bigquery-storage';\n\n/**\n * Example environment configurations for GCP BigQuery destination\n *\n * These environments provide standardized mock structures for testing\n * and development without requiring actual BigQuery SDK dependencies.\n *\n * The Storage Write API mocks (WriterClient, JSONWriter, adapt) are\n * re-exported from the package-local __mocks__ folder so example/test\n * code shares a single source of truth with the jest auto-mock.\n */\n\n// Simple no-op function for mocking\nconst noop = () => {};\n\n/**\n * Mock BigQuery client class that simulates dataset/table operations\n */\nfunction createMockBigQuery() {\n return class MockBigQuery {\n calls: Array<{ method: string; args: unknown[] }>;\n options: unknown;\n\n constructor(options?: unknown) {\n this.options = options;\n this.calls = [];\n }\n\n dataset(datasetId: string) {\n this.calls.push({ method: 'dataset', args: [datasetId] });\n return this;\n }\n\n table(tableId: string) {\n this.calls.push({ method: 'table', args: [tableId] });\n return this;\n }\n\n async insert(rows: unknown[]) {\n this.calls.push({ method: 'insert', args: [rows] });\n return Promise.resolve();\n }\n\n // For backwards compatibility with tests that might check mockFn\n get mockFn() {\n return noop;\n }\n };\n}\n\n/**\n * Standard mock environment for push operations\n *\n * Use this for testing BigQuery insert operations without connecting\n * to actual GCP infrastructure.\n */\nexport const push: Env = {\n get BigQuery() {\n return createMockBigQuery() as unknown as Env['BigQuery'];\n },\n get WriterClient() {\n return mockManagedwriter.WriterClient as unknown as Env['WriterClient'];\n },\n get JSONWriter() {\n return mockManagedwriter.JSONWriter as unknown as Env['JSONWriter'];\n },\n get adapt() {\n return mockAdapt as unknown as Env['adapt'];\n },\n get managedwriterModule() {\n return mockManagedwriter as unknown as Env['managedwriterModule'];\n },\n};\n\nexport const simulation = ['BigQuery', 'WriterClient', 'JSONWriter', 'adapt'];\n","import { EventEmitter } from 'events';\n\nconst calls: Array<{ method: string; args: unknown[] }> = [];\n\ninterface MockRowError {\n index: number;\n code: number;\n message: string;\n}\n\nlet nextAppendRowErrors: MockRowError[] | null = null;\nlet nextAppendThrow: unknown = null;\nlet nextGetResultReject: unknown = null;\nlet nextCreateStreamConnectionError: unknown = null;\n\n/**\n * Honest stand-in for the SDK's StreamConnection: a REAL Node EventEmitter so\n * `emit('error', …)` with no listener throws exactly like the real one (Node's\n * special-cased `'error'` event). `onConnectionError` mirrors the SDK surface:\n * it registers an `'error'` listener and returns an `{ off }` disposable.\n */\nclass MockStreamConnection extends EventEmitter {\n private readonly streamId: string;\n constructor(streamId: string) {\n super();\n this.streamId = streamId;\n }\n getStreamId(): string {\n return this.streamId;\n }\n onConnectionError(listener: (err: unknown) => void): { off: () => void } {\n calls.push({ method: 'onConnectionError', args: [] });\n this.on('error', listener);\n return {\n off: () => {\n this.off('error', listener);\n },\n };\n }\n /**\n * Test-only: literally `this.emit('error', err)` with NO internal\n * listener-count guard, so before a listener is attached this reproduces\n * Node's real \"throw if no 'error' listener\" behavior. A fake that silently\n * swallowed would mask the very crash this listener exists to contain.\n */\n __emitConnectionError(err: unknown): void {\n this.emit('error', err);\n }\n}\n\n// The most recently created connection, so tests can emit on it and assert the\n// listener was registered.\nlet lastConnection: MockStreamConnection | null = null;\n\n// Every connection ever created (this reset cycle), so tests can assert that a\n// concurrent re-open did not orphan a connection still carrying an 'error'\n// listener.\nconst allConnections: MockStreamConnection[] = [];\n\nclass MockJSONWriter {\n constructor(_args: { connection: unknown; protoDescriptor: unknown }) {\n calls.push({ method: 'JSONWriter.ctor', args: [_args] });\n }\n appendRows(rows: unknown[], offsetValue?: unknown) {\n calls.push({ method: 'appendRows', args: [rows, offsetValue] });\n const queuedThrow = nextAppendThrow;\n if (queuedThrow !== null) {\n nextAppendThrow = null;\n throw queuedThrow;\n }\n const queuedErrors = nextAppendRowErrors;\n nextAppendRowErrors = null;\n const queuedReject = nextGetResultReject;\n nextGetResultReject = null;\n return {\n getResult: async () => {\n // Models a gRPC deadline-exceeded (or any stream error): the append is\n // accepted but getResult() rejects when the stream's deadline fires.\n if (queuedReject !== null) throw queuedReject;\n return {\n appendResult: { offset: { value: '0' } },\n rowErrors: queuedErrors ?? [],\n writeStream: 'projects/p/datasets/d/tables/t/streams/_default',\n };\n },\n };\n }\n close(): void {\n calls.push({ method: 'JSONWriter.close', args: [] });\n }\n}\n\nclass MockWriterClient {\n constructor(args: {\n projectId?: string;\n keyFilename?: string;\n credentials?: unknown;\n scopes?: string | string[];\n }) {\n calls.push({ method: 'WriterClient.ctor', args: [args] });\n }\n async createStreamConnection(\n args: {\n destinationTable: string;\n streamId: string;\n },\n options?: unknown,\n ) {\n // Match the real SDK: callers must pass streamId=DefaultStream (not streamType)\n // for default-stream use. Passing streamType triggers a CreateWriteStream\n // call with type='DEFAULT', which BQ rejects as TYPE_UNSPECIFIED.\n if (args.streamId !== 'DEFAULT') {\n throw new Error(\n `mock createStreamConnection: expected streamId='DEFAULT', got ${JSON.stringify(args)}`,\n );\n }\n // args[1] captures the gax CallOptions (e.g. { timeout }) so tests can\n // assert the request deadline is forwarded to the appendRows stream.\n calls.push({ method: 'createStreamConnection', args: [args, options] });\n const queuedError = nextCreateStreamConnectionError;\n if (queuedError !== null) {\n nextCreateStreamConnectionError = null;\n throw queuedError;\n }\n const connection = new MockStreamConnection(\n `${args.destinationTable}/streams/_default`,\n );\n lastConnection = connection;\n allConnections.push(connection);\n return connection;\n }\n async getWriteStream(\n args: { streamId: string; view?: number },\n options?: unknown,\n ) {\n // args[1] captures the gax CallOptions so tests can assert the deadline\n // is forwarded to the unary schema fetch.\n calls.push({ method: 'getWriteStream', args: [args, options] });\n // Minimal tableSchema shape consumed by adapt.convertStorageSchemaToProto2Descriptor\n return {\n tableSchema: { fields: [] },\n };\n }\n close(): void {\n calls.push({ method: 'WriterClient.close', args: [] });\n }\n}\n\nconst adapt = {\n convertStorageSchemaToProto2Descriptor: (_schema: unknown, _root: string) => {\n calls.push({\n method: 'adapt.convertStorageSchemaToProto2Descriptor',\n args: [_schema, _root],\n });\n return { name: 'root', field: [] };\n },\n};\n\nconst managedwriter = {\n WriterClient: MockWriterClient,\n JSONWriter: MockJSONWriter,\n DefaultStream: 'DEFAULT',\n};\n\nconst protos = {\n google: {\n cloud: {\n bigquery: {\n storage: {\n v1: {\n WriteStreamView: {\n WRITE_STREAM_VIEW_UNSPECIFIED: 0,\n BASIC: 1,\n FULL: 2,\n },\n },\n },\n },\n },\n },\n};\n\n// Test-only helper. Not part of the real SDK.\nfunction __getMockCalls() {\n return calls;\n}\n\nfunction __resetMockCalls() {\n calls.length = 0;\n nextAppendRowErrors = null;\n nextAppendThrow = null;\n nextGetResultReject = null;\n nextCreateStreamConnectionError = null;\n lastConnection = null;\n allConnections.length = 0;\n}\n\n/**\n * Test-only: the most recently created StreamConnection, so a test can emit an\n * out-of-band `'error'` on it (via `__emitConnectionError`) and assert the\n * destination attached a listener.\n */\nfunction __getLastConnection(): MockStreamConnection {\n if (!lastConnection) throw new Error('mock: no StreamConnection created yet');\n return lastConnection;\n}\n\n/**\n * Test-only: every StreamConnection created since the last reset, so a test can\n * assert that a concurrent re-open did not orphan a connection that still\n * carries an 'error' listener (a leak).\n */\nfunction __getAllConnections(): MockStreamConnection[] {\n return allConnections.slice();\n}\n\n/**\n * Test-only: queue rowErrors for the next appendRows().getResult() call.\n * Auto-resets after one use.\n */\nfunction __setNextAppendRowErrors(errors: MockRowError[]): void {\n nextAppendRowErrors = errors;\n}\n\n/**\n * Test-only: make the next appendRows() throw synchronously, simulating a\n * Storage Write API call failure. Auto-resets after one use.\n */\nfunction __setNextAppendThrow(err: unknown): void {\n nextAppendThrow = err;\n}\n\n/**\n * Test-only: make the next appendRows().getResult() reject, simulating a gRPC\n * deadline-exceeded (or any stream error) surfacing through the pending write.\n * Auto-resets after one use.\n */\nfunction __setNextGetResultReject(err: unknown): void {\n nextGetResultReject = err;\n}\n\n/**\n * Test-only: queue an error for the next createStreamConnection() call so\n * tests can simulate openWriter failures (NotFound, INVALID_ARGUMENT, etc.).\n * Auto-resets after one use.\n */\nfunction __setNextOpenWriterError(err: unknown): void {\n nextCreateStreamConnectionError = err;\n}\n\nexport {\n managedwriter,\n adapt,\n protos,\n MockStreamConnection,\n __getMockCalls,\n __resetMockCalls,\n __getLastConnection,\n __getAllConnections,\n __setNextAppendRowErrors,\n __setNextAppendThrow,\n __setNextGetResultReject,\n __setNextOpenWriterError,\n};\n","import type { Flow, WalkerOS } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport { eventToRow } from '../eventToRow';\n\n/**\n * Mirror of push.ts via eventToRow() -- produces a flat 15-column row\n * with nested object/array values JSON-stringified. Imported directly\n * from the runtime helper so the step examples stay in sync with what\n * push.ts actually emits to JSONWriter.appendRows.\n */\nfunction expectedRow(event: WalkerOS.Event) {\n return eventToRow(event);\n}\n\n/**\n * Page view -- one row appended through JSONWriter.appendRows([row]).\n * Captured as a single intent-level call: ['appendRows', [row]].\n */\nconst pageViewEvent = getEvent('page view', {\n timestamp: 1700001100,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is appended as one row through the BigQuery Storage Write API JSONWriter. Nested objects/arrays in data, source, etc. are JSON-stringified by eventToRow.',\n in: pageViewEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(pageViewEvent)]]],\n};\n\n/**\n * Purchase -- nested array in data.items is JSON.stringified into the\n * data column of the appended row.\n */\nconst purchaseEvent = getEvent('order complete', {\n timestamp: 1700001101,\n data: {\n id: 'ORD-500',\n total: 199.99,\n items: [{ sku: 'SKU-1', qty: 2 }],\n },\n source: { type: 'express', platform: 'server' },\n});\n\nexport const purchase: Flow.StepExample = {\n title: 'Purchase',\n description:\n 'An order event is appended as a single row through JSONWriter.appendRows. The entire nested data object (including arrays like items) is JSON-stringified into the data column via eventToRow().',\n in: purchaseEvent,\n mapping: undefined,\n out: [['appendRows', [expectedRow(purchaseEvent)]]],\n};\n","import type { WalkerOS } from '@walkeros/core';\n\n/** Row shape passed to JSONWriter.appendRows. Values are JSON-serializable scalars or strings. */\nexport interface BigQueryRow {\n [key: string]: string | number | null;\n name: string;\n data: string | null;\n context: string | null;\n globals: string | null;\n custom: string | null;\n user: string | null;\n nested: string | null;\n consent: string | null;\n id: string;\n trigger: string;\n entity: string;\n action: string;\n timestamp: number;\n timing: number;\n source: string | null;\n}\n\nfunction jsonOrNull(value: unknown): string | null {\n if (value === undefined || value === null) return null;\n if (typeof value === 'object') {\n if (Array.isArray(value) && value.length === 0) return null;\n if (!Array.isArray(value) && Object.keys(value).length === 0) return null;\n return JSON.stringify(value);\n }\n return JSON.stringify(value);\n}\n\n/** Convert a walkerOS Event v4 into a 15-column BigQuery row in canonical order.\n *\n * Note: BQ Storage Write API encodes TIMESTAMP fields as INT64 microseconds\n * since epoch (the SDK calls Long.fromString on the value). ISO strings fail\n * with \"interior hyphen\" because Long.fromString sees the date hyphens as\n * non-numeric. Pass microseconds directly.\n */\nexport function eventToRow(event: WalkerOS.Event): BigQueryRow {\n return {\n name: event.name,\n data: jsonOrNull(event.data),\n context: jsonOrNull(event.context),\n globals: jsonOrNull(event.globals),\n custom: jsonOrNull(event.custom),\n user: jsonOrNull(event.user),\n nested: jsonOrNull(event.nested),\n consent: jsonOrNull(event.consent),\n id: event.id,\n trigger: event.trigger,\n entity: event.entity,\n action: event.action,\n timestamp: new Date(event.timestamp).getTime() * 1000, // microseconds since epoch\n timing: event.timing,\n source: jsonOrNull(event.source),\n };\n}\n","export * as env from './env';\nexport * as step from './step';\n","/**\n * Example environment metadata for GCP Pub/Sub destination.\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 destination touches\n * during a simulated run, used by the simulator to know what to stub.\n */\n\nexport const simulation = ['PubSub'];\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\n\n/**\n * Pub/Sub step examples. Each example's `out` is the array of recorded mock\n * calls produced by `push()`. The recording shape is:\n * ['topic', topicName, topicOptions] // implicit topic-handle creation\n * ['publishMessage', topicName, messageOptions]\n * ['resumePublishing', topicName, orderingKey] // only on publish failure\n */\n\n// Events reaching a server destination arrive already enriched by the upstream\n// collector, so they carry the run trace and per-run count. The collector\n// preserves these (stamp-if-absent), keeping the example deterministic.\nconst orderEvent = getEvent('order complete', {\n timestamp: 1700001100,\n data: { id: 'ORD-500', total: 199.99, currency: 'EUR' },\n user: { id: 'usr-789' },\n source: {\n type: 'express',\n platform: 'server',\n trace: '1a2b3c4d5e6f70819a2b3c4d5e6f7081',\n count: 1,\n },\n});\n\nconst pageEvent = getEvent('page view', {\n timestamp: 1700001101,\n data: { title: 'Documentation', url: 'https://example.com/docs' },\n source: {\n type: 'express',\n platform: 'server',\n trace: '9f8e7d6c5b4a39281706f5e4d3c2b1a0',\n count: 1,\n },\n});\n\nfunction expectedPayload(event: unknown): Buffer {\n return Buffer.from(JSON.stringify(event));\n}\n\n/**\n * Default publish, no mapping. Settings.topic = 'events'. The destination\n * constructs a topic handle inline with messageOrdering=false (no ordering\n * key resolved) and publishes the full event JSON as the message body.\n */\nexport const defaultPush: Flow.StepExample = {\n title: 'Default publish',\n description:\n 'An event is published to the configured Pub/Sub topic with the full JSON event as the message body and no ordering key.',\n in: orderEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule topic override. Mapping carries `settings.topic = 'orders'`\n * which routes this rule to a dedicated topic.\n */\nexport const mappedTopic: Flow.StepExample = {\n title: 'Topic override',\n description:\n 'A mapping rule overrides the destination default topic so order events are published to a dedicated topic.',\n in: orderEvent,\n mapping: {\n settings: {\n topic: 'orders',\n },\n },\n out: [\n ['topic', 'orders', { messageOrdering: false }],\n ['publishMessage', 'orders', { data: expectedPayload(orderEvent) }],\n ],\n};\n\n/**\n * Per-rule ordering key resolved from the event. `mapping.orderingKey =\n * 'user.id'` is a Mapping.Value that resolves to the event's user.id. The\n * topic handle is constructed with messageOrdering=true and the publish\n * carries the resolved orderingKey.\n */\nexport const mappedOrderingKey: Flow.StepExample = {\n title: 'Ordering key from user',\n description:\n 'A mapping resolves the ordering key from event.user.id, enabling per-user ordering for this publish.',\n in: orderEvent,\n mapping: {\n settings: {\n orderingKey: 'user.id',\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: true }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n orderingKey: 'usr-789',\n },\n ],\n ],\n};\n\n/**\n * Per-rule attributes. `mapping.attributes = { entity: 'entity', action:\n * 'action' }` is a Mapping.Map resolved per event. Each value is a path\n * resolved against the event.\n */\nexport const mappedAttributes: Flow.StepExample = {\n title: 'Mapped attributes',\n description:\n 'A mapping resolves a per-event attribute map, here exposing entity and action as Pub/Sub attributes for routing in subscribers.',\n in: orderEvent,\n mapping: {\n settings: {\n attributes: {\n entity: 'entity',\n action: 'action',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload(orderEvent),\n attributes: { entity: 'order', action: 'complete' },\n },\n ],\n ],\n};\n\n/**\n * Mapped data. `mapping.data` rewrites the publish body. The rewritten\n * object replaces the event as the message data.\n */\nexport const mappedData: Flow.StepExample = {\n title: 'Mapped payload',\n description:\n 'A data mapping transforms the event payload before publish. The rewritten object becomes the Pub/Sub message body.',\n in: orderEvent,\n mapping: {\n data: {\n map: {\n order_id: 'data.id',\n revenue: 'data.total',\n currency: 'data.currency',\n },\n },\n },\n out: [\n ['topic', 'events', { messageOrdering: false }],\n [\n 'publishMessage',\n 'events',\n {\n data: expectedPayload({\n order_id: 'ORD-500',\n revenue: 199.99,\n currency: 'EUR',\n }),\n },\n ],\n ],\n};\n\n/**\n * Page view, no rule. Verifies free-form publish on a non-ordered topic\n * for an event with no special mapping.\n */\nexport const pageView: Flow.StepExample = {\n title: 'Page view',\n description:\n 'A page view is published to the default topic with no ordering key, demonstrating the simplest publish path.',\n in: pageEvent,\n out: [\n ['topic', 'events', { messageOrdering: false }],\n ['publishMessage', 'events', { data: expectedPayload(pageEvent) }],\n ],\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'auth-methods': {\n text: 'Supports three auth methods: SA key file via bigquery options ({ bigquery: { keyFilename: \"./sa.json\" } }), Application Default Credentials (automatic on GCP infrastructure — just provide projectId), or a pre-configured BigQuery client instance (client option). See settings schema for all options.',\n code: [\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\", \"bigquery\": { \"keyFilename\": \"./sa.json\" } } }',\n },\n {\n lang: 'json',\n code: '{ \"settings\": { \"projectId\": \"my-project\" } }',\n },\n ],\n },\n 'storage-format': {\n text: 'All events are stored in a single table. Scalar fields (strings, numbers, booleans) are stored as-is. Nested objects and arrays are JSON-stringified automatically. Defaults: dataset \"walkeros\", table \"events\", location \"EU\" — all overridable via settings.',\n },\n 'query-json-columns': {\n text: 'Nested event fields (data, context, globals, user) are stored as JSON strings. Use BigQuery JSON_EXTRACT_SCALAR to query them. Field paths follow the walkerOS event structure.',\n code: [\n {\n lang: 'sql',\n code: \"SELECT JSON_EXTRACT_SCALAR(data, '$.total') AS total FROM `project.walkeros.events` WHERE entity = 'order'\",\n },\n ],\n },\n 'troubleshoot-empty-table': {\n text: \"Events not appearing? Common causes: projectId doesn't match GCP project, dataset doesn't exist yet (create via BigQuery console or bq CLI before first push), or SA key lacks bigquery.dataEditor role. The destination validates client/datasetId/tableId at push time but GCP permission errors surface from the BigQuery SDK.\",\n },\n};\n"],"mappings":"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","names":["mapping","settings","z","zodToSchema","z","SettingsSchema","z","MappingSchema","z","settings","zodToSchema","SettingsSchema","mapping","MappingSchema","examples_exports","env_exports","step_exports","env_exports","simulation","step_exports","pageView","getEvent"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as _google_cloud_bigquery_storage from '@google-cloud/bigquery-storage';
|
|
2
2
|
import { managedwriter } from '@google-cloud/bigquery-storage';
|
|
3
3
|
import { DestinationServer } from '@walkeros/server-core';
|
|
4
|
-
import { Destination as Destination$2, Credential,
|
|
4
|
+
import { ServiceAccount, Destination as Destination$2, Credential, Mapping as Mapping$2, SetupFn as SetupFn$2 } from '@walkeros/core';
|
|
5
5
|
import { BigQuery, BigQueryOptions } from '@google-cloud/bigquery';
|
|
6
6
|
import { PubSub, TopicMetadata } from '@google-cloud/pubsub';
|
|
7
7
|
|
|
@@ -21,6 +21,14 @@ interface Settings$1 {
|
|
|
21
21
|
tableId: string;
|
|
22
22
|
location?: string;
|
|
23
23
|
bigquery?: BigQueryOptions;
|
|
24
|
+
/**
|
|
25
|
+
* Service-account credentials parsed from `config.credentials` at init.
|
|
26
|
+
* Threaded to BOTH the query client (`new BigQuery`) and the data-plane
|
|
27
|
+
* Storage Write client (`new WriterClient`) so event writes authenticate
|
|
28
|
+
* with the configured SA instead of falling back to ADC on non-GCP runtimes.
|
|
29
|
+
* Runtime-only (the raw `config.credentials` may be a JSON string).
|
|
30
|
+
*/
|
|
31
|
+
credentials?: ServiceAccount;
|
|
24
32
|
writeClient?: managedwriter.WriterClient;
|
|
25
33
|
writer?: managedwriter.JSONWriter;
|
|
26
34
|
connection?: StreamConnection;
|