@walkeros/server-destination-file 3.4.0 → 3.4.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/dist/dev.js CHANGED
@@ -1 +1 @@
1
- "use strict";var e,t=Object.defineProperty,s=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,r=(e,s)=>{for(var n in s)t(e,n,{get:s[n],enumerable:!0})},o={};r(o,{examples:()=>v,schemas:()=>i}),module.exports=(e=o,((e,r,o,i)=>{if(r&&"object"==typeof r||"function"==typeof r)for(let l of n(r))a.call(e,l)||l===o||t(e,l,{get:()=>r[l],enumerable:!(i=s(r,l))||i.enumerable});return e})(t({},"__esModule",{value:!0}),e));var i={};r(i,{MappingSchema:()=>p,SettingsSchema:()=>m,mapping:()=>u,settings:()=>d});var l=require("@walkeros/core/dev"),c=require("@walkeros/core/dev"),m=c.z.object({filename:c.z.union([c.z.string().describe("Static output filename."),c.z.record(c.z.string(),c.z.unknown()).describe('Mapping.Value resolved per event (e.g. { key: "data.tenant" } or { fn: "$code:..." }).')]).describe('Output filename. Static string or Mapping.Value (e.g. { fn: "$code:..." } for daily rotation, { key: "data.tenant" } for sharding).'),format:c.z.enum(["jsonl","tsv","csv"]).optional().describe("Serialisation format. Defaults to jsonl."),fields:c.z.array(c.z.string()).optional().describe("Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.")}),p=require("@walkeros/core/dev").z.object({}).describe("No per-rule overrides for the file destination."),d=(0,l.zodToSchema)(m),u=(0,l.zodToSchema)(p),v={};r(v,{env:()=>f,step:()=>b});var f={};function g(){const e={captured:new Map,mkdirCalls:[]};return{_spy:e,fs:{createWriteStream:t=>{const s=e.captured.get(t),n=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,n);return{write:e=>(n.lines.push(e),!0),end(){n.ended=!0}}},mkdir:async t=>{e.mkdirCalls.push(t)}}}}r(f,{init:()=>j,push:()=>w});var j=g(),w=g(),b={};r(b,{csvObjectCell:()=>k,jsonlDailyRotation:()=>z,jsonlDefault:()=>y,jsonlTenantShardKey:()=>S,tsvBaerschLog:()=>O});var h=require("@walkeros/core"),y={in:(0,h.getEvent)("page view",{timestamp:17e11}),settings:{filename:"events.jsonl"},out:[["fs.writeFile","events.jsonl","jsonl:event"]]},O={in:(0,h.getEvent)("page view",{timestamp:17e11,data:{title:"Docs"},user:{session:"sess-1"},source:{id:"https://example.com/docs",type:"server",previous_id:"https://example.com/"}}),settings:{filename:"storage/mblog.txt",format:"tsv",fields:["timestamp","user.session","name","source.id","data.title","source.previous_id"]},out:[["fs.writeFile","storage/mblog.txt","1700000000000\tsess-1\tpage view\thttps://example.com/docs\tDocs\thttps://example.com/\n"]]},S={in:(0,h.getEvent)("custom event",{timestamp:17e11,data:{tenant:"acme"}}),settings:{filename:{key:"data.tenant"},format:"jsonl"},out:[["fs.writeFile","acme","jsonl:event"]]},z={in:(0,h.getEvent)("order complete",{timestamp:Date.UTC(2026,3,15,12,34,56),data:{id:"ORD-1"}}),settings:{filename:{fn:e=>{var t;const s=null!=(t=e.timestamp)?t:0;return`events-${new Date(s).toISOString().slice(0,10)}.jsonl`}},format:"jsonl"},out:[["fs.writeFile","events-2026-04-15.jsonl","jsonl:event"]]},k={in:(0,h.getEvent)("page view",{timestamp:17e11,data:{title:'Hello, "World"',count:3}}),settings:{filename:"events.csv",format:"csv",fields:["timestamp","name","data"]},out:[["fs.writeFile","events.csv",'1700000000000,page view,"{""title"":""Hello, \\""World\\"""",""count"":3}"\n']]};//# sourceMappingURL=dev.js.map
1
+ "use strict";var e,t=Object.defineProperty,s=Object.getOwnPropertyDescriptor,i=Object.getOwnPropertyNames,n=Object.prototype.hasOwnProperty,a=(e,s)=>{for(var i in s)t(e,i,{get:s[i],enumerable:!0})},o={};a(o,{examples:()=>u,schemas:()=>r}),module.exports=(e=o,((e,a,o,r)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let l of i(a))n.call(e,l)||l===o||t(e,l,{get:()=>a[l],enumerable:!(r=s(a,l))||r.enumerable});return e})(t({},"__esModule",{value:!0}),e));var r={};a(r,{MappingSchema:()=>m,SettingsSchema:()=>d,mapping:()=>f,settings:()=>p});var l=require("@walkeros/core/dev"),c=require("@walkeros/core/dev"),d=c.z.object({filename:c.z.union([c.z.string().describe("Static output filename."),c.z.record(c.z.string(),c.z.unknown()).describe('Mapping.Value resolved per event (e.g. { key: "data.tenant" } or { fn: "$code:..." }).')]).describe('Output filename. Static string or Mapping.Value (e.g. { fn: "$code:..." } for daily rotation, { key: "data.tenant" } for sharding).'),format:c.z.enum(["jsonl","tsv","csv"]).optional().describe("Serialisation format. Defaults to jsonl."),fields:c.z.array(c.z.string()).optional().describe("Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.")}),m=require("@walkeros/core/dev").z.object({}).describe("No per-rule overrides for the file destination."),p=(0,l.zodToSchema)(d),f=(0,l.zodToSchema)(m),u={};a(u,{env:()=>v,step:()=>j});var v={};function g(){const e={captured:new Map,mkdirCalls:[]};return{_spy:e,fs:{createWriteStream:t=>{const s=e.captured.get(t),i=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,i);return{write:e=>(i.lines.push(e),!0),end(){i.ended=!0}}},mkdir:async t=>{e.mkdirCalls.push(t)}}}}a(v,{init:()=>w,push:()=>h});var w=g(),h=g(),j={};a(j,{csvObjectCell:()=>k,jsonlDailyRotation:()=>z,jsonlDefault:()=>S,jsonlTenantShardKey:()=>O,tsvBaerschLog:()=>y});var b=require("@walkeros/core"),S={title:"JSONL append",description:"An event is appended as a single JSON line to a static filename using default JSONL formatting.",in:(0,b.getEvent)("page view",{timestamp:17e11}),settings:{filename:"events.jsonl"},out:[["fs.writeFile","events.jsonl","jsonl:event"]]},y={title:"TSV log",description:"An event is written as a tab-separated line selecting specific fields for a compact access-log style file.",in:(0,b.getEvent)("page view",{timestamp:17e11,data:{title:"Docs"},user:{session:"sess-1"},source:{id:"https://example.com/docs",type:"server",previous_id:"https://example.com/"}}),settings:{filename:"storage/mblog.txt",format:"tsv",fields:["timestamp","user.session","name","source.id","data.title","source.previous_id"]},out:[["fs.writeFile","storage/mblog.txt","1700000000000\tsess-1\tpage view\thttps://example.com/docs\tDocs\thttps://example.com/\n"]]},O={title:"Tenant sharding",description:"The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.",in:(0,b.getEvent)("custom event",{timestamp:17e11,data:{tenant:"acme"}}),settings:{filename:{key:"data.tenant"},format:"jsonl"},out:[["fs.writeFile","acme","jsonl:event"]]},z={title:"Daily rotation",description:"A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.",in:(0,b.getEvent)("order complete",{timestamp:Date.UTC(2026,3,15,12,34,56),data:{id:"ORD-1"}}),settings:{filename:{fn:e=>{var t;const s=null!=(t=e.timestamp)?t:0;return`events-${new Date(s).toISOString().slice(0,10)}.jsonl`}},format:"jsonl"},out:[["fs.writeFile","events-2026-04-15.jsonl","jsonl:event"]]},k={title:"CSV with object cell",description:"An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.",in:(0,b.getEvent)("page view",{timestamp:17e11,data:{title:'Hello, "World"',count:3}}),settings:{filename:"events.csv",format:"csv",fields:["timestamp","name","data"]},out:[["fs.writeFile","events.csv",'1700000000000,page view,"{""title"":""Hello, \\""World\\"""",""count"":3}"\n']]};//# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\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 filename: z\n .union([\n z.string().describe('Static output filename.'),\n z\n .record(z.string(), z.unknown())\n .describe(\n 'Mapping.Value resolved per event (e.g. { key: \"data.tenant\" } or { fn: \"$code:...\" }).',\n ),\n ])\n .describe(\n 'Output filename. Static string or Mapping.Value (e.g. { fn: \"$code:...\" } for daily rotation, { key: \"data.tenant\" } for sharding).',\n ),\n format: z\n .enum(['jsonl', 'tsv', 'csv'])\n .optional()\n .describe('Serialisation format. Defaults to jsonl.'),\n fields: z\n .array(z.string())\n .optional()\n .describe(\n 'Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.',\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z\n .object({})\n .describe('No per-rule overrides for the file destination.');\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env, FileWriteStream } from '../types';\n\n/**\n * Captured file state for assertions in tests.\n */\nexport interface CapturedFile {\n filename: string;\n lines: string[];\n ended: boolean;\n}\n\n// Narrow helper type aliases so the mock fs is typed explicitly without `any`.\ntype CreateWriteStreamFn = (\n path: string,\n options: { flags: string },\n) => FileWriteStream;\ntype MkdirFn = (path: string, options: { recursive: boolean }) => Promise<void>;\n\nexport interface SpyState {\n captured: Map<string, CapturedFile>;\n mkdirCalls: string[];\n}\n\nexport interface SpyEnv extends Env {\n _spy: SpyState;\n}\n\nfunction makeSpyEnv(): SpyEnv {\n const state: SpyState = {\n captured: new Map(),\n mkdirCalls: [],\n };\n\n const createWriteStream: CreateWriteStreamFn = (path) => {\n const existing = state.captured.get(path);\n const file: CapturedFile = existing ?? {\n filename: path,\n lines: [],\n ended: false,\n };\n if (!existing) state.captured.set(path, file);\n const stream: FileWriteStream = {\n write(chunk) {\n file.lines.push(chunk);\n return true;\n },\n end() {\n file.ended = true;\n },\n };\n return stream;\n };\n\n const mkdir: MkdirFn = async (path) => {\n state.mkdirCalls.push(path);\n };\n\n return {\n _spy: state,\n fs: {\n createWriteStream,\n mkdir,\n },\n };\n}\n\nexport const init: SpyEnv = makeSpyEnv();\nexport const push: SpyEnv = makeSpyEnv();\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Format } from '../types';\n\n/**\n * Raw filename-config shape accepted in step examples and flow.json.\n * Mirrors the runtime Settings.filename but types `fn` as string so\n * `$code:` tags (resolved at bundle time by walkerOS) are expressible\n * here without casting to a function type.\n */\nexport interface FileSettingsJson {\n filename:\n | string\n | {\n key?: string;\n fn?: string | ((value: unknown) => unknown);\n value?: unknown;\n };\n format?: Format;\n fields?: string[];\n}\n\n/**\n * Extended step example that carries destination-level settings for the\n * file destination.\n *\n * `out` is modeled at intent level as a single `['fs.writeFile', path, line]`\n * tuple per event (even though the destination internally uses a persistent\n * createWriteStream + write). This matches the design doc's preference for\n * readable intent-level callable tuples over stream-chain fidelity.\n *\n * Dropped / ignored events produce `out: []`.\n */\nexport type FileStepExample = Flow.StepExample & {\n settings: FileSettingsJson;\n};\n\n/** Default JSONL append. Static filename, all defaults. */\nexport const jsonlDefault: FileStepExample = {\n in: getEvent('page view', { timestamp: 1700000000000 }),\n settings: { filename: 'events.jsonl' },\n out: [\n [\n 'fs.writeFile',\n 'events.jsonl',\n // JSONL framework contract: JSON.stringify(event) + '\\n'.\n // The test recomputes this from example.in for the jsonl default to\n // avoid duplicating the full event shape here.\n 'jsonl:event',\n ],\n ],\n};\n\n/** Baersch-style TSV log: PHP parity case. */\nexport const tsvBaerschLog: FileStepExample = {\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Docs' },\n user: { session: 'sess-1' },\n source: {\n id: 'https://example.com/docs',\n type: 'server',\n previous_id: 'https://example.com/',\n },\n }),\n settings: {\n filename: 'storage/mblog.txt',\n format: 'tsv',\n fields: [\n 'timestamp',\n 'user.session',\n 'name',\n 'source.id',\n 'data.title',\n 'source.previous_id',\n ],\n },\n out: [\n [\n 'fs.writeFile',\n 'storage/mblog.txt',\n '1700000000000\\tsess-1\\tpage view\\thttps://example.com/docs\\tDocs\\thttps://example.com/\\n',\n ],\n ],\n};\n\n/** Tenant sharding via plain key extraction. */\nexport const jsonlTenantShardKey: FileStepExample = {\n in: getEvent('custom event', {\n timestamp: 1700000000000,\n data: { tenant: 'acme' },\n }),\n settings: {\n filename: { key: 'data.tenant' },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'acme', 'jsonl:event']],\n};\n\n/**\n * Daily rotation via a mapping fn. In flow.json this is authored as a\n * `$code:` string; walkerOS compiles it to a function at bundle time. For\n * in-process tests we pass the already-compiled function directly so the\n * example exercises the same code path without needing the bundler.\n */\nexport const jsonlDailyRotation: FileStepExample = {\n in: getEvent('order complete', {\n timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),\n data: { id: 'ORD-1' },\n }),\n settings: {\n filename: {\n fn: (value) => {\n const event = value as { timestamp?: number };\n const ts = event.timestamp ?? 0;\n return `events-${new Date(ts).toISOString().slice(0, 10)}.jsonl`;\n },\n },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'events-2026-04-15.jsonl', 'jsonl:event']],\n};\n\n/** CSV with an object cell. data is JSON-stringified, properly quoted. */\nexport const csvObjectCell: FileStepExample = {\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Hello, \"World\"', count: 3 },\n }),\n settings: {\n filename: 'events.csv',\n format: 'csv',\n fields: ['timestamp', 'name', 'data'],\n },\n out: [\n [\n 'fs.writeFile',\n 'events.csv',\n '1700000000000,page view,\"{\"\"title\"\":\"\"Hello, \\\\\"\"World\\\\\"\"\"\",\"\"count\"\":3}\"\\n',\n ],\n ],\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAAAA,cAA4B;;;ACA5B,iBAAkB;AAEX,IAAM,iBAAiB,aAAE,OAAO;AAAA,EACrC,UAAU,aACP,MAAM;AAAA,IACL,aAAE,OAAO,EAAE,SAAS,yBAAyB;AAAA,IAC7C,aACG,OAAO,aAAE,OAAO,GAAG,aAAE,QAAQ,CAAC,EAC9B;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC,EACA;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,aACL,KAAK,CAAC,SAAS,OAAO,KAAK,CAAC,EAC5B,SAAS,EACT,SAAS,0CAA0C;AAAA,EACtD,QAAQ,aACL,MAAM,aAAE,OAAO,CAAC,EAChB,SAAS,EACT;AAAA,IACC;AAAA,EACF;AACJ,CAAC;;;ACzBD,IAAAC,cAAkB;AAEX,IAAM,gBAAgB,cAC1B,OAAO,CAAC,CAAC,EACT,SAAS,iDAAiD;;;AFItD,IAAM,eAAW,yBAAY,cAAc;AAC3C,IAAM,cAAU,yBAAY,aAAa;;;AGThD;AAAA;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AA2BA,SAAS,aAAqB;AAC5B,QAAM,QAAkB;AAAA,IACtB,UAAU,oBAAI,IAAI;AAAA,IAClB,YAAY,CAAC;AAAA,EACf;AAEA,QAAM,oBAAyC,CAAC,SAAS;AACvD,UAAM,WAAW,MAAM,SAAS,IAAI,IAAI;AACxC,UAAM,OAAqB,8BAAY;AAAA,MACrC,UAAU;AAAA,MACV,OAAO,CAAC;AAAA,MACR,OAAO;AAAA,IACT;AACA,QAAI,CAAC,SAAU,OAAM,SAAS,IAAI,MAAM,IAAI;AAC5C,UAAM,SAA0B;AAAA,MAC9B,MAAM,OAAO;AACX,aAAK,MAAM,KAAK,KAAK;AACrB,eAAO;AAAA,MACT;AAAA,MACA,MAAM;AACJ,aAAK,QAAQ;AAAA,MACf;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,QAAiB,OAAO,SAAS;AACrC,UAAM,WAAW,KAAK,IAAI;AAAA,EAC5B;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,IAAI;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,OAAe,WAAW;AAChC,IAAM,OAAe,WAAW;;;ACnEvC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAyB;AAqClB,IAAM,eAAgC;AAAA,EAC3C,QAAI,sBAAS,aAAa,EAAE,WAAW,MAAc,CAAC;AAAA,EACtD,UAAU,EAAE,UAAU,eAAe;AAAA,EACrC,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,MAIA;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,gBAAiC;AAAA,EAC5C,QAAI,sBAAS,aAAa;AAAA,IACxB,WAAW;AAAA,IACX,MAAM,EAAE,OAAO,OAAO;AAAA,IACtB,MAAM,EAAE,SAAS,SAAS;AAAA,IAC1B,QAAQ;AAAA,MACN,IAAI;AAAA,MACJ,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,EACF,CAAC;AAAA,EACD,UAAU;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,sBAAuC;AAAA,EAClD,QAAI,sBAAS,gBAAgB;AAAA,IAC3B,WAAW;AAAA,IACX,MAAM,EAAE,QAAQ,OAAO;AAAA,EACzB,CAAC;AAAA,EACD,UAAU;AAAA,IACR,UAAU,EAAE,KAAK,cAAc;AAAA,IAC/B,QAAQ;AAAA,EACV;AAAA,EACA,KAAK,CAAC,CAAC,gBAAgB,QAAQ,aAAa,CAAC;AAC/C;AAQO,IAAM,qBAAsC;AAAA,EACjD,QAAI,sBAAS,kBAAkB;AAAA,IAC7B,WAAW,KAAK,IAAI,MAAM,GAAG,IAAI,IAAI,IAAI,EAAE;AAAA,IAC3C,MAAM,EAAE,IAAI,QAAQ;AAAA,EACtB,CAAC;AAAA,EACD,UAAU;AAAA,IACR,UAAU;AAAA,MACR,IAAI,CAAC,UAAU;AAhHrB;AAiHQ,cAAM,QAAQ;AACd,cAAM,MAAK,WAAM,cAAN,YAAmB;AAC9B,eAAO,UAAU,IAAI,KAAK,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,EAAE,CAAC;AAAA,MAC1D;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,EACV;AAAA,EACA,KAAK,CAAC,CAAC,gBAAgB,2BAA2B,aAAa,CAAC;AAClE;AAGO,IAAM,gBAAiC;AAAA,EAC5C,QAAI,sBAAS,aAAa;AAAA,IACxB,WAAW;AAAA,IACX,MAAM,EAAE,OAAO,kBAAkB,OAAO,EAAE;AAAA,EAC5C,CAAC;AAAA,EACD,UAAU;AAAA,IACR,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ,CAAC,aAAa,QAAQ,MAAM;AAAA,EACtC;AAAA,EACA,KAAK;AAAA,IACH;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":["import_dev","import_dev"]}
1
+ {"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\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 filename: z\n .union([\n z.string().describe('Static output filename.'),\n z\n .record(z.string(), z.unknown())\n .describe(\n 'Mapping.Value resolved per event (e.g. { key: \"data.tenant\" } or { fn: \"$code:...\" }).',\n ),\n ])\n .describe(\n 'Output filename. Static string or Mapping.Value (e.g. { fn: \"$code:...\" } for daily rotation, { key: \"data.tenant\" } for sharding).',\n ),\n format: z\n .enum(['jsonl', 'tsv', 'csv'])\n .optional()\n .describe('Serialisation format. Defaults to jsonl.'),\n fields: z\n .array(z.string())\n .optional()\n .describe(\n 'Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.',\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z\n .object({})\n .describe('No per-rule overrides for the file destination.');\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env, FileWriteStream } from '../types';\n\n/**\n * Captured file state for assertions in tests.\n */\nexport interface CapturedFile {\n filename: string;\n lines: string[];\n ended: boolean;\n}\n\n// Narrow helper type aliases so the mock fs is typed explicitly without `any`.\ntype CreateWriteStreamFn = (\n path: string,\n options: { flags: string },\n) => FileWriteStream;\ntype MkdirFn = (path: string, options: { recursive: boolean }) => Promise<void>;\n\nexport interface SpyState {\n captured: Map<string, CapturedFile>;\n mkdirCalls: string[];\n}\n\nexport interface SpyEnv extends Env {\n _spy: SpyState;\n}\n\nfunction makeSpyEnv(): SpyEnv {\n const state: SpyState = {\n captured: new Map(),\n mkdirCalls: [],\n };\n\n const createWriteStream: CreateWriteStreamFn = (path) => {\n const existing = state.captured.get(path);\n const file: CapturedFile = existing ?? {\n filename: path,\n lines: [],\n ended: false,\n };\n if (!existing) state.captured.set(path, file);\n const stream: FileWriteStream = {\n write(chunk) {\n file.lines.push(chunk);\n return true;\n },\n end() {\n file.ended = true;\n },\n };\n return stream;\n };\n\n const mkdir: MkdirFn = async (path) => {\n state.mkdirCalls.push(path);\n };\n\n return {\n _spy: state,\n fs: {\n createWriteStream,\n mkdir,\n },\n };\n}\n\nexport const init: SpyEnv = makeSpyEnv();\nexport const push: SpyEnv = makeSpyEnv();\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Format } from '../types';\n\n/**\n * Raw filename-config shape accepted in step examples and flow.json.\n * Mirrors the runtime Settings.filename but types `fn` as string so\n * `$code:` tags (resolved at bundle time by walkerOS) are expressible\n * here without casting to a function type.\n */\nexport interface FileSettingsJson {\n filename:\n | string\n | {\n key?: string;\n fn?: string | ((value: unknown) => unknown);\n value?: unknown;\n };\n format?: Format;\n fields?: string[];\n}\n\n/**\n * Extended step example that carries destination-level settings for the\n * file destination.\n *\n * `out` is modeled at intent level as a single `['fs.writeFile', path, line]`\n * tuple per event (even though the destination internally uses a persistent\n * createWriteStream + write). This matches the design doc's preference for\n * readable intent-level callable tuples over stream-chain fidelity.\n *\n * Dropped / ignored events produce `out: []`.\n */\nexport type FileStepExample = Flow.StepExample & {\n settings: FileSettingsJson;\n};\n\n/** Default JSONL append. Static filename, all defaults. */\nexport const jsonlDefault: FileStepExample = {\n title: 'JSONL append',\n description:\n 'An event is appended as a single JSON line to a static filename using default JSONL formatting.',\n in: getEvent('page view', { timestamp: 1700000000000 }),\n settings: { filename: 'events.jsonl' },\n out: [\n [\n 'fs.writeFile',\n 'events.jsonl',\n // JSONL framework contract: JSON.stringify(event) + '\\n'.\n // The test recomputes this from example.in for the jsonl default to\n // avoid duplicating the full event shape here.\n 'jsonl:event',\n ],\n ],\n};\n\n/** Baersch-style TSV log: PHP parity case. */\nexport const tsvBaerschLog: FileStepExample = {\n title: 'TSV log',\n description:\n 'An event is written as a tab-separated line selecting specific fields for a compact access-log style file.',\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Docs' },\n user: { session: 'sess-1' },\n source: {\n id: 'https://example.com/docs',\n type: 'server',\n previous_id: 'https://example.com/',\n },\n }),\n settings: {\n filename: 'storage/mblog.txt',\n format: 'tsv',\n fields: [\n 'timestamp',\n 'user.session',\n 'name',\n 'source.id',\n 'data.title',\n 'source.previous_id',\n ],\n },\n out: [\n [\n 'fs.writeFile',\n 'storage/mblog.txt',\n '1700000000000\\tsess-1\\tpage view\\thttps://example.com/docs\\tDocs\\thttps://example.com/\\n',\n ],\n ],\n};\n\n/** Tenant sharding via plain key extraction. */\nexport const jsonlTenantShardKey: FileStepExample = {\n title: 'Tenant sharding',\n description:\n 'The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.',\n in: getEvent('custom event', {\n timestamp: 1700000000000,\n data: { tenant: 'acme' },\n }),\n settings: {\n filename: { key: 'data.tenant' },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'acme', 'jsonl:event']],\n};\n\n/**\n * Daily rotation via a mapping fn. In flow.json this is authored as a\n * `$code:` string; walkerOS compiles it to a function at bundle time. For\n * in-process tests we pass the already-compiled function directly so the\n * example exercises the same code path without needing the bundler.\n */\nexport const jsonlDailyRotation: FileStepExample = {\n title: 'Daily rotation',\n description:\n 'A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.',\n in: getEvent('order complete', {\n timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),\n data: { id: 'ORD-1' },\n }),\n settings: {\n filename: {\n fn: (value) => {\n const event = value as { timestamp?: number };\n const ts = event.timestamp ?? 0;\n return `events-${new Date(ts).toISOString().slice(0, 10)}.jsonl`;\n },\n },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'events-2026-04-15.jsonl', 'jsonl:event']],\n};\n\n/** CSV with an object cell. data is JSON-stringified, properly quoted. */\nexport const csvObjectCell: FileStepExample = {\n title: 'CSV with object cell',\n description:\n 'An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.',\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Hello, \"World\"', count: 3 },\n }),\n settings: {\n filename: 'events.csv',\n format: 'csv',\n fields: ['timestamp', 'name', 'data'],\n },\n out: [\n [\n 'fs.writeFile',\n 'events.csv',\n '1700000000000,page view,\"{\"\"title\"\":\"\"Hello, \\\\\"\"World\\\\\"\"\"\",\"\"count\"\":3}\"\\n',\n ],\n ],\n};\n"],"mappings":"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","names":["import_dev","import_dev"]}
package/dist/dev.mjs CHANGED
@@ -1 +1 @@
1
- var e=Object.defineProperty,t=(t,s)=>{for(var a in s)e(t,a,{get:s[a],enumerable:!0})},s={};t(s,{MappingSchema:()=>r,SettingsSchema:()=>i,mapping:()=>m,settings:()=>l});import{zodToSchema as a}from"@walkeros/core/dev";import{z as n}from"@walkeros/core/dev";var i=n.object({filename:n.union([n.string().describe("Static output filename."),n.record(n.string(),n.unknown()).describe('Mapping.Value resolved per event (e.g. { key: "data.tenant" } or { fn: "$code:..." }).')]).describe('Output filename. Static string or Mapping.Value (e.g. { fn: "$code:..." } for daily rotation, { key: "data.tenant" } for sharding).'),format:n.enum(["jsonl","tsv","csv"]).optional().describe("Serialisation format. Defaults to jsonl."),fields:n.array(n.string()).optional().describe("Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.")});import{z as o}from"@walkeros/core/dev";var r=o.object({}).describe("No per-rule overrides for the file destination."),l=a(i),m=a(r),c={};t(c,{env:()=>p,step:()=>u});var p={};function d(){const e={captured:new Map,mkdirCalls:[]};return{_spy:e,fs:{createWriteStream:t=>{const s=e.captured.get(t),a=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,a);return{write:e=>(a.lines.push(e),!0),end(){a.ended=!0}}},mkdir:async t=>{e.mkdirCalls.push(t)}}}}t(p,{init:()=>v,push:()=>f});var v=d(),f=d(),u={};t(u,{csvObjectCell:()=>k,jsonlDailyRotation:()=>b,jsonlDefault:()=>j,jsonlTenantShardKey:()=>h,tsvBaerschLog:()=>w});import{getEvent as g}from"@walkeros/core";var j={in:g("page view",{timestamp:17e11}),settings:{filename:"events.jsonl"},out:[["fs.writeFile","events.jsonl","jsonl:event"]]},w={in:g("page view",{timestamp:17e11,data:{title:"Docs"},user:{session:"sess-1"},source:{id:"https://example.com/docs",type:"server",previous_id:"https://example.com/"}}),settings:{filename:"storage/mblog.txt",format:"tsv",fields:["timestamp","user.session","name","source.id","data.title","source.previous_id"]},out:[["fs.writeFile","storage/mblog.txt","1700000000000\tsess-1\tpage view\thttps://example.com/docs\tDocs\thttps://example.com/\n"]]},h={in:g("custom event",{timestamp:17e11,data:{tenant:"acme"}}),settings:{filename:{key:"data.tenant"},format:"jsonl"},out:[["fs.writeFile","acme","jsonl:event"]]},b={in:g("order complete",{timestamp:Date.UTC(2026,3,15,12,34,56),data:{id:"ORD-1"}}),settings:{filename:{fn:e=>{var t;const s=null!=(t=e.timestamp)?t:0;return`events-${new Date(s).toISOString().slice(0,10)}.jsonl`}},format:"jsonl"},out:[["fs.writeFile","events-2026-04-15.jsonl","jsonl:event"]]},k={in:g("page view",{timestamp:17e11,data:{title:'Hello, "World"',count:3}}),settings:{filename:"events.csv",format:"csv",fields:["timestamp","name","data"]},out:[["fs.writeFile","events.csv",'1700000000000,page view,"{""title"":""Hello, \\""World\\"""",""count"":3}"\n']]};export{c as examples,s as schemas};//# sourceMappingURL=dev.mjs.map
1
+ var e=Object.defineProperty,t=(t,s)=>{for(var i in s)e(t,i,{get:s[i],enumerable:!0})},s={};t(s,{MappingSchema:()=>r,SettingsSchema:()=>n,mapping:()=>m,settings:()=>l});import{zodToSchema as i}from"@walkeros/core/dev";import{z as a}from"@walkeros/core/dev";var n=a.object({filename:a.union([a.string().describe("Static output filename."),a.record(a.string(),a.unknown()).describe('Mapping.Value resolved per event (e.g. { key: "data.tenant" } or { fn: "$code:..." }).')]).describe('Output filename. Static string or Mapping.Value (e.g. { fn: "$code:..." } for daily rotation, { key: "data.tenant" } for sharding).'),format:a.enum(["jsonl","tsv","csv"]).optional().describe("Serialisation format. Defaults to jsonl."),fields:a.array(a.string()).optional().describe("Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.")});import{z as o}from"@walkeros/core/dev";var r=o.object({}).describe("No per-rule overrides for the file destination."),l=i(n),m=i(r),d={};t(d,{env:()=>c,step:()=>u});var c={};function p(){const e={captured:new Map,mkdirCalls:[]};return{_spy:e,fs:{createWriteStream:t=>{const s=e.captured.get(t),i=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,i);return{write:e=>(i.lines.push(e),!0),end(){i.ended=!0}}},mkdir:async t=>{e.mkdirCalls.push(t)}}}}t(c,{init:()=>f,push:()=>v});var f=p(),v=p(),u={};t(u,{csvObjectCell:()=>b,jsonlDailyRotation:()=>S,jsonlDefault:()=>w,jsonlTenantShardKey:()=>j,tsvBaerschLog:()=>h});import{getEvent as g}from"@walkeros/core";var w={title:"JSONL append",description:"An event is appended as a single JSON line to a static filename using default JSONL formatting.",in:g("page view",{timestamp:17e11}),settings:{filename:"events.jsonl"},out:[["fs.writeFile","events.jsonl","jsonl:event"]]},h={title:"TSV log",description:"An event is written as a tab-separated line selecting specific fields for a compact access-log style file.",in:g("page view",{timestamp:17e11,data:{title:"Docs"},user:{session:"sess-1"},source:{id:"https://example.com/docs",type:"server",previous_id:"https://example.com/"}}),settings:{filename:"storage/mblog.txt",format:"tsv",fields:["timestamp","user.session","name","source.id","data.title","source.previous_id"]},out:[["fs.writeFile","storage/mblog.txt","1700000000000\tsess-1\tpage view\thttps://example.com/docs\tDocs\thttps://example.com/\n"]]},j={title:"Tenant sharding",description:"The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.",in:g("custom event",{timestamp:17e11,data:{tenant:"acme"}}),settings:{filename:{key:"data.tenant"},format:"jsonl"},out:[["fs.writeFile","acme","jsonl:event"]]},S={title:"Daily rotation",description:"A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.",in:g("order complete",{timestamp:Date.UTC(2026,3,15,12,34,56),data:{id:"ORD-1"}}),settings:{filename:{fn:e=>{var t;const s=null!=(t=e.timestamp)?t:0;return`events-${new Date(s).toISOString().slice(0,10)}.jsonl`}},format:"jsonl"},out:[["fs.writeFile","events-2026-04-15.jsonl","jsonl:event"]]},b={title:"CSV with object cell",description:"An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.",in:g("page view",{timestamp:17e11,data:{title:'Hello, "World"',count:3}}),settings:{filename:"events.csv",format:"csv",fields:["timestamp","name","data"]},out:[["fs.writeFile","events.csv",'1700000000000,page view,"{""title"":""Hello, \\""World\\"""",""count"":3}"\n']]};export{d as examples,s as schemas};//# sourceMappingURL=dev.mjs.map
package/dist/dev.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["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 filename: z\n .union([\n z.string().describe('Static output filename.'),\n z\n .record(z.string(), z.unknown())\n .describe(\n 'Mapping.Value resolved per event (e.g. { key: \"data.tenant\" } or { fn: \"$code:...\" }).',\n ),\n ])\n .describe(\n 'Output filename. Static string or Mapping.Value (e.g. { fn: \"$code:...\" } for daily rotation, { key: \"data.tenant\" } for sharding).',\n ),\n format: z\n .enum(['jsonl', 'tsv', 'csv'])\n .optional()\n .describe('Serialisation format. Defaults to jsonl.'),\n fields: z\n .array(z.string())\n .optional()\n .describe(\n 'Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.',\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z\n .object({})\n .describe('No per-rule overrides for the file destination.');\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env, FileWriteStream } from '../types';\n\n/**\n * Captured file state for assertions in tests.\n */\nexport interface CapturedFile {\n filename: string;\n lines: string[];\n ended: boolean;\n}\n\n// Narrow helper type aliases so the mock fs is typed explicitly without `any`.\ntype CreateWriteStreamFn = (\n path: string,\n options: { flags: string },\n) => FileWriteStream;\ntype MkdirFn = (path: string, options: { recursive: boolean }) => Promise<void>;\n\nexport interface SpyState {\n captured: Map<string, CapturedFile>;\n mkdirCalls: string[];\n}\n\nexport interface SpyEnv extends Env {\n _spy: SpyState;\n}\n\nfunction makeSpyEnv(): SpyEnv {\n const state: SpyState = {\n captured: new Map(),\n mkdirCalls: [],\n };\n\n const createWriteStream: CreateWriteStreamFn = (path) => {\n const existing = state.captured.get(path);\n const file: CapturedFile = existing ?? {\n filename: path,\n lines: [],\n ended: false,\n };\n if (!existing) state.captured.set(path, file);\n const stream: FileWriteStream = {\n write(chunk) {\n file.lines.push(chunk);\n return true;\n },\n end() {\n file.ended = true;\n },\n };\n return stream;\n };\n\n const mkdir: MkdirFn = async (path) => {\n state.mkdirCalls.push(path);\n };\n\n return {\n _spy: state,\n fs: {\n createWriteStream,\n mkdir,\n },\n };\n}\n\nexport const init: SpyEnv = makeSpyEnv();\nexport const push: SpyEnv = makeSpyEnv();\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Format } from '../types';\n\n/**\n * Raw filename-config shape accepted in step examples and flow.json.\n * Mirrors the runtime Settings.filename but types `fn` as string so\n * `$code:` tags (resolved at bundle time by walkerOS) are expressible\n * here without casting to a function type.\n */\nexport interface FileSettingsJson {\n filename:\n | string\n | {\n key?: string;\n fn?: string | ((value: unknown) => unknown);\n value?: unknown;\n };\n format?: Format;\n fields?: string[];\n}\n\n/**\n * Extended step example that carries destination-level settings for the\n * file destination.\n *\n * `out` is modeled at intent level as a single `['fs.writeFile', path, line]`\n * tuple per event (even though the destination internally uses a persistent\n * createWriteStream + write). This matches the design doc's preference for\n * readable intent-level callable tuples over stream-chain fidelity.\n *\n * Dropped / ignored events produce `out: []`.\n */\nexport type FileStepExample = Flow.StepExample & {\n settings: FileSettingsJson;\n};\n\n/** Default JSONL append. Static filename, all defaults. */\nexport const jsonlDefault: FileStepExample = {\n in: getEvent('page view', { timestamp: 1700000000000 }),\n settings: { filename: 'events.jsonl' },\n out: [\n [\n 'fs.writeFile',\n 'events.jsonl',\n // JSONL framework contract: JSON.stringify(event) + '\\n'.\n // The test recomputes this from example.in for the jsonl default to\n // avoid duplicating the full event shape here.\n 'jsonl:event',\n ],\n ],\n};\n\n/** Baersch-style TSV log: PHP parity case. */\nexport const tsvBaerschLog: FileStepExample = {\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Docs' },\n user: { session: 'sess-1' },\n source: {\n id: 'https://example.com/docs',\n type: 'server',\n previous_id: 'https://example.com/',\n },\n }),\n settings: {\n filename: 'storage/mblog.txt',\n format: 'tsv',\n fields: [\n 'timestamp',\n 'user.session',\n 'name',\n 'source.id',\n 'data.title',\n 'source.previous_id',\n ],\n },\n out: [\n [\n 'fs.writeFile',\n 'storage/mblog.txt',\n '1700000000000\\tsess-1\\tpage view\\thttps://example.com/docs\\tDocs\\thttps://example.com/\\n',\n ],\n ],\n};\n\n/** Tenant sharding via plain key extraction. */\nexport const jsonlTenantShardKey: FileStepExample = {\n in: getEvent('custom event', {\n timestamp: 1700000000000,\n data: { tenant: 'acme' },\n }),\n settings: {\n filename: { key: 'data.tenant' },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'acme', 'jsonl:event']],\n};\n\n/**\n * Daily rotation via a mapping fn. In flow.json this is authored as a\n * `$code:` string; walkerOS compiles it to a function at bundle time. For\n * in-process tests we pass the already-compiled function directly so the\n * example exercises the same code path without needing the bundler.\n */\nexport const jsonlDailyRotation: FileStepExample = {\n in: getEvent('order complete', {\n timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),\n data: { id: 'ORD-1' },\n }),\n settings: {\n filename: {\n fn: (value) => {\n const event = value as { timestamp?: number };\n const ts = event.timestamp ?? 0;\n return `events-${new Date(ts).toISOString().slice(0, 10)}.jsonl`;\n },\n },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'events-2026-04-15.jsonl', 'jsonl:event']],\n};\n\n/** CSV with an object cell. data is JSON-stringified, properly quoted. */\nexport const csvObjectCell: FileStepExample = {\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Hello, \"World\"', count: 3 },\n }),\n settings: {\n filename: 'events.csv',\n format: 'csv',\n fields: ['timestamp', 'name', 'data'],\n },\n out: [\n [\n 'fs.writeFile',\n 'events.csv',\n '1700000000000,page view,\"{\"\"title\"\":\"\"Hello, \\\\\"\"World\\\\\"\"\"\",\"\"count\"\":3}\"\\n',\n ],\n ],\n};\n"],"mappings":"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","names":["z"]}
1
+ {"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/schemas/mapping.ts","../src/examples/index.ts","../src/examples/env.ts","../src/examples/step.ts"],"sourcesContent":["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 filename: z\n .union([\n z.string().describe('Static output filename.'),\n z\n .record(z.string(), z.unknown())\n .describe(\n 'Mapping.Value resolved per event (e.g. { key: \"data.tenant\" } or { fn: \"$code:...\" }).',\n ),\n ])\n .describe(\n 'Output filename. Static string or Mapping.Value (e.g. { fn: \"$code:...\" } for daily rotation, { key: \"data.tenant\" } for sharding).',\n ),\n format: z\n .enum(['jsonl', 'tsv', 'csv'])\n .optional()\n .describe('Serialisation format. Defaults to jsonl.'),\n fields: z\n .array(z.string())\n .optional()\n .describe(\n 'Event paths used as columns for tsv/csv formats. Object values are JSON-stringified. Required when format is tsv or csv.',\n ),\n});\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","import { z } from '@walkeros/core/dev';\n\nexport const MappingSchema = z\n .object({})\n .describe('No per-rule overrides for the file destination.');\n\nexport type Mapping = z.infer<typeof MappingSchema>;\n","export * as env from './env';\nexport * as step from './step';\n","import type { Env, FileWriteStream } from '../types';\n\n/**\n * Captured file state for assertions in tests.\n */\nexport interface CapturedFile {\n filename: string;\n lines: string[];\n ended: boolean;\n}\n\n// Narrow helper type aliases so the mock fs is typed explicitly without `any`.\ntype CreateWriteStreamFn = (\n path: string,\n options: { flags: string },\n) => FileWriteStream;\ntype MkdirFn = (path: string, options: { recursive: boolean }) => Promise<void>;\n\nexport interface SpyState {\n captured: Map<string, CapturedFile>;\n mkdirCalls: string[];\n}\n\nexport interface SpyEnv extends Env {\n _spy: SpyState;\n}\n\nfunction makeSpyEnv(): SpyEnv {\n const state: SpyState = {\n captured: new Map(),\n mkdirCalls: [],\n };\n\n const createWriteStream: CreateWriteStreamFn = (path) => {\n const existing = state.captured.get(path);\n const file: CapturedFile = existing ?? {\n filename: path,\n lines: [],\n ended: false,\n };\n if (!existing) state.captured.set(path, file);\n const stream: FileWriteStream = {\n write(chunk) {\n file.lines.push(chunk);\n return true;\n },\n end() {\n file.ended = true;\n },\n };\n return stream;\n };\n\n const mkdir: MkdirFn = async (path) => {\n state.mkdirCalls.push(path);\n };\n\n return {\n _spy: state,\n fs: {\n createWriteStream,\n mkdir,\n },\n };\n}\n\nexport const init: SpyEnv = makeSpyEnv();\nexport const push: SpyEnv = makeSpyEnv();\n","import type { Flow } from '@walkeros/core';\nimport { getEvent } from '@walkeros/core';\nimport type { Format } from '../types';\n\n/**\n * Raw filename-config shape accepted in step examples and flow.json.\n * Mirrors the runtime Settings.filename but types `fn` as string so\n * `$code:` tags (resolved at bundle time by walkerOS) are expressible\n * here without casting to a function type.\n */\nexport interface FileSettingsJson {\n filename:\n | string\n | {\n key?: string;\n fn?: string | ((value: unknown) => unknown);\n value?: unknown;\n };\n format?: Format;\n fields?: string[];\n}\n\n/**\n * Extended step example that carries destination-level settings for the\n * file destination.\n *\n * `out` is modeled at intent level as a single `['fs.writeFile', path, line]`\n * tuple per event (even though the destination internally uses a persistent\n * createWriteStream + write). This matches the design doc's preference for\n * readable intent-level callable tuples over stream-chain fidelity.\n *\n * Dropped / ignored events produce `out: []`.\n */\nexport type FileStepExample = Flow.StepExample & {\n settings: FileSettingsJson;\n};\n\n/** Default JSONL append. Static filename, all defaults. */\nexport const jsonlDefault: FileStepExample = {\n title: 'JSONL append',\n description:\n 'An event is appended as a single JSON line to a static filename using default JSONL formatting.',\n in: getEvent('page view', { timestamp: 1700000000000 }),\n settings: { filename: 'events.jsonl' },\n out: [\n [\n 'fs.writeFile',\n 'events.jsonl',\n // JSONL framework contract: JSON.stringify(event) + '\\n'.\n // The test recomputes this from example.in for the jsonl default to\n // avoid duplicating the full event shape here.\n 'jsonl:event',\n ],\n ],\n};\n\n/** Baersch-style TSV log: PHP parity case. */\nexport const tsvBaerschLog: FileStepExample = {\n title: 'TSV log',\n description:\n 'An event is written as a tab-separated line selecting specific fields for a compact access-log style file.',\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Docs' },\n user: { session: 'sess-1' },\n source: {\n id: 'https://example.com/docs',\n type: 'server',\n previous_id: 'https://example.com/',\n },\n }),\n settings: {\n filename: 'storage/mblog.txt',\n format: 'tsv',\n fields: [\n 'timestamp',\n 'user.session',\n 'name',\n 'source.id',\n 'data.title',\n 'source.previous_id',\n ],\n },\n out: [\n [\n 'fs.writeFile',\n 'storage/mblog.txt',\n '1700000000000\\tsess-1\\tpage view\\thttps://example.com/docs\\tDocs\\thttps://example.com/\\n',\n ],\n ],\n};\n\n/** Tenant sharding via plain key extraction. */\nexport const jsonlTenantShardKey: FileStepExample = {\n title: 'Tenant sharding',\n description:\n 'The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.',\n in: getEvent('custom event', {\n timestamp: 1700000000000,\n data: { tenant: 'acme' },\n }),\n settings: {\n filename: { key: 'data.tenant' },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'acme', 'jsonl:event']],\n};\n\n/**\n * Daily rotation via a mapping fn. In flow.json this is authored as a\n * `$code:` string; walkerOS compiles it to a function at bundle time. For\n * in-process tests we pass the already-compiled function directly so the\n * example exercises the same code path without needing the bundler.\n */\nexport const jsonlDailyRotation: FileStepExample = {\n title: 'Daily rotation',\n description:\n 'A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.',\n in: getEvent('order complete', {\n timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),\n data: { id: 'ORD-1' },\n }),\n settings: {\n filename: {\n fn: (value) => {\n const event = value as { timestamp?: number };\n const ts = event.timestamp ?? 0;\n return `events-${new Date(ts).toISOString().slice(0, 10)}.jsonl`;\n },\n },\n format: 'jsonl',\n },\n out: [['fs.writeFile', 'events-2026-04-15.jsonl', 'jsonl:event']],\n};\n\n/** CSV with an object cell. data is JSON-stringified, properly quoted. */\nexport const csvObjectCell: FileStepExample = {\n title: 'CSV with object cell',\n description:\n 'An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.',\n in: getEvent('page view', {\n timestamp: 1700000000000,\n data: { title: 'Hello, \"World\"', count: 3 },\n }),\n settings: {\n filename: 'events.csv',\n format: 'csv',\n fields: ['timestamp', 'name', 'data'],\n },\n out: [\n [\n 'fs.writeFile',\n 'events.csv',\n '1700000000000,page view,\"{\"\"title\"\":\"\"Hello, \\\\\"\"World\\\\\"\"\"\",\"\"count\"\":3}\"\\n',\n ],\n ],\n};\n"],"mappings":"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","names":["z"]}
@@ -80,6 +80,8 @@ __export(step_exports, {
80
80
  });
81
81
  var import_core = require("@walkeros/core");
82
82
  var jsonlDefault = {
83
+ title: "JSONL append",
84
+ description: "An event is appended as a single JSON line to a static filename using default JSONL formatting.",
83
85
  in: (0, import_core.getEvent)("page view", { timestamp: 17e11 }),
84
86
  settings: { filename: "events.jsonl" },
85
87
  out: [
@@ -94,6 +96,8 @@ var jsonlDefault = {
94
96
  ]
95
97
  };
96
98
  var tsvBaerschLog = {
99
+ title: "TSV log",
100
+ description: "An event is written as a tab-separated line selecting specific fields for a compact access-log style file.",
97
101
  in: (0, import_core.getEvent)("page view", {
98
102
  timestamp: 17e11,
99
103
  data: { title: "Docs" },
@@ -125,6 +129,8 @@ var tsvBaerschLog = {
125
129
  ]
126
130
  };
127
131
  var jsonlTenantShardKey = {
132
+ title: "Tenant sharding",
133
+ description: "The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.",
128
134
  in: (0, import_core.getEvent)("custom event", {
129
135
  timestamp: 17e11,
130
136
  data: { tenant: "acme" }
@@ -136,6 +142,8 @@ var jsonlTenantShardKey = {
136
142
  out: [["fs.writeFile", "acme", "jsonl:event"]]
137
143
  };
138
144
  var jsonlDailyRotation = {
145
+ title: "Daily rotation",
146
+ description: "A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.",
139
147
  in: (0, import_core.getEvent)("order complete", {
140
148
  timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),
141
149
  data: { id: "ORD-1" }
@@ -154,6 +162,8 @@ var jsonlDailyRotation = {
154
162
  out: [["fs.writeFile", "events-2026-04-15.jsonl", "jsonl:event"]]
155
163
  };
156
164
  var csvObjectCell = {
165
+ title: "CSV with object cell",
166
+ description: "An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.",
157
167
  in: (0, import_core.getEvent)("page view", {
158
168
  timestamp: 17e11,
159
169
  data: { title: 'Hello, "World"', count: 3 }
@@ -59,6 +59,8 @@ __export(step_exports, {
59
59
  });
60
60
  import { getEvent } from "@walkeros/core";
61
61
  var jsonlDefault = {
62
+ title: "JSONL append",
63
+ description: "An event is appended as a single JSON line to a static filename using default JSONL formatting.",
62
64
  in: getEvent("page view", { timestamp: 17e11 }),
63
65
  settings: { filename: "events.jsonl" },
64
66
  out: [
@@ -73,6 +75,8 @@ var jsonlDefault = {
73
75
  ]
74
76
  };
75
77
  var tsvBaerschLog = {
78
+ title: "TSV log",
79
+ description: "An event is written as a tab-separated line selecting specific fields for a compact access-log style file.",
76
80
  in: getEvent("page view", {
77
81
  timestamp: 17e11,
78
82
  data: { title: "Docs" },
@@ -104,6 +108,8 @@ var tsvBaerschLog = {
104
108
  ]
105
109
  };
106
110
  var jsonlTenantShardKey = {
111
+ title: "Tenant sharding",
112
+ description: "The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.",
107
113
  in: getEvent("custom event", {
108
114
  timestamp: 17e11,
109
115
  data: { tenant: "acme" }
@@ -115,6 +121,8 @@ var jsonlTenantShardKey = {
115
121
  out: [["fs.writeFile", "acme", "jsonl:event"]]
116
122
  };
117
123
  var jsonlDailyRotation = {
124
+ title: "Daily rotation",
125
+ description: "A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.",
118
126
  in: getEvent("order complete", {
119
127
  timestamp: Date.UTC(2026, 3, 15, 12, 34, 56),
120
128
  data: { id: "ORD-1" }
@@ -133,6 +141,8 @@ var jsonlDailyRotation = {
133
141
  out: [["fs.writeFile", "events-2026-04-15.jsonl", "jsonl:event"]]
134
142
  };
135
143
  var csvObjectCell = {
144
+ title: "CSV with object cell",
145
+ description: "An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.",
136
146
  in: getEvent("page view", {
137
147
  timestamp: 17e11,
138
148
  data: { title: 'Hello, "World"', count: 3 }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$meta": {
3
3
  "package": "@walkeros/server-destination-file",
4
- "version": "3.4.0",
4
+ "version": "3.4.1",
5
5
  "type": "destination",
6
6
  "platform": [
7
7
  "server"
@@ -70,7 +70,7 @@
70
70
  },
71
71
  "fs": {
72
72
  "createWriteStream": {
73
- "$code": "t=>{const s=e.captured.get(t),a=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,a);return{write:e=>(a.lines.push(e),!0),end(){a.ended=!0}}}"
73
+ "$code": "t=>{const s=e.captured.get(t),i=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,i);return{write:e=>(i.lines.push(e),!0),end(){i.ended=!0}}}"
74
74
  },
75
75
  "mkdir": {
76
76
  "$code": "async t=>{e.mkdirCalls.push(t)}"
@@ -84,7 +84,7 @@
84
84
  },
85
85
  "fs": {
86
86
  "createWriteStream": {
87
- "$code": "t=>{const s=e.captured.get(t),a=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,a);return{write:e=>(a.lines.push(e),!0),end(){a.ended=!0}}}"
87
+ "$code": "t=>{const s=e.captured.get(t),i=null!=s?s:{filename:t,lines:[],ended:!1};s||e.captured.set(t,i);return{write:e=>(i.lines.push(e),!0),end(){i.ended=!0}}}"
88
88
  },
89
89
  "mkdir": {
90
90
  "$code": "async t=>{e.mkdirCalls.push(t)}"
@@ -94,6 +94,8 @@
94
94
  },
95
95
  "step": {
96
96
  "csvObjectCell": {
97
+ "title": "CSV with object cell",
98
+ "description": "An event is written as a CSV row with the data object JSON-stringified and properly quoted for embedded commas and quotes.",
97
99
  "in": {
98
100
  "name": "page view",
99
101
  "data": {
@@ -144,7 +146,7 @@
144
146
  "group": "gr0up",
145
147
  "count": 1,
146
148
  "version": {
147
- "source": "3.4.0",
149
+ "source": "3.4.1",
148
150
  "tagging": 1
149
151
  },
150
152
  "source": {
@@ -171,6 +173,8 @@
171
173
  ]
172
174
  },
173
175
  "jsonlDailyRotation": {
176
+ "title": "Daily rotation",
177
+ "description": "A mapping function derives a date-stamped filename from the event timestamp to rotate JSONL files daily.",
174
178
  "in": {
175
179
  "name": "order complete",
176
180
  "data": {
@@ -253,7 +257,7 @@
253
257
  "group": "gr0up",
254
258
  "count": 1,
255
259
  "version": {
256
- "source": "3.4.0",
260
+ "source": "3.4.1",
257
261
  "tagging": 1
258
262
  },
259
263
  "source": {
@@ -279,6 +283,8 @@
279
283
  ]
280
284
  },
281
285
  "jsonlDefault": {
286
+ "title": "JSONL append",
287
+ "description": "An event is appended as a single JSON line to a static filename using default JSONL formatting.",
282
288
  "in": {
283
289
  "name": "page view",
284
290
  "data": {
@@ -333,7 +339,7 @@
333
339
  "group": "gr0up",
334
340
  "count": 1,
335
341
  "version": {
336
- "source": "3.4.0",
342
+ "source": "3.4.1",
337
343
  "tagging": 1
338
344
  },
339
345
  "source": {
@@ -354,6 +360,8 @@
354
360
  ]
355
361
  },
356
362
  "jsonlTenantShardKey": {
363
+ "title": "Tenant sharding",
364
+ "description": "The filename is resolved from an event field so events are partitioned into per-tenant JSONL files.",
357
365
  "in": {
358
366
  "name": "custom event",
359
367
  "data": {
@@ -403,7 +411,7 @@
403
411
  "group": "gr0up",
404
412
  "count": 1,
405
413
  "version": {
406
- "source": "3.4.0",
414
+ "source": "3.4.1",
407
415
  "tagging": 1
408
416
  },
409
417
  "source": {
@@ -427,6 +435,8 @@
427
435
  ]
428
436
  },
429
437
  "tsvBaerschLog": {
438
+ "title": "TSV log",
439
+ "description": "An event is written as a tab-separated line selecting specific fields for a compact access-log style file.",
430
440
  "in": {
431
441
  "name": "page view",
432
442
  "data": {
@@ -474,7 +484,7 @@
474
484
  "group": "gr0up",
475
485
  "count": 1,
476
486
  "version": {
477
- "source": "3.4.0",
487
+ "source": "3.4.1",
478
488
  "tagging": 1
479
489
  },
480
490
  "source": {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@walkeros/server-destination-file",
3
3
  "description": "Local file sink for walkerOS server flows (JSONL, TSV, CSV)",
4
- "version": "3.4.0",
4
+ "version": "3.4.1",
5
5
  "license": "MIT",
6
6
  "exports": {
7
7
  ".": {
@@ -34,11 +34,11 @@
34
34
  "update": "npx npm-check-updates -u && npm update"
35
35
  },
36
36
  "dependencies": {
37
- "@walkeros/core": "3.4.0",
38
- "@walkeros/server-core": "3.4.0"
37
+ "@walkeros/core": "3.4.1",
38
+ "@walkeros/server-core": "3.4.1"
39
39
  },
40
40
  "devDependencies": {
41
- "@walkeros/collector": "3.4.0"
41
+ "@walkeros/collector": "3.4.1"
42
42
  },
43
43
  "repository": {
44
44
  "url": "git+https://github.com/elbwalker/walkerOS.git",