@walkeros/server-transformer-fingerprint 3.0.1 → 4.0.0-next-1773967844643
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dev.d.mts +4 -2
- package/dist/dev.d.ts +4 -2
- 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/walkerOS.json +20 -2
- package/package.json +8 -6
package/dist/dev.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
2
|
import { z } from '@walkeros/core/dev';
|
|
3
|
-
import { Flow } from '@walkeros/core';
|
|
3
|
+
import { Flow, Hint } from '@walkeros/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Fingerprint transformer settings schema.
|
|
@@ -43,4 +43,6 @@ declare namespace index {
|
|
|
43
43
|
export { index_step as step };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
declare const hints: Hint.Hints;
|
|
47
|
+
|
|
48
|
+
export { index as examples, hints, index$1 as schemas };
|
package/dist/dev.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
2
|
import { z } from '@walkeros/core/dev';
|
|
3
|
-
import { Flow } from '@walkeros/core';
|
|
3
|
+
import { Flow, Hint } from '@walkeros/core';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Fingerprint transformer settings schema.
|
|
@@ -43,4 +43,6 @@ declare namespace index {
|
|
|
43
43
|
export { index_step as step };
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
declare const hints: Hint.Hints;
|
|
47
|
+
|
|
48
|
+
export { index as examples, hints, index$1 as schemas };
|
package/dist/dev.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,n=(e,i)=>{for(var r in i)t(e,r,{get:i[r],enumerable:!0})},a={};n(a,{examples:()=>c,hints:()=>f,schemas:()=>o}),module.exports=(e=a,((e,n,a,o)=>{if(n&&"object"==typeof n||"function"==typeof n)for(let g of r(n))s.call(e,g)||g===a||t(e,g,{get:()=>n[g],enumerable:!(o=i(n,g))||o.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o={};n(o,{SettingsSchema:()=>d,settings:()=>u});var g=require("@walkeros/core/dev"),p=require("@walkeros/core/dev"),d=p.z.object({fields:p.z.array(p.z.union([p.z.string().describe('Dot-notation path: "ingest.ip", "event.data.userId"'),p.z.object({key:p.z.string().optional().describe("Source property path"),value:p.z.unknown().optional().describe("Static value or fallback"),fn:p.z.string().optional().describe("$code: function for value transformation")}).describe("Mapping value config for computed fields")])).describe("Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }."),output:p.z.string().optional().describe('Dot-notation path where hash is stored on the event. Default: "user.hash"'),length:p.z.number().int().positive().optional().describe("Truncate hash to this length. Default: full 64-char SHA-256 hash")}).describe("Fingerprint transformer: generates deterministic user hashes from event fields"),u=(0,g.zodToSchema)(d),c={};n(c,{step:()=>l});var l={};n(l,{ipAnonymization:()=>h,missingFields:()=>m,serverFingerprint:()=>v});var v={description:"Standard server fingerprint using ingest.ip and ingest.userAgent. Requires source config.ingest.",in:{name:"page view",data:{domain:"www.example.com",title:"Getting Started",id:"/docs/getting-started"},id:"1700000600-gr0up-1",trigger:"load",entity:"page",action:"view",timestamp:1700000600,group:"gr0up",count:1,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"page view",data:{domain:"www.example.com",title:"Getting Started",id:"/docs/getting-started"},user:{hash:"158f99cc06e33fd6"},id:"1700000600-gr0up-1",trigger:"load",entity:"page",action:"view",timestamp:1700000600,group:"gr0up",count:1,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},m={description:"Graceful handling when ingest is missing — fields resolve to empty strings, hash is still generated.",in:{name:"session start",data:{id:"s3ss10n"},id:"1700000601-gr0up-2",trigger:"load",entity:"session",action:"start",timestamp:1700000601,group:"gr0up",count:2,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"session start",data:{id:"s3ss10n"},user:{hash:"e183220b699c10a8"},id:"1700000601-gr0up-2",trigger:"load",entity:"session",action:"start",timestamp:1700000601,group:"gr0up",count:2,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},h={description:'Privacy-preserving fingerprint using key+fn pattern: fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. Config: fields: [{ key: "ingest.ip", fn: ip => ip.replace(/\\.\\d+$/, ".0") }, "ingest.userAgent"]',in:{name:"page view",data:{domain:"www.example.com",title:"Privacy Policy",id:"/privacy"},id:"1700000602-gr0up-3",trigger:"load",entity:"page",action:"view",timestamp:1700000602,group:"gr0up",count:3,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"page view",data:{domain:"www.example.com",title:"Privacy Policy",id:"/privacy"},user:{hash:"44d9154b9a9b3792"},id:"1700000602-gr0up-3",trigger:"load",entity:"page",action:"view",timestamp:1700000602,group:"gr0up",count:3,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},f={"ingest-prerequisite":{text:"Fields starting with ingest.* require the server source to have config.ingest configured. Without it, ingest is undefined and all ingest.* fields resolve to empty strings — the hash is still generated but not unique. Always pair this transformer with a source that extracts request metadata.",code:[{lang:"json",code:JSON.stringify({sources:{express:{package:"@walkeros/server-source-express",config:{settings:{port:8080},ingest:{ip:"req.ip",userAgent:"req.headers.user-agent",origin:"req.headers.origin"}}}},transformers:{fingerprint:{package:"@walkeros/server-transformer-fingerprint",config:{settings:{fields:["ingest.ip","ingest.userAgent"],output:"user.hash",length:16}}}}},null,2)}]},"fields-overview":{text:"Fields resolve from { event, ingest } via walkerOS mapping. Common patterns: ingest.ip (client IP), ingest.userAgent (browser UA), event.data.* (any event property). For time-based rotation use fn fields: daily rotation with toISOString().slice(0,10), monthly with getDate(). Order matters — same fields in different order produce different hashes. Use { key, fn } objects to transform before hashing (e.g., IP anonymization via the ipAnonymization step example)."}};//# 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/examples/index.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';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Fingerprint transformer settings schema.\n *\n * Mirrors: types.ts FingerprintSettings\n */\nexport const SettingsSchema = z\n .object({\n fields: z\n .array(\n z.union([\n z\n .string()\n .describe('Dot-notation path: \"ingest.ip\", \"event.data.userId\"'),\n z\n .object({\n key: z.string().optional().describe('Source property path'),\n value: z\n .unknown()\n .optional()\n .describe('Static value or fallback'),\n fn: z\n .string()\n .optional()\n .describe('$code: function for value transformation'),\n })\n .describe('Mapping value config for computed fields'),\n ]),\n )\n .describe(\n 'Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }.',\n ),\n output: z\n .string()\n .optional()\n .describe(\n 'Dot-notation path where hash is stored on the event. Default: \"user.hash\"',\n ),\n length: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Truncate hash to this length. Default: full 64-char SHA-256 hash',\n ),\n })\n .describe(\n 'Fingerprint transformer: generates deterministic user hashes from event fields',\n );\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\nexport const serverFingerprint: Flow.StepExample = {\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n user: { hash: '158f99cc06e33fd6' },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const missingFields: Flow.StepExample = {\n in: {\n name: 'session start',\n data: { id: 's3ss10n' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'session start',\n data: { id: 's3ss10n' },\n user: { hash: 'e183220b699c10a8' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const ipAnonymization: Flow.StepExample = {\n description:\n 'Privacy-preserving fingerprint using key+fn pattern: ' +\n 'fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. ' +\n 'Config: fields: [{ key: \"ingest.ip\", fn: ip => ip.replace(/\\\\.\\\\d+$/, \".0\") }, \"ingest.userAgent\"]',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n user: { hash: '44d9154b9a9b3792' },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n"],"mappings":"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","names":["import_dev"]}
|
|
1
|
+
{"version":3,"sources":["../src/dev.ts","../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/hints.ts"],"sourcesContent":["export * as schemas from './schemas';\nexport * as examples from './examples';\nexport { hints } from './hints';\n","import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Fingerprint transformer settings schema.\n *\n * Mirrors: types.ts FingerprintSettings\n */\nexport const SettingsSchema = z\n .object({\n fields: z\n .array(\n z.union([\n z\n .string()\n .describe('Dot-notation path: \"ingest.ip\", \"event.data.userId\"'),\n z\n .object({\n key: z.string().optional().describe('Source property path'),\n value: z\n .unknown()\n .optional()\n .describe('Static value or fallback'),\n fn: z\n .string()\n .optional()\n .describe('$code: function for value transformation'),\n })\n .describe('Mapping value config for computed fields'),\n ]),\n )\n .describe(\n 'Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }.',\n ),\n output: z\n .string()\n .optional()\n .describe(\n 'Dot-notation path where hash is stored on the event. Default: \"user.hash\"',\n ),\n length: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Truncate hash to this length. Default: full 64-char SHA-256 hash',\n ),\n })\n .describe(\n 'Fingerprint transformer: generates deterministic user hashes from event fields',\n );\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\nexport const serverFingerprint: Flow.StepExample = {\n description:\n 'Standard server fingerprint using ingest.ip and ingest.userAgent. Requires source config.ingest.',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n user: { hash: '158f99cc06e33fd6' },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const missingFields: Flow.StepExample = {\n description:\n 'Graceful handling when ingest is missing — fields resolve to empty strings, hash is still generated.',\n in: {\n name: 'session start',\n data: { id: 's3ss10n' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'session start',\n data: { id: 's3ss10n' },\n user: { hash: 'e183220b699c10a8' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const ipAnonymization: Flow.StepExample = {\n description:\n 'Privacy-preserving fingerprint using key+fn pattern: ' +\n 'fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. ' +\n 'Config: fields: [{ key: \"ingest.ip\", fn: ip => ip.replace(/\\\\.\\\\d+$/, \".0\") }, \"ingest.userAgent\"]',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n user: { hash: '44d9154b9a9b3792' },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'ingest-prerequisite': {\n text: 'Fields starting with ingest.* require the server source to have config.ingest configured. Without it, ingest is undefined and all ingest.* fields resolve to empty strings — the hash is still generated but not unique. Always pair this transformer with a source that extracts request metadata.',\n code: [\n {\n lang: 'json',\n code: JSON.stringify(\n {\n sources: {\n express: {\n package: '@walkeros/server-source-express',\n config: {\n settings: { port: 8080 },\n ingest: {\n ip: 'req.ip',\n userAgent: 'req.headers.user-agent',\n origin: 'req.headers.origin',\n },\n },\n },\n },\n transformers: {\n fingerprint: {\n package: '@walkeros/server-transformer-fingerprint',\n config: {\n settings: {\n fields: ['ingest.ip', 'ingest.userAgent'],\n output: 'user.hash',\n length: 16,\n },\n },\n },\n },\n },\n null,\n 2,\n ),\n },\n ],\n },\n 'fields-overview': {\n text: 'Fields resolve from { event, ingest } via walkerOS mapping. Common patterns: ingest.ip (client IP), ingest.userAgent (browser UA), event.data.* (any event property). For time-based rotation use fn fields: daily rotation with toISOString().slice(0,10), monthly with getDate(). Order matters — same fields in different order produce different hashes. Use { key, fn } objects to transform before hashing (e.g., IP anonymization via the ipAnonymization step example).',\n },\n};\n"],"mappings":"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","names":["import_dev"]}
|
package/dist/dev.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var e=Object.defineProperty,t=(t,i)=>{for(var r in i)e(t,r,{get:i[r],enumerable:!0})},i={};t(i,{SettingsSchema:()=>
|
|
1
|
+
var e=Object.defineProperty,t=(t,i)=>{for(var r in i)e(t,r,{get:i[r],enumerable:!0})},i={};t(i,{SettingsSchema:()=>n,settings:()=>a});import{zodToSchema as r}from"@walkeros/core/dev";import{z as s}from"@walkeros/core/dev";var n=s.object({fields:s.array(s.union([s.string().describe('Dot-notation path: "ingest.ip", "event.data.userId"'),s.object({key:s.string().optional().describe("Source property path"),value:s.unknown().optional().describe("Static value or fallback"),fn:s.string().optional().describe("$code: function for value transformation")}).describe("Mapping value config for computed fields")])).describe("Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }."),output:s.string().optional().describe('Dot-notation path where hash is stored on the event. Default: "user.hash"'),length:s.number().int().positive().optional().describe("Truncate hash to this length. Default: full 64-char SHA-256 hash")}).describe("Fingerprint transformer: generates deterministic user hashes from event fields"),a=r(n),o={};t(o,{step:()=>g});var g={};t(g,{ipAnonymization:()=>u,missingFields:()=>d,serverFingerprint:()=>p});var p={description:"Standard server fingerprint using ingest.ip and ingest.userAgent. Requires source config.ingest.",in:{name:"page view",data:{domain:"www.example.com",title:"Getting Started",id:"/docs/getting-started"},id:"1700000600-gr0up-1",trigger:"load",entity:"page",action:"view",timestamp:1700000600,group:"gr0up",count:1,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"page view",data:{domain:"www.example.com",title:"Getting Started",id:"/docs/getting-started"},user:{hash:"158f99cc06e33fd6"},id:"1700000600-gr0up-1",trigger:"load",entity:"page",action:"view",timestamp:1700000600,group:"gr0up",count:1,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},d={description:"Graceful handling when ingest is missing — fields resolve to empty strings, hash is still generated.",in:{name:"session start",data:{id:"s3ss10n"},id:"1700000601-gr0up-2",trigger:"load",entity:"session",action:"start",timestamp:1700000601,group:"gr0up",count:2,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"session start",data:{id:"s3ss10n"},user:{hash:"e183220b699c10a8"},id:"1700000601-gr0up-2",trigger:"load",entity:"session",action:"start",timestamp:1700000601,group:"gr0up",count:2,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},u={description:'Privacy-preserving fingerprint using key+fn pattern: fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. Config: fields: [{ key: "ingest.ip", fn: ip => ip.replace(/\\.\\d+$/, ".0") }, "ingest.userAgent"]',in:{name:"page view",data:{domain:"www.example.com",title:"Privacy Policy",id:"/privacy"},id:"1700000602-gr0up-3",trigger:"load",entity:"page",action:"view",timestamp:1700000602,group:"gr0up",count:3,version:{tagging:1},source:{type:"server",id:"",previous_id:""}},out:{event:{name:"page view",data:{domain:"www.example.com",title:"Privacy Policy",id:"/privacy"},user:{hash:"44d9154b9a9b3792"},id:"1700000602-gr0up-3",trigger:"load",entity:"page",action:"view",timestamp:1700000602,group:"gr0up",count:3,version:{tagging:1},source:{type:"server",id:"",previous_id:""}}}},c={"ingest-prerequisite":{text:"Fields starting with ingest.* require the server source to have config.ingest configured. Without it, ingest is undefined and all ingest.* fields resolve to empty strings — the hash is still generated but not unique. Always pair this transformer with a source that extracts request metadata.",code:[{lang:"json",code:JSON.stringify({sources:{express:{package:"@walkeros/server-source-express",config:{settings:{port:8080},ingest:{ip:"req.ip",userAgent:"req.headers.user-agent",origin:"req.headers.origin"}}}},transformers:{fingerprint:{package:"@walkeros/server-transformer-fingerprint",config:{settings:{fields:["ingest.ip","ingest.userAgent"],output:"user.hash",length:16}}}}},null,2)}]},"fields-overview":{text:"Fields resolve from { event, ingest } via walkerOS mapping. Common patterns: ingest.ip (client IP), ingest.userAgent (browser UA), event.data.* (any event property). For time-based rotation use fn fields: daily rotation with toISOString().slice(0,10), monthly with getDate(). Order matters — same fields in different order produce different hashes. Use { key, fn } objects to transform before hashing (e.g., IP anonymization via the ipAnonymization step example)."}};export{o as examples,c as hints,i 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/examples/index.ts","../src/examples/step.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Fingerprint transformer settings schema.\n *\n * Mirrors: types.ts FingerprintSettings\n */\nexport const SettingsSchema = z\n .object({\n fields: z\n .array(\n z.union([\n z\n .string()\n .describe('Dot-notation path: \"ingest.ip\", \"event.data.userId\"'),\n z\n .object({\n key: z.string().optional().describe('Source property path'),\n value: z\n .unknown()\n .optional()\n .describe('Static value or fallback'),\n fn: z\n .string()\n .optional()\n .describe('$code: function for value transformation'),\n })\n .describe('Mapping value config for computed fields'),\n ]),\n )\n .describe(\n 'Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }.',\n ),\n output: z\n .string()\n .optional()\n .describe(\n 'Dot-notation path where hash is stored on the event. Default: \"user.hash\"',\n ),\n length: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Truncate hash to this length. Default: full 64-char SHA-256 hash',\n ),\n })\n .describe(\n 'Fingerprint transformer: generates deterministic user hashes from event fields',\n );\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\nexport const serverFingerprint: Flow.StepExample = {\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n user: { hash: '158f99cc06e33fd6' },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const missingFields: Flow.StepExample = {\n in: {\n name: 'session start',\n data: { id: 's3ss10n' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'session start',\n data: { id: 's3ss10n' },\n user: { hash: 'e183220b699c10a8' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const ipAnonymization: Flow.StepExample = {\n description:\n 'Privacy-preserving fingerprint using key+fn pattern: ' +\n 'fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. ' +\n 'Config: fields: [{ key: \"ingest.ip\", fn: ip => ip.replace(/\\\\.\\\\d+$/, \".0\") }, \"ingest.userAgent\"]',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n user: { hash: '44d9154b9a9b3792' },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/schemas/index.ts","../src/schemas/settings.ts","../src/examples/index.ts","../src/examples/step.ts","../src/hints.ts"],"sourcesContent":["import { zodToSchema } from '@walkeros/core/dev';\nimport { SettingsSchema } from './settings';\n\nexport { SettingsSchema, type Settings } from './settings';\nexport const settings = zodToSchema(SettingsSchema);\n","import { z } from '@walkeros/core/dev';\n\n/**\n * Fingerprint transformer settings schema.\n *\n * Mirrors: types.ts FingerprintSettings\n */\nexport const SettingsSchema = z\n .object({\n fields: z\n .array(\n z.union([\n z\n .string()\n .describe('Dot-notation path: \"ingest.ip\", \"event.data.userId\"'),\n z\n .object({\n key: z.string().optional().describe('Source property path'),\n value: z\n .unknown()\n .optional()\n .describe('Static value or fallback'),\n fn: z\n .string()\n .optional()\n .describe('$code: function for value transformation'),\n })\n .describe('Mapping value config for computed fields'),\n ]),\n )\n .describe(\n 'Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }.',\n ),\n output: z\n .string()\n .optional()\n .describe(\n 'Dot-notation path where hash is stored on the event. Default: \"user.hash\"',\n ),\n length: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n 'Truncate hash to this length. Default: full 64-char SHA-256 hash',\n ),\n })\n .describe(\n 'Fingerprint transformer: generates deterministic user hashes from event fields',\n );\n\nexport type Settings = z.infer<typeof SettingsSchema>;\n","export * as step from './step';\n","import type { Flow } from '@walkeros/core';\n\nexport const serverFingerprint: Flow.StepExample = {\n description:\n 'Standard server fingerprint using ingest.ip and ingest.userAgent. Requires source config.ingest.',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Getting Started',\n id: '/docs/getting-started',\n },\n user: { hash: '158f99cc06e33fd6' },\n id: '1700000600-gr0up-1',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000600,\n group: 'gr0up',\n count: 1,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const missingFields: Flow.StepExample = {\n description:\n 'Graceful handling when ingest is missing — fields resolve to empty strings, hash is still generated.',\n in: {\n name: 'session start',\n data: { id: 's3ss10n' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'session start',\n data: { id: 's3ss10n' },\n user: { hash: 'e183220b699c10a8' },\n id: '1700000601-gr0up-2',\n trigger: 'load',\n entity: 'session',\n action: 'start',\n timestamp: 1700000601,\n group: 'gr0up',\n count: 2,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n\nexport const ipAnonymization: Flow.StepExample = {\n description:\n 'Privacy-preserving fingerprint using key+fn pattern: ' +\n 'fn truncates IP to /24 subnet before hashing, so 10.0.42.* users share a hash. ' +\n 'Config: fields: [{ key: \"ingest.ip\", fn: ip => ip.replace(/\\\\.\\\\d+$/, \".0\") }, \"ingest.userAgent\"]',\n in: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n out: {\n event: {\n name: 'page view',\n data: {\n domain: 'www.example.com',\n title: 'Privacy Policy',\n id: '/privacy',\n },\n user: { hash: '44d9154b9a9b3792' },\n id: '1700000602-gr0up-3',\n trigger: 'load',\n entity: 'page',\n action: 'view',\n timestamp: 1700000602,\n group: 'gr0up',\n count: 3,\n version: { tagging: 1 },\n source: { type: 'server', id: '', previous_id: '' },\n },\n },\n};\n","import type { Hint } from '@walkeros/core';\n\nexport const hints: Hint.Hints = {\n 'ingest-prerequisite': {\n text: 'Fields starting with ingest.* require the server source to have config.ingest configured. Without it, ingest is undefined and all ingest.* fields resolve to empty strings — the hash is still generated but not unique. Always pair this transformer with a source that extracts request metadata.',\n code: [\n {\n lang: 'json',\n code: JSON.stringify(\n {\n sources: {\n express: {\n package: '@walkeros/server-source-express',\n config: {\n settings: { port: 8080 },\n ingest: {\n ip: 'req.ip',\n userAgent: 'req.headers.user-agent',\n origin: 'req.headers.origin',\n },\n },\n },\n },\n transformers: {\n fingerprint: {\n package: '@walkeros/server-transformer-fingerprint',\n config: {\n settings: {\n fields: ['ingest.ip', 'ingest.userAgent'],\n output: 'user.hash',\n length: 16,\n },\n },\n },\n },\n },\n null,\n 2,\n ),\n },\n ],\n },\n 'fields-overview': {\n text: 'Fields resolve from { event, ingest } via walkerOS mapping. Common patterns: ingest.ip (client IP), ingest.userAgent (browser UA), event.data.* (any event property). For time-based rotation use fn fields: daily rotation with toISOString().slice(0,10), monthly with getDate(). Order matters — same fields in different order produce different hashes. Use { key, fn } objects to transform before hashing (e.g., IP anonymization via the ipAnonymization step example).',\n },\n};\n"],"mappings":";;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,SAAS,mBAAmB;;;ACA5B,SAAS,SAAS;AAOX,IAAM,iBAAiB,EAC3B,OAAO;AAAA,EACN,QAAQ,EACL;AAAA,IACC,EAAE,MAAM;AAAA,MACN,EACG,OAAO,EACP,SAAS,qDAAqD;AAAA,MACjE,EACG,OAAO;AAAA,QACN,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,sBAAsB;AAAA,QAC1D,OAAO,EACJ,QAAQ,EACR,SAAS,EACT,SAAS,0BAA0B;AAAA,QACtC,IAAI,EACD,OAAO,EACP,SAAS,EACT,SAAS,0CAA0C;AAAA,MACxD,CAAC,EACA,SAAS,0CAA0C;AAAA,IACxD,CAAC;AAAA,EACH,EACC;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EACL,OAAO,EACP,SAAS,EACT;AAAA,IACC;AAAA,EACF;AAAA,EACF,QAAQ,EACL,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,IACC;AAAA,EACF;AACJ,CAAC,EACA;AAAA,EACC;AACF;;;AD9CK,IAAM,WAAW,YAAY,cAAc;;;AEJlD;AAAA;AAAA;AAAA;;;ACAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEO,IAAM,oBAAsC;AAAA,EACjD,aACE;AAAA,EACF,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,IAAI;AAAA,IACN;AAAA,IACA,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS,EAAE,SAAS,EAAE;AAAA,IACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,EACpD;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,IAAI;AAAA,MACN;AAAA,MACA,MAAM,EAAE,MAAM,mBAAmB;AAAA,MACjC,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,SAAS,EAAE;AAAA,MACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,IACpD;AAAA,EACF;AACF;AAEO,IAAM,gBAAkC;AAAA,EAC7C,aACE;AAAA,EACF,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM,EAAE,IAAI,UAAU;AAAA,IACtB,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS,EAAE,SAAS,EAAE;AAAA,IACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,EACpD;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM,EAAE,IAAI,UAAU;AAAA,MACtB,MAAM,EAAE,MAAM,mBAAmB;AAAA,MACjC,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,SAAS,EAAE;AAAA,MACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,IACpD;AAAA,EACF;AACF;AAEO,IAAM,kBAAoC;AAAA,EAC/C,aACE;AAAA,EAGF,IAAI;AAAA,IACF,MAAM;AAAA,IACN,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,IAAI;AAAA,IACN;AAAA,IACA,IAAI;AAAA,IACJ,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS,EAAE,SAAS,EAAE;AAAA,IACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,EACpD;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,MACL,MAAM;AAAA,MACN,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,OAAO;AAAA,QACP,IAAI;AAAA,MACN;AAAA,MACA,MAAM,EAAE,MAAM,mBAAmB;AAAA,MACjC,IAAI;AAAA,MACJ,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,OAAO;AAAA,MACP,OAAO;AAAA,MACP,SAAS,EAAE,SAAS,EAAE;AAAA,MACtB,QAAQ,EAAE,MAAM,UAAU,IAAI,IAAI,aAAa,GAAG;AAAA,IACpD;AAAA,EACF;AACF;;;ACtHO,IAAM,QAAoB;AAAA,EAC/B,uBAAuB;AAAA,IACrB,MAAM;AAAA,IACN,MAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,QACN,MAAM,KAAK;AAAA,UACT;AAAA,YACE,SAAS;AAAA,cACP,SAAS;AAAA,gBACP,SAAS;AAAA,gBACT,QAAQ;AAAA,kBACN,UAAU,EAAE,MAAM,KAAK;AAAA,kBACvB,QAAQ;AAAA,oBACN,IAAI;AAAA,oBACJ,WAAW;AAAA,oBACX,QAAQ;AAAA,kBACV;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,YACA,cAAc;AAAA,cACZ,aAAa;AAAA,gBACX,SAAS;AAAA,gBACT,QAAQ;AAAA,kBACN,UAAU;AAAA,oBACR,QAAQ,CAAC,aAAa,kBAAkB;AAAA,oBACxC,QAAQ;AAAA,oBACR,QAAQ;AAAA,kBACV;AAAA,gBACF;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,mBAAmB;AAAA,IACjB,MAAM;AAAA,EACR;AACF;","names":[]}
|
package/dist/walkerOS.json
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$meta": {
|
|
3
3
|
"package": "@walkeros/server-transformer-fingerprint",
|
|
4
|
-
"version": "3.0.
|
|
4
|
+
"version": "3.0.2",
|
|
5
5
|
"type": "transformer",
|
|
6
|
-
"platform":
|
|
6
|
+
"platform": [
|
|
7
|
+
"server"
|
|
8
|
+
],
|
|
7
9
|
"docs": "https://www.walkeros.io/docs/transformers/fingerprint",
|
|
8
10
|
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/server/transformers/fingerprint/src"
|
|
9
11
|
},
|
|
@@ -117,6 +119,7 @@
|
|
|
117
119
|
}
|
|
118
120
|
},
|
|
119
121
|
"missingFields": {
|
|
122
|
+
"description": "Graceful handling when ingest is missing — fields resolve to empty strings, hash is still generated.",
|
|
120
123
|
"in": {
|
|
121
124
|
"name": "session start",
|
|
122
125
|
"data": {
|
|
@@ -166,6 +169,7 @@
|
|
|
166
169
|
}
|
|
167
170
|
},
|
|
168
171
|
"serverFingerprint": {
|
|
172
|
+
"description": "Standard server fingerprint using ingest.ip and ingest.userAgent. Requires source config.ingest.",
|
|
169
173
|
"in": {
|
|
170
174
|
"name": "page view",
|
|
171
175
|
"data": {
|
|
@@ -219,5 +223,19 @@
|
|
|
219
223
|
}
|
|
220
224
|
}
|
|
221
225
|
}
|
|
226
|
+
},
|
|
227
|
+
"hints": {
|
|
228
|
+
"ingest-prerequisite": {
|
|
229
|
+
"text": "Fields starting with ingest.* require the server source to have config.ingest configured. Without it, ingest is undefined and all ingest.* fields resolve to empty strings — the hash is still generated but not unique. Always pair this transformer with a source that extracts request metadata.",
|
|
230
|
+
"code": [
|
|
231
|
+
{
|
|
232
|
+
"lang": "json",
|
|
233
|
+
"code": "{\n \"sources\": {\n \"express\": {\n \"package\": \"@walkeros/server-source-express\",\n \"config\": {\n \"settings\": {\n \"port\": 8080\n },\n \"ingest\": {\n \"ip\": \"req.ip\",\n \"userAgent\": \"req.headers.user-agent\",\n \"origin\": \"req.headers.origin\"\n }\n }\n }\n },\n \"transformers\": {\n \"fingerprint\": {\n \"package\": \"@walkeros/server-transformer-fingerprint\",\n \"config\": {\n \"settings\": {\n \"fields\": [\n \"ingest.ip\",\n \"ingest.userAgent\"\n ],\n \"output\": \"user.hash\",\n \"length\": 16\n }\n }\n }\n }\n}"
|
|
234
|
+
}
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
"fields-overview": {
|
|
238
|
+
"text": "Fields resolve from { event, ingest } via walkerOS mapping. Common patterns: ingest.ip (client IP), ingest.userAgent (browser UA), event.data.* (any event property). For time-based rotation use fn fields: daily rotation with toISOString().slice(0,10), monthly with getDate(). Order matters — same fields in different order produce different hashes. Use { key, fn } objects to transform before hashing (e.g., IP anonymization via the ipAnonymization step example)."
|
|
239
|
+
}
|
|
222
240
|
}
|
|
223
241
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@walkeros/server-transformer-fingerprint",
|
|
3
3
|
"description": "Fingerprint transformer for walkerOS server - hash configurable fields for session continuity",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0-next-1773967844643",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
"update": "npx npm-check-updates -u && npm update"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@walkeros/core": "
|
|
30
|
-
"@walkeros/server-core": "
|
|
29
|
+
"@walkeros/core": "4.0.0-next-1773967844643",
|
|
30
|
+
"@walkeros/server-core": "4.0.0-next-1773967844643"
|
|
31
31
|
},
|
|
32
32
|
"repository": {
|
|
33
33
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|
|
@@ -40,7 +40,9 @@
|
|
|
40
40
|
},
|
|
41
41
|
"walkerOS": {
|
|
42
42
|
"type": "transformer",
|
|
43
|
-
"platform":
|
|
43
|
+
"platform": [
|
|
44
|
+
"server"
|
|
45
|
+
],
|
|
44
46
|
"docs": "https://www.walkeros.io/docs/transformers/fingerprint"
|
|
45
47
|
},
|
|
46
48
|
"keywords": [
|
|
@@ -57,7 +59,7 @@
|
|
|
57
59
|
}
|
|
58
60
|
],
|
|
59
61
|
"dependencies": {
|
|
60
|
-
"@walkeros/core": "
|
|
61
|
-
"@walkeros/server-core": "
|
|
62
|
+
"@walkeros/core": "4.0.0-next-1773967844643",
|
|
63
|
+
"@walkeros/server-core": "4.0.0-next-1773967844643"
|
|
62
64
|
}
|
|
63
65
|
}
|