@walkeros/server-transformer-fingerprint 3.0.0 → 3.0.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.d.mts +46 -0
- package/dist/dev.d.ts +46 -0
- package/dist/dev.js +1 -0
- package/dist/dev.js.map +1 -0
- package/dist/dev.mjs +1 -0
- package/dist/dev.mjs.map +1 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/walkerOS.json +223 -0
- package/package.json +15 -10
package/dist/dev.d.mts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
|
+
import { z } from '@walkeros/core/dev';
|
|
3
|
+
import { Flow } from '@walkeros/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fingerprint transformer settings schema.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors: types.ts FingerprintSettings
|
|
9
|
+
*/
|
|
10
|
+
declare const SettingsSchema: z.ZodObject<{
|
|
11
|
+
fields: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
12
|
+
key: z.ZodOptional<z.ZodString>;
|
|
13
|
+
value: z.ZodOptional<z.ZodUnknown>;
|
|
14
|
+
fn: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>]>>;
|
|
16
|
+
output: z.ZodOptional<z.ZodString>;
|
|
17
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
type Settings = z.infer<typeof SettingsSchema>;
|
|
20
|
+
|
|
21
|
+
declare const settings: _walkeros_core_dev.JSONSchema;
|
|
22
|
+
|
|
23
|
+
type index$1_Settings = Settings;
|
|
24
|
+
declare const index$1_SettingsSchema: typeof SettingsSchema;
|
|
25
|
+
declare const index$1_settings: typeof settings;
|
|
26
|
+
declare namespace index$1 {
|
|
27
|
+
export { type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare const serverFingerprint: Flow.StepExample;
|
|
31
|
+
declare const missingFields: Flow.StepExample;
|
|
32
|
+
declare const ipAnonymization: Flow.StepExample;
|
|
33
|
+
|
|
34
|
+
declare const step_ipAnonymization: typeof ipAnonymization;
|
|
35
|
+
declare const step_missingFields: typeof missingFields;
|
|
36
|
+
declare const step_serverFingerprint: typeof serverFingerprint;
|
|
37
|
+
declare namespace step {
|
|
38
|
+
export { step_ipAnonymization as ipAnonymization, step_missingFields as missingFields, step_serverFingerprint as serverFingerprint };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare const index_step: typeof step;
|
|
42
|
+
declare namespace index {
|
|
43
|
+
export { index_step as step };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { index as examples, index$1 as schemas };
|
package/dist/dev.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as _walkeros_core_dev from '@walkeros/core/dev';
|
|
2
|
+
import { z } from '@walkeros/core/dev';
|
|
3
|
+
import { Flow } from '@walkeros/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Fingerprint transformer settings schema.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors: types.ts FingerprintSettings
|
|
9
|
+
*/
|
|
10
|
+
declare const SettingsSchema: z.ZodObject<{
|
|
11
|
+
fields: z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
12
|
+
key: z.ZodOptional<z.ZodString>;
|
|
13
|
+
value: z.ZodOptional<z.ZodUnknown>;
|
|
14
|
+
fn: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>]>>;
|
|
16
|
+
output: z.ZodOptional<z.ZodString>;
|
|
17
|
+
length: z.ZodOptional<z.ZodNumber>;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
type Settings = z.infer<typeof SettingsSchema>;
|
|
20
|
+
|
|
21
|
+
declare const settings: _walkeros_core_dev.JSONSchema;
|
|
22
|
+
|
|
23
|
+
type index$1_Settings = Settings;
|
|
24
|
+
declare const index$1_SettingsSchema: typeof SettingsSchema;
|
|
25
|
+
declare const index$1_settings: typeof settings;
|
|
26
|
+
declare namespace index$1 {
|
|
27
|
+
export { type index$1_Settings as Settings, index$1_SettingsSchema as SettingsSchema, index$1_settings as settings };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare const serverFingerprint: Flow.StepExample;
|
|
31
|
+
declare const missingFields: Flow.StepExample;
|
|
32
|
+
declare const ipAnonymization: Flow.StepExample;
|
|
33
|
+
|
|
34
|
+
declare const step_ipAnonymization: typeof ipAnonymization;
|
|
35
|
+
declare const step_missingFields: typeof missingFields;
|
|
36
|
+
declare const step_serverFingerprint: typeof serverFingerprint;
|
|
37
|
+
declare namespace step {
|
|
38
|
+
export { step_ipAnonymization as ipAnonymization, step_missingFields as missingFields, step_serverFingerprint as serverFingerprint };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
declare const index_step: typeof step;
|
|
42
|
+
declare namespace index {
|
|
43
|
+
export { index_step as step };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { index as examples, index$1 as schemas };
|
package/dist/dev.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var e,t=Object.defineProperty,i=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,a=Object.prototype.hasOwnProperty,s=(e,i)=>{for(var r in i)t(e,r,{get:i[r],enumerable:!0})},n={};s(n,{examples:()=>c,schemas:()=>o}),module.exports=(e=n,((e,s,n,o)=>{if(s&&"object"==typeof s||"function"==typeof s)for(let g of r(s))a.call(e,g)||g===n||t(e,g,{get:()=>s[g],enumerable:!(o=i(s,g))||o.enumerable});return e})(t({},"__esModule",{value:!0}),e));var o={};s(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={};s(c,{step:()=>v});var v={};s(v,{ipAnonymization:()=>h,missingFields:()=>m,serverFingerprint:()=>l});var l={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={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:""}}}};//# sourceMappingURL=dev.js.map
|
package/dist/dev.js.map
ADDED
|
@@ -0,0 +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"]}
|
package/dist/dev.mjs
ADDED
|
@@ -0,0 +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:()=>s,settings:()=>n});import{zodToSchema as r}from"@walkeros/core/dev";import{z as a}from"@walkeros/core/dev";var s=a.object({fields:a.array(a.union([a.string().describe('Dot-notation path: "ingest.ip", "event.data.userId"'),a.object({key:a.string().optional().describe("Source property path"),value:a.unknown().optional().describe("Static value or fallback"),fn:a.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:a.string().optional().describe('Dot-notation path where hash is stored on the event. Default: "user.hash"'),length:a.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"),n=r(s),o={};t(o,{step:()=>g});var g={};t(g,{ipAnonymization:()=>u,missingFields:()=>d,serverFingerprint:()=>p});var p={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={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:""}}}};export{o as examples,i as schemas};//# sourceMappingURL=dev.mjs.map
|
package/dist/dev.mjs.map
ADDED
|
@@ -0,0 +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":";;;;;;;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,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,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;","names":[]}
|
package/dist/index.d.mts
CHANGED
|
@@ -53,4 +53,4 @@ interface FingerprintSettings {
|
|
|
53
53
|
*/
|
|
54
54
|
declare const transformerFingerprint: Transformer.Init<Transformer.Types<FingerprintSettings>>;
|
|
55
55
|
|
|
56
|
-
export { type FingerprintSettings, transformerFingerprint };
|
|
56
|
+
export { type FingerprintSettings, transformerFingerprint as default, transformerFingerprint };
|
package/dist/index.d.ts
CHANGED
|
@@ -53,4 +53,4 @@ interface FingerprintSettings {
|
|
|
53
53
|
*/
|
|
54
54
|
declare const transformerFingerprint: Transformer.Init<Transformer.Types<FingerprintSettings>>;
|
|
55
55
|
|
|
56
|
-
export { type FingerprintSettings, transformerFingerprint };
|
|
56
|
+
export { type FingerprintSettings, transformerFingerprint as default, transformerFingerprint };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var e,r=Object.defineProperty,t=Object.getOwnPropertyDescriptor,
|
|
1
|
+
"use strict";var e,r=Object.defineProperty,t=Object.getOwnPropertyDescriptor,n=Object.getOwnPropertyNames,o=Object.prototype.hasOwnProperty,a={};((e,t)=>{for(var n in t)r(e,n,{get:t[n],enumerable:!0})})(a,{default:()=>l,transformerFingerprint:()=>l}),module.exports=(e=a,((e,a,s,i)=>{if(a&&"object"==typeof a||"function"==typeof a)for(let l of n(a))o.call(e,l)||l===s||r(e,l,{get:()=>a[l],enumerable:!(i=t(a,l))||i.enumerable});return e})(r({},"__esModule",{value:!0}),e));var s=require("@walkeros/core"),i=require("@walkeros/server-core"),l=e=>{const{config:r}=e,t=r.settings||{},n=t.fields||[],o=t.output||"user.hash",a=t.length;return{type:"fingerprint",config:r,async push(e,r){const{ingest:t,collector:l}=r,c={event:e,ingest:t},u=""+(await Promise.all(n.map(e=>(0,s.getMappingValue)(c,e,{collector:l})))).map(e=>String(null!=e?e:"")).join(""),p=await(0,i.getHashServer)(u,a);return{event:(0,s.setByPath)(e,o,p)}}}};//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/transformer.ts"],"sourcesContent":["export { transformerFingerprint } from './transformer';\nexport type { FingerprintSettings } from './types';\n","import type { Mapping, Transformer } from '@walkeros/core';\nimport { getMappingValue, setByPath } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\nimport type { FingerprintSettings } from './types';\n\n/**\n * Fingerprint transformer - hash configurable fields for session continuity.\n *\n * Resolves fields from { event, ingest } source object using getMappingValue,\n * concatenates values in order, hashes with SHA-256, and stores at output path.\n *\n * @example\n * transformerFingerprint({\n * config: {\n * settings: {\n * fields: [\n * 'ingest.ip',\n * 'ingest.userAgent',\n * { fn: () => new Date().getDate() },\n * ],\n * output: 'user.hash',\n * length: 16,\n * },\n * },\n * })\n */\nexport const transformerFingerprint: Transformer.Init<\n Transformer.Types<FingerprintSettings>\n> = (context) => {\n const { config } = context;\n const settings = (config.settings || {}) as Partial<FingerprintSettings>;\n const fields: Mapping.Value[] = settings.fields || [];\n const output: string = settings.output || 'user.hash';\n const length: number | undefined = settings.length;\n\n return {\n type: 'fingerprint',\n config: config as Transformer.Config<\n Transformer.Types<FingerprintSettings>\n >,\n\n async push(event, context) {\n const { ingest, collector } = context;\n\n // Build source object for field resolution\n const source = { event, ingest };\n\n // Resolve each field via mapping (maintains order)\n const values = await Promise.all(\n fields.map((field: Mapping.Value) =>\n getMappingValue(source, field, { collector }),\n ),\n );\n\n // Safe string concatenation: '' prefix + String() cast for each value\n // '' prefix ensures we always have a string even if fields is empty\n // String(v ?? '') handles undefined/null gracefully\n const input = '' + values.map((v: unknown) => String(v ?? '')).join('');\n\n // Hash and store at output path\n const hash = await getHashServer(input, length);\n return setByPath(event, output, hash);\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,kBAA2C;AAC3C,yBAA8B;AAwBvB,IAAM,yBAET,CAAC,YAAY;AACf,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,WAAY,OAAO,YAAY,CAAC;AACtC,QAAM,SAA0B,SAAS,UAAU,CAAC;AACpD,QAAM,SAAiB,SAAS,UAAU;AAC1C,QAAM,SAA6B,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IAIA,MAAM,KAAK,OAAOA,UAAS;AACzB,YAAM,EAAE,QAAQ,UAAU,IAAIA;AAG9B,YAAM,SAAS,EAAE,OAAO,OAAO;AAG/B,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,OAAO;AAAA,UAAI,CAAC,cACV,6BAAgB,QAAQ,OAAO,EAAE,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAKA,YAAM,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAe,OAAO,gBAAK,EAAE,CAAC,EAAE,KAAK,EAAE;AAGtE,YAAM,OAAO,UAAM,kCAAc,OAAO,MAAM;AAC9C,
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/transformer.ts"],"sourcesContent":["export { transformerFingerprint } from './transformer';\nexport type { FingerprintSettings } from './types';\n\nexport { transformerFingerprint as default } from './transformer';\n","import type { Mapping, Transformer } from '@walkeros/core';\nimport { getMappingValue, setByPath } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\nimport type { FingerprintSettings } from './types';\n\n/**\n * Fingerprint transformer - hash configurable fields for session continuity.\n *\n * Resolves fields from { event, ingest } source object using getMappingValue,\n * concatenates values in order, hashes with SHA-256, and stores at output path.\n *\n * @example\n * transformerFingerprint({\n * config: {\n * settings: {\n * fields: [\n * 'ingest.ip',\n * 'ingest.userAgent',\n * { fn: () => new Date().getDate() },\n * ],\n * output: 'user.hash',\n * length: 16,\n * },\n * },\n * })\n */\nexport const transformerFingerprint: Transformer.Init<\n Transformer.Types<FingerprintSettings>\n> = (context) => {\n const { config } = context;\n const settings = (config.settings || {}) as Partial<FingerprintSettings>;\n const fields: Mapping.Value[] = settings.fields || [];\n const output: string = settings.output || 'user.hash';\n const length: number | undefined = settings.length;\n\n return {\n type: 'fingerprint',\n config: config as Transformer.Config<\n Transformer.Types<FingerprintSettings>\n >,\n\n async push(event, context) {\n const { ingest, collector } = context;\n\n // Build source object for field resolution\n const source = { event, ingest };\n\n // Resolve each field via mapping (maintains order)\n const values = await Promise.all(\n fields.map((field: Mapping.Value) =>\n getMappingValue(source, field, { collector }),\n ),\n );\n\n // Safe string concatenation: '' prefix + String() cast for each value\n // '' prefix ensures we always have a string even if fields is empty\n // String(v ?? '') handles undefined/null gracefully\n const input = '' + values.map((v: unknown) => String(v ?? '')).join('');\n\n // Hash and store at output path\n const hash = await getHashServer(input, length);\n return { event: setByPath(event, output, hash) };\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,kBAA2C;AAC3C,yBAA8B;AAwBvB,IAAM,yBAET,CAAC,YAAY;AACf,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,WAAY,OAAO,YAAY,CAAC;AACtC,QAAM,SAA0B,SAAS,UAAU,CAAC;AACpD,QAAM,SAAiB,SAAS,UAAU;AAC1C,QAAM,SAA6B,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IAIA,MAAM,KAAK,OAAOA,UAAS;AACzB,YAAM,EAAE,QAAQ,UAAU,IAAIA;AAG9B,YAAM,SAAS,EAAE,OAAO,OAAO;AAG/B,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,OAAO;AAAA,UAAI,CAAC,cACV,6BAAgB,QAAQ,OAAO,EAAE,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAKA,YAAM,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAe,OAAO,gBAAK,EAAE,CAAC,EAAE,KAAK,EAAE;AAGtE,YAAM,OAAO,UAAM,kCAAc,OAAO,MAAM;AAC9C,aAAO,EAAE,WAAO,uBAAU,OAAO,QAAQ,IAAI,EAAE;AAAA,IACjD;AAAA,EACF;AACF;","names":["context"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getMappingValue as
|
|
1
|
+
import{getMappingValue as e,setByPath as t}from"@walkeros/core";import{getHashServer as r}from"@walkeros/server-core";var o=o=>{const{config:n}=o,s=n.settings||{},i=s.fields||[],a=s.output||"user.hash",l=s.length;return{type:"fingerprint",config:n,async push(o,n){const{ingest:s,collector:c}=n,p={event:o,ingest:s},g=""+(await Promise.all(i.map(t=>e(p,t,{collector:c})))).map(e=>String(null!=e?e:"")).join(""),u=await r(g,l);return{event:t(o,a,u)}}}};export{o as default,o as transformerFingerprint};//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/transformer.ts"],"sourcesContent":["import type { Mapping, Transformer } from '@walkeros/core';\nimport { getMappingValue, setByPath } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\nimport type { FingerprintSettings } from './types';\n\n/**\n * Fingerprint transformer - hash configurable fields for session continuity.\n *\n * Resolves fields from { event, ingest } source object using getMappingValue,\n * concatenates values in order, hashes with SHA-256, and stores at output path.\n *\n * @example\n * transformerFingerprint({\n * config: {\n * settings: {\n * fields: [\n * 'ingest.ip',\n * 'ingest.userAgent',\n * { fn: () => new Date().getDate() },\n * ],\n * output: 'user.hash',\n * length: 16,\n * },\n * },\n * })\n */\nexport const transformerFingerprint: Transformer.Init<\n Transformer.Types<FingerprintSettings>\n> = (context) => {\n const { config } = context;\n const settings = (config.settings || {}) as Partial<FingerprintSettings>;\n const fields: Mapping.Value[] = settings.fields || [];\n const output: string = settings.output || 'user.hash';\n const length: number | undefined = settings.length;\n\n return {\n type: 'fingerprint',\n config: config as Transformer.Config<\n Transformer.Types<FingerprintSettings>\n >,\n\n async push(event, context) {\n const { ingest, collector } = context;\n\n // Build source object for field resolution\n const source = { event, ingest };\n\n // Resolve each field via mapping (maintains order)\n const values = await Promise.all(\n fields.map((field: Mapping.Value) =>\n getMappingValue(source, field, { collector }),\n ),\n );\n\n // Safe string concatenation: '' prefix + String() cast for each value\n // '' prefix ensures we always have a string even if fields is empty\n // String(v ?? '') handles undefined/null gracefully\n const input = '' + values.map((v: unknown) => String(v ?? '')).join('');\n\n // Hash and store at output path\n const hash = await getHashServer(input, length);\n return setByPath(event, output, hash);\n },\n };\n};\n"],"mappings":";AACA,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,qBAAqB;AAwBvB,IAAM,yBAET,CAAC,YAAY;AACf,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,WAAY,OAAO,YAAY,CAAC;AACtC,QAAM,SAA0B,SAAS,UAAU,CAAC;AACpD,QAAM,SAAiB,SAAS,UAAU;AAC1C,QAAM,SAA6B,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IAIA,MAAM,KAAK,OAAOA,UAAS;AACzB,YAAM,EAAE,QAAQ,UAAU,IAAIA;AAG9B,YAAM,SAAS,EAAE,OAAO,OAAO;AAG/B,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,OAAO;AAAA,UAAI,CAAC,UACV,gBAAgB,QAAQ,OAAO,EAAE,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAKA,YAAM,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAe,OAAO,gBAAK,EAAE,CAAC,EAAE,KAAK,EAAE;AAGtE,YAAM,OAAO,MAAM,cAAc,OAAO,MAAM;AAC9C,aAAO,UAAU,OAAO,QAAQ,IAAI;AAAA,
|
|
1
|
+
{"version":3,"sources":["../src/transformer.ts"],"sourcesContent":["import type { Mapping, Transformer } from '@walkeros/core';\nimport { getMappingValue, setByPath } from '@walkeros/core';\nimport { getHashServer } from '@walkeros/server-core';\nimport type { FingerprintSettings } from './types';\n\n/**\n * Fingerprint transformer - hash configurable fields for session continuity.\n *\n * Resolves fields from { event, ingest } source object using getMappingValue,\n * concatenates values in order, hashes with SHA-256, and stores at output path.\n *\n * @example\n * transformerFingerprint({\n * config: {\n * settings: {\n * fields: [\n * 'ingest.ip',\n * 'ingest.userAgent',\n * { fn: () => new Date().getDate() },\n * ],\n * output: 'user.hash',\n * length: 16,\n * },\n * },\n * })\n */\nexport const transformerFingerprint: Transformer.Init<\n Transformer.Types<FingerprintSettings>\n> = (context) => {\n const { config } = context;\n const settings = (config.settings || {}) as Partial<FingerprintSettings>;\n const fields: Mapping.Value[] = settings.fields || [];\n const output: string = settings.output || 'user.hash';\n const length: number | undefined = settings.length;\n\n return {\n type: 'fingerprint',\n config: config as Transformer.Config<\n Transformer.Types<FingerprintSettings>\n >,\n\n async push(event, context) {\n const { ingest, collector } = context;\n\n // Build source object for field resolution\n const source = { event, ingest };\n\n // Resolve each field via mapping (maintains order)\n const values = await Promise.all(\n fields.map((field: Mapping.Value) =>\n getMappingValue(source, field, { collector }),\n ),\n );\n\n // Safe string concatenation: '' prefix + String() cast for each value\n // '' prefix ensures we always have a string even if fields is empty\n // String(v ?? '') handles undefined/null gracefully\n const input = '' + values.map((v: unknown) => String(v ?? '')).join('');\n\n // Hash and store at output path\n const hash = await getHashServer(input, length);\n return { event: setByPath(event, output, hash) };\n },\n };\n};\n"],"mappings":";AACA,SAAS,iBAAiB,iBAAiB;AAC3C,SAAS,qBAAqB;AAwBvB,IAAM,yBAET,CAAC,YAAY;AACf,QAAM,EAAE,OAAO,IAAI;AACnB,QAAM,WAAY,OAAO,YAAY,CAAC;AACtC,QAAM,SAA0B,SAAS,UAAU,CAAC;AACpD,QAAM,SAAiB,SAAS,UAAU;AAC1C,QAAM,SAA6B,SAAS;AAE5C,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IAIA,MAAM,KAAK,OAAOA,UAAS;AACzB,YAAM,EAAE,QAAQ,UAAU,IAAIA;AAG9B,YAAM,SAAS,EAAE,OAAO,OAAO;AAG/B,YAAM,SAAS,MAAM,QAAQ;AAAA,QAC3B,OAAO;AAAA,UAAI,CAAC,UACV,gBAAgB,QAAQ,OAAO,EAAE,UAAU,CAAC;AAAA,QAC9C;AAAA,MACF;AAKA,YAAM,QAAQ,KAAK,OAAO,IAAI,CAAC,MAAe,OAAO,gBAAK,EAAE,CAAC,EAAE,KAAK,EAAE;AAGtE,YAAM,OAAO,MAAM,cAAc,OAAO,MAAM;AAC9C,aAAO,EAAE,OAAO,UAAU,OAAO,QAAQ,IAAI,EAAE;AAAA,IACjD;AAAA,EACF;AACF;","names":["context"]}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$meta": {
|
|
3
|
+
"package": "@walkeros/server-transformer-fingerprint",
|
|
4
|
+
"version": "3.0.0",
|
|
5
|
+
"type": "transformer",
|
|
6
|
+
"platform": "server",
|
|
7
|
+
"docs": "https://www.walkeros.io/docs/transformers/fingerprint",
|
|
8
|
+
"source": "https://github.com/elbwalker/walkerOS/tree/main/packages/server/transformers/fingerprint/src"
|
|
9
|
+
},
|
|
10
|
+
"schemas": {
|
|
11
|
+
"settings": {
|
|
12
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"fields": {
|
|
16
|
+
"type": "array",
|
|
17
|
+
"items": {
|
|
18
|
+
"anyOf": [
|
|
19
|
+
{
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Dot-notation path: \"ingest.ip\", \"event.data.userId\""
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"key": {
|
|
27
|
+
"description": "Source property path",
|
|
28
|
+
"type": "string"
|
|
29
|
+
},
|
|
30
|
+
"value": {
|
|
31
|
+
"description": "Static value or fallback"
|
|
32
|
+
},
|
|
33
|
+
"fn": {
|
|
34
|
+
"description": "$code: function for value transformation",
|
|
35
|
+
"type": "string"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"additionalProperties": false,
|
|
39
|
+
"description": "Mapping value config for computed fields"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
"description": "Fields to include in hash (order matters). Each resolved via getMappingValue with source { event, ingest }."
|
|
44
|
+
},
|
|
45
|
+
"output": {
|
|
46
|
+
"description": "Dot-notation path where hash is stored on the event. Default: \"user.hash\"",
|
|
47
|
+
"type": "string"
|
|
48
|
+
},
|
|
49
|
+
"length": {
|
|
50
|
+
"description": "Truncate hash to this length. Default: full 64-char SHA-256 hash",
|
|
51
|
+
"type": "integer",
|
|
52
|
+
"exclusiveMinimum": 0,
|
|
53
|
+
"maximum": 9007199254740991
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
"required": [
|
|
57
|
+
"fields"
|
|
58
|
+
],
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"description": "Fingerprint transformer: generates deterministic user hashes from event fields"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"examples": {
|
|
64
|
+
"step": {
|
|
65
|
+
"ipAnonymization": {
|
|
66
|
+
"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\"]",
|
|
67
|
+
"in": {
|
|
68
|
+
"name": "page view",
|
|
69
|
+
"data": {
|
|
70
|
+
"domain": "www.example.com",
|
|
71
|
+
"title": "Privacy Policy",
|
|
72
|
+
"id": "/privacy"
|
|
73
|
+
},
|
|
74
|
+
"id": "1700000602-gr0up-3",
|
|
75
|
+
"trigger": "load",
|
|
76
|
+
"entity": "page",
|
|
77
|
+
"action": "view",
|
|
78
|
+
"timestamp": 1700000602,
|
|
79
|
+
"group": "gr0up",
|
|
80
|
+
"count": 3,
|
|
81
|
+
"version": {
|
|
82
|
+
"tagging": 1
|
|
83
|
+
},
|
|
84
|
+
"source": {
|
|
85
|
+
"type": "server",
|
|
86
|
+
"id": "",
|
|
87
|
+
"previous_id": ""
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"out": {
|
|
91
|
+
"event": {
|
|
92
|
+
"name": "page view",
|
|
93
|
+
"data": {
|
|
94
|
+
"domain": "www.example.com",
|
|
95
|
+
"title": "Privacy Policy",
|
|
96
|
+
"id": "/privacy"
|
|
97
|
+
},
|
|
98
|
+
"user": {
|
|
99
|
+
"hash": "44d9154b9a9b3792"
|
|
100
|
+
},
|
|
101
|
+
"id": "1700000602-gr0up-3",
|
|
102
|
+
"trigger": "load",
|
|
103
|
+
"entity": "page",
|
|
104
|
+
"action": "view",
|
|
105
|
+
"timestamp": 1700000602,
|
|
106
|
+
"group": "gr0up",
|
|
107
|
+
"count": 3,
|
|
108
|
+
"version": {
|
|
109
|
+
"tagging": 1
|
|
110
|
+
},
|
|
111
|
+
"source": {
|
|
112
|
+
"type": "server",
|
|
113
|
+
"id": "",
|
|
114
|
+
"previous_id": ""
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"missingFields": {
|
|
120
|
+
"in": {
|
|
121
|
+
"name": "session start",
|
|
122
|
+
"data": {
|
|
123
|
+
"id": "s3ss10n"
|
|
124
|
+
},
|
|
125
|
+
"id": "1700000601-gr0up-2",
|
|
126
|
+
"trigger": "load",
|
|
127
|
+
"entity": "session",
|
|
128
|
+
"action": "start",
|
|
129
|
+
"timestamp": 1700000601,
|
|
130
|
+
"group": "gr0up",
|
|
131
|
+
"count": 2,
|
|
132
|
+
"version": {
|
|
133
|
+
"tagging": 1
|
|
134
|
+
},
|
|
135
|
+
"source": {
|
|
136
|
+
"type": "server",
|
|
137
|
+
"id": "",
|
|
138
|
+
"previous_id": ""
|
|
139
|
+
}
|
|
140
|
+
},
|
|
141
|
+
"out": {
|
|
142
|
+
"event": {
|
|
143
|
+
"name": "session start",
|
|
144
|
+
"data": {
|
|
145
|
+
"id": "s3ss10n"
|
|
146
|
+
},
|
|
147
|
+
"user": {
|
|
148
|
+
"hash": "e183220b699c10a8"
|
|
149
|
+
},
|
|
150
|
+
"id": "1700000601-gr0up-2",
|
|
151
|
+
"trigger": "load",
|
|
152
|
+
"entity": "session",
|
|
153
|
+
"action": "start",
|
|
154
|
+
"timestamp": 1700000601,
|
|
155
|
+
"group": "gr0up",
|
|
156
|
+
"count": 2,
|
|
157
|
+
"version": {
|
|
158
|
+
"tagging": 1
|
|
159
|
+
},
|
|
160
|
+
"source": {
|
|
161
|
+
"type": "server",
|
|
162
|
+
"id": "",
|
|
163
|
+
"previous_id": ""
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"serverFingerprint": {
|
|
169
|
+
"in": {
|
|
170
|
+
"name": "page view",
|
|
171
|
+
"data": {
|
|
172
|
+
"domain": "www.example.com",
|
|
173
|
+
"title": "Getting Started",
|
|
174
|
+
"id": "/docs/getting-started"
|
|
175
|
+
},
|
|
176
|
+
"id": "1700000600-gr0up-1",
|
|
177
|
+
"trigger": "load",
|
|
178
|
+
"entity": "page",
|
|
179
|
+
"action": "view",
|
|
180
|
+
"timestamp": 1700000600,
|
|
181
|
+
"group": "gr0up",
|
|
182
|
+
"count": 1,
|
|
183
|
+
"version": {
|
|
184
|
+
"tagging": 1
|
|
185
|
+
},
|
|
186
|
+
"source": {
|
|
187
|
+
"type": "server",
|
|
188
|
+
"id": "",
|
|
189
|
+
"previous_id": ""
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"out": {
|
|
193
|
+
"event": {
|
|
194
|
+
"name": "page view",
|
|
195
|
+
"data": {
|
|
196
|
+
"domain": "www.example.com",
|
|
197
|
+
"title": "Getting Started",
|
|
198
|
+
"id": "/docs/getting-started"
|
|
199
|
+
},
|
|
200
|
+
"user": {
|
|
201
|
+
"hash": "158f99cc06e33fd6"
|
|
202
|
+
},
|
|
203
|
+
"id": "1700000600-gr0up-1",
|
|
204
|
+
"trigger": "load",
|
|
205
|
+
"entity": "page",
|
|
206
|
+
"action": "view",
|
|
207
|
+
"timestamp": 1700000600,
|
|
208
|
+
"group": "gr0up",
|
|
209
|
+
"count": 1,
|
|
210
|
+
"version": {
|
|
211
|
+
"tagging": 1
|
|
212
|
+
},
|
|
213
|
+
"source": {
|
|
214
|
+
"type": "server",
|
|
215
|
+
"id": "",
|
|
216
|
+
"previous_id": ""
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
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": "3.0.
|
|
4
|
+
"version": "3.0.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.js",
|
|
7
7
|
"module": "./dist/index.mjs",
|
|
@@ -20,17 +20,14 @@
|
|
|
20
20
|
"build": "tsup --silent",
|
|
21
21
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
|
|
22
22
|
"dev": "jest --watchAll --colors",
|
|
23
|
-
"
|
|
23
|
+
"typecheck": "tsc --noEmit",
|
|
24
|
+
"lint": "eslint \"**/*.ts*\"",
|
|
24
25
|
"test": "jest",
|
|
25
26
|
"update": "npx npm-check-updates -u && npm update"
|
|
26
27
|
},
|
|
27
|
-
"peerDependencies": {
|
|
28
|
-
"@walkeros/core": "^0.8.0",
|
|
29
|
-
"@walkeros/server-core": "^0.8.0"
|
|
30
|
-
},
|
|
31
28
|
"devDependencies": {
|
|
32
|
-
"@walkeros/core": "0.
|
|
33
|
-
"@walkeros/server-core": "0.
|
|
29
|
+
"@walkeros/core": "^3.0.1",
|
|
30
|
+
"@walkeros/server-core": "^3.0.1"
|
|
34
31
|
},
|
|
35
32
|
"repository": {
|
|
36
33
|
"url": "git+https://github.com/elbwalker/walkerOS.git",
|
|
@@ -41,8 +38,12 @@
|
|
|
41
38
|
"bugs": {
|
|
42
39
|
"url": "https://github.com/elbwalker/walkerOS/issues"
|
|
43
40
|
},
|
|
41
|
+
"walkerOS": {
|
|
42
|
+
"type": "transformer",
|
|
43
|
+
"platform": "server",
|
|
44
|
+
"docs": "https://www.walkeros.io/docs/transformers/fingerprint"
|
|
45
|
+
},
|
|
44
46
|
"keywords": [
|
|
45
|
-
"walker",
|
|
46
47
|
"walkerOS",
|
|
47
48
|
"transformer",
|
|
48
49
|
"fingerprint",
|
|
@@ -54,5 +55,9 @@
|
|
|
54
55
|
"type": "GitHub Sponsors",
|
|
55
56
|
"url": "https://github.com/sponsors/elbwalker"
|
|
56
57
|
}
|
|
57
|
-
]
|
|
58
|
+
],
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@walkeros/core": "^3.0.1",
|
|
61
|
+
"@walkeros/server-core": "^3.0.1"
|
|
62
|
+
}
|
|
58
63
|
}
|