Skip to main content
Ask your AI

File

Server Source code Package

Serves static files from a store backend. Reads the file by ingest.path, derives the Content-Type from the file extension, and responds directly. Returns false to stop the transformer chain so no further transformers or destinations run for the request.

Installation​

npm install @walkeros/server-transformer-file
import { startFlow } from '@walkeros/collector';
import { transformerFile } from '@walkeros/server-transformer-file';
import { storeFsInit } from '@walkeros/server-store-fs';

// Reference this same object in stores and in env: the collector swaps it
// for the initialized store instance at startup.
const files = {
  code: storeFsInit,
  config: { settings: { basePath: './public' }, file: true },
};

await startFlow({
  stores: { files },
  transformers: {
    file: {
      code: transformerFile,
      config: {
        settings: { prefix: '/static' },
      },
      env: { store: files },
    },
  },
});

The '$store.files' string only works in a bundled flow.json, where the CLI resolves it. In startFlow it stays a string and the transformer fails.

Configuration​

This transformer uses the standard transformer config wrapper (consent, data, env, id, ...). For the shared fields see transformer configuration. Package-specific fields live under config.settings and are listed below.

Settings​

PropertyTypeDescriptionMore
prefixstringURL prefix to strip before store lookup. E.g., "/static" → /static/walker.js looks up "walker.js"
headersRecord<string, string>Default response headers (e.g., Cache-Control, X-Frame-Options)
mimeTypesRecord<string, string>Extension → Content-Type overrides. Keys include dot: { ".wasm": "application/wasm" }

Mapping​

This package does not define custom rule-level settings. For the standard rule fields (consent, condition, data, batch, name, policy) see mapping.

Examples

Serve static file

Serve a static JavaScript file from store. Config: prefix: "/static", headers: { "Cache-Control": "public, max-age=3600" }

Event
{
  "name": "page view",
  "data": {
    "path": "/static/walker.js"
  },
  "id": "ev-1700000600",
  "trigger": "load",
  "entity": "page",
  "action": "view",
  "timestamp": 1700000600,
  "source": {
    "type": "express",
    "platform": "server"
  }
}
Out
respond({
  "status": 200,
  "headers": {
    "Content-Type": "application/javascript",
    "Cache-Control": "public, max-age=3600"
  }
})

How it works​

  1. Reads ingest.path from the request context
  2. Strips the configured prefix (if set), e.g. /static/image.png becomes image.png
  3. Looks up the remaining path in the store via store.get(key)
  4. If found, derives the Content-Type from the file extension and responds with the content
  5. Returns false to stop the chain. No further transformers or destinations run.
  6. If the file is not found or the path doesn't match the prefix, the event passes through unchanged

Environment​

KeyTypeRequiredDescription
storeStore.InstanceYesStore providing file content. Without one, the transformer warns and passes through.

Cache and file chain​

Put a cache on the source to answer repeated file requests from memory, without reading the store again. A cache on the file transformer itself never stores an entry, because the transformer stops the chain once it responds:

"sources": {
  "http": {
    "package": "@walkeros/server-source-express",
    "config": {
      "settings": { "paths": ["/collect", "/static/*path"] },
      "ingest": {
        "map": {
          "method": { "key": "method" },
          "path": { "key": "path" }
        }
      }
    },
    "cache": {
      "rules": [
        {
          "match": {
            "and": [
              { "key": "ingest.method", "operator": "eq", "value": "GET" },
              { "key": "ingest.path", "operator": "prefix", "value": "/static" }
            ]
          },
          "key": ["ingest.method", "ingest.path"],
          "ttl": 300
        }
      ]
    },
    "next": [
      {
        "match": { "key": "ingest.method", "operator": "eq", "value": "GET" },
        "next": "file"
      }
    ]
  }
},
"transformers": {
  "file": {
    "package": "@walkeros/server-transformer-file",
    "config": { "settings": { "prefix": "/static" } },
    "env": { "store": "$store.files" }
  }
}

Custom MIME types​

{
  settings: {
    mimeTypes: {
      '.wasm': 'application/wasm',
      '.mjs': 'application/javascript',
    },
  },
}

Behavior notes​

  • Requires a store: without env.store, every request logs a warning and passes through
  • Prefix matching: if prefix is set and the path doesn't start with it, the event passes through (not an error)
  • Returns false: a served file stops the chain; no destinations receive the event
  • Content-Length: automatically set for string and Buffer content

In the complete example​

The server flow of flow-complete.json, the tested example flow, serves the web bundle walker.js first party from an fs store. The step stops after serving, so a script request never becomes an event:

/flows/server/transformers/file
{
  "package": "@walkeros/server-transformer-file",
  "env": {
    "store": "$store.assets"
  },
  "config": {
    "settings": {
      "headers": {
        "Cache-Control": "public, max-age=300",
        "Cross-Origin-Resource-Policy": "same-site"
      }
    }
  },
  "next": {
    "stop": true
  },
  "examples": { … }
}
walker.js is served first party from the server flow. Guide chapter state-stores
/flows/server/transformers/file/config/settings/headers
{
  "Cache-Control": "public, max-age=300",
  "Cross-Origin-Resource-Policy": "same-site"
}
Default response headers for served files: caching and resource policy. Guide chapter state-stores

GET /walker.js is answered from the assets store with the configured headers; the step returns false and its next stops, so a script request never becomes an event. Proven over HTTP in the flow test.

Event
{
  "name": "page view",
  "entity": "page",
  "action": "view",
  "data": {
    "domain": "www.example.com",
    "title": "Trail Runner",
    "id": "/product/trail-runner"
  },
  "id": "ev-page-view",
  "trigger": "load",
  "timestamp": 1700000000000,
  "consent": {
    "functional": true,
    "marketing": true
  },
  "globals": {
    "language": "en",
    "pageGroup": "product"
  },
  "user": {
    "device": "d3v1c3",
    "session": "s3ss10n"
  },
  "source": {
    "type": "express",
    "platform": "server"
  }
}
Out
// no output
Serve walker.js first party: example walkerJs of step file. Guide chapter state-stores

Next steps​

  • Cache - Add response caching before file serving (integrated collector mode)
  • Stores - Configure store backends
  • Runtime: serving files - Bake files into the flow image
💡 Need implementation support?
elbwalker offers hands-on support: setup review, measurement planning, destination mapping, and live troubleshooting. Book a 2-hour session (€399)