snowplow-tracker-core
Advanced tools
Comparing version 0.7.0-alpha.5 to 0.7.0
@@ -21,32 +21,62 @@ "use strict"; | ||
function getSchemaParts(input) { | ||
var re = new RegExp('^iglu:([a-zA-Z0-9-_]+|\.)\/([a-zA-Z0-9-_]+|\.)\/([a-zA-Z0-9-_]+|\.)\/([0-9]+-[0-9]+-[0-9]|\.)$'); | ||
var re = new RegExp('^iglu:([a-zA-Z0-9-_\.]+)\/([a-zA-Z0-9-_]+)\/jsonschema\/([1-9][0-9]*)\-(0|[1-9][0-9]*)\-(0|[1-9][0-9]*)$'); | ||
var matches = re.exec(input); | ||
if (matches !== null) { | ||
return matches.slice(1, 5); | ||
} | ||
if (matches !== null) | ||
return matches.slice(1, 6); | ||
return undefined; | ||
} | ||
exports.getSchemaParts = getSchemaParts; | ||
function isValidMatcher(input) { | ||
var schemaParts = getSchemaParts(input); | ||
if (schemaParts) { | ||
return schemaParts.length === 4; | ||
function validateVendorParts(parts) { | ||
if (parts[0] === '*' || parts[1] === '*') { | ||
return false; | ||
} | ||
if (parts.slice(2).length > 0) { | ||
var asterisk = false; | ||
for (var _i = 0, _a = parts.slice(2); _i < _a.length; _i++) { | ||
var part = _a[_i]; | ||
if (part === '*') | ||
asterisk = true; | ||
else if (asterisk) | ||
return false; | ||
} | ||
return true; | ||
} | ||
else if (parts.length == 2) | ||
return true; | ||
return false; | ||
} | ||
exports.isValidMatcher = isValidMatcher; | ||
function isStringArray(input) { | ||
if (Array.isArray(input)) { | ||
return input.every(function (i) { return typeof i === 'string'; }); | ||
exports.validateVendorParts = validateVendorParts; | ||
function validateVendor(input) { | ||
var parts = input.split('.'); | ||
if (parts && parts.length > 1) | ||
return validateVendorParts(parts); | ||
return false; | ||
} | ||
exports.validateVendor = validateVendor; | ||
function getRuleParts(input) { | ||
var re = new RegExp('^iglu:((?:(?:[a-zA-Z0-9-_]+|\\*)\.)+(?:[a-zA-Z0-9-_]+|\\*))\/([a-zA-Z0-9-_.]+|\\*)\/jsonschema\/([1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)$'); | ||
var matches = re.exec(input); | ||
if (matches !== null && validateVendor(matches[1])) | ||
return matches.slice(1, 6); | ||
return undefined; | ||
} | ||
exports.getRuleParts = getRuleParts; | ||
function isValidRule(input) { | ||
var ruleParts = getRuleParts(input); | ||
if (ruleParts) { | ||
var vendor = ruleParts[0]; | ||
return ruleParts.length === 5 && validateVendor(vendor); | ||
} | ||
return false; | ||
} | ||
exports.isValidRule = isValidRule; | ||
function isStringArray(input) { | ||
return Array.isArray(input) && input.every(function (x) { return typeof x === 'string'; }); | ||
} | ||
exports.isStringArray = isStringArray; | ||
function isValidRuleSetArg(input) { | ||
if (isStringArray(input)) { | ||
input.every(function (i) { return isValidMatcher(i); }); | ||
} | ||
else if (typeof input === 'string') { | ||
return isValidMatcher(input); | ||
} | ||
if (isStringArray(input)) | ||
return input.every(function (x) { return isValidRule(x); }); | ||
else if (typeof input === 'string') | ||
return isValidRule(input); | ||
return false; | ||
@@ -56,7 +86,5 @@ } | ||
function isSelfDescribingJson(input) { | ||
if (payload_1.isNonEmptyJson(input)) { | ||
if ('schema' in input && 'data' in input) { | ||
if (payload_1.isNonEmptyJson(input)) | ||
if ('schema' in input && 'data' in input) | ||
return (typeof (input.schema) === 'string' && typeof (input.data) === 'object'); | ||
} | ||
} | ||
return false; | ||
@@ -66,7 +94,4 @@ } | ||
function isEventJson(input) { | ||
if (payload_1.isNonEmptyJson(input)) { | ||
if ('e' in input) { | ||
return (typeof (input.e) === 'string'); | ||
} | ||
} | ||
if (payload_1.isNonEmptyJson(input) && ('e' in input)) | ||
return (typeof (input.e) === 'string'); | ||
return false; | ||
@@ -100,13 +125,7 @@ } | ||
function isContextGenerator(input) { | ||
if (typeof (input) === 'function') { | ||
return input.length === 3; | ||
} | ||
return false; | ||
return typeof (input) === 'function' && input.length <= 1; | ||
} | ||
exports.isContextGenerator = isContextGenerator; | ||
function isContextFilter(input) { | ||
if (typeof (input) === 'function') { | ||
return input.length === 3; | ||
} | ||
return false; | ||
return typeof (input) === 'function' && input.length <= 1; | ||
} | ||
@@ -118,3 +137,3 @@ exports.isContextFilter = isContextFilter; | ||
exports.isContextPrimitive = isContextPrimitive; | ||
function isFilterContextProvider(input) { | ||
function isFilterProvider(input) { | ||
if (Array.isArray(input)) { | ||
@@ -130,93 +149,122 @@ if (input.length === 2) { | ||
} | ||
exports.isFilterContextProvider = isFilterContextProvider; | ||
function isPathContextProvider(input) { | ||
exports.isFilterProvider = isFilterProvider; | ||
function isRuleSetProvider(input) { | ||
if (Array.isArray(input) && input.length === 2) { | ||
if (Array.isArray(input[1])) { | ||
return isRuleSet(input[0]) && every(input[1], isContextPrimitive); | ||
} | ||
return isRuleSet(input[0]) && isContextPrimitive(input[1]); | ||
if (!isRuleSet(input[0])) | ||
return false; | ||
if (Array.isArray(input[1])) | ||
return every(input[1], isContextPrimitive); | ||
return isContextPrimitive(input[1]); | ||
} | ||
return false; | ||
} | ||
exports.isPathContextProvider = isPathContextProvider; | ||
exports.isRuleSetProvider = isRuleSetProvider; | ||
function isConditionalContextProvider(input) { | ||
return isFilterContextProvider(input) || isPathContextProvider(input); | ||
return isFilterProvider(input) || isRuleSetProvider(input); | ||
} | ||
exports.isConditionalContextProvider = isConditionalContextProvider; | ||
function matchSchemaAgainstRule(rule, schema) { | ||
var ruleParts = getSchemaParts(rule); | ||
if (!isValidRule(rule)) | ||
return false; | ||
var ruleParts = getRuleParts(rule); | ||
var schemaParts = getSchemaParts(schema); | ||
if (ruleParts === undefined || schemaParts === undefined || | ||
ruleParts.length !== 4 || schemaParts.length !== 4) { | ||
return false; | ||
if (ruleParts && schemaParts) { | ||
if (!matchVendor(ruleParts[0], schemaParts[0])) | ||
return false; | ||
for (var i = 1; i < 5; i++) { | ||
if (!matchPart(ruleParts[i], schemaParts[i])) | ||
return false; | ||
} | ||
return true; | ||
} | ||
var matchCount = 0; | ||
for (var i = 0; i <= 3; i++) { | ||
if (ruleParts[0] === schemaParts[0] || ruleParts[0] === '.') { | ||
matchCount++; | ||
} | ||
else { | ||
return false; | ||
} | ||
exports.matchSchemaAgainstRule = matchSchemaAgainstRule; | ||
function matchVendor(rule, vendor) { | ||
var vendorParts = vendor.split('.'); | ||
var ruleParts = rule.split('.'); | ||
if (vendorParts && ruleParts) { | ||
if (vendorParts.length !== ruleParts.length) | ||
return false; | ||
for (var i = 0; i < ruleParts.length; i++) { | ||
if (!matchPart(vendorParts[i], ruleParts[i])) | ||
return false; | ||
} | ||
return true; | ||
} | ||
return matchCount === 4; | ||
return false; | ||
} | ||
exports.matchSchemaAgainstRule = matchSchemaAgainstRule; | ||
exports.matchVendor = matchVendor; | ||
function matchPart(rule, schema) { | ||
return (rule && schema && rule === '*' || rule === schema); | ||
} | ||
exports.matchPart = matchPart; | ||
function matchSchemaAgainstRuleSet(ruleSet, schema) { | ||
var matchCount = 0; | ||
var rejectCount = 0; | ||
var acceptCount = 0; | ||
var acceptRules = get(ruleSet, 'accept'); | ||
if (Array.isArray(acceptRules)) { | ||
if (!ruleSet.accept.every(function (rule) { return (matchSchemaAgainstRule(rule, schema)); })) { | ||
return false; | ||
if (ruleSet.accept.some(function (rule) { return (matchSchemaAgainstRule(rule, schema)); })) { | ||
acceptCount++; | ||
} | ||
matchCount++; | ||
} | ||
else if (typeof (acceptRules) === 'string') { | ||
if (!matchSchemaAgainstRule(acceptRules, schema)) { | ||
return false; | ||
if (matchSchemaAgainstRule(acceptRules, schema)) { | ||
acceptCount++; | ||
} | ||
matchCount++; | ||
} | ||
var rejectRules = get(ruleSet, 'reject'); | ||
if (Array.isArray(rejectRules)) { | ||
if (!ruleSet.reject.every(function (rule) { return (matchSchemaAgainstRule(rule, schema)); })) { | ||
return false; | ||
if (ruleSet.reject.some(function (rule) { return (matchSchemaAgainstRule(rule, schema)); })) { | ||
rejectCount++; | ||
} | ||
matchCount++; | ||
} | ||
else if (typeof (rejectRules) === 'string') { | ||
if (!matchSchemaAgainstRule(rejectRules, schema)) { | ||
return false; | ||
if (matchSchemaAgainstRule(rejectRules, schema)) { | ||
rejectCount++; | ||
} | ||
matchCount++; | ||
} | ||
return matchCount > 0; | ||
if (acceptCount > 0 && rejectCount === 0) { | ||
return true; | ||
} | ||
else if (acceptCount === 0 && rejectCount > 0) { | ||
return false; | ||
} | ||
return false; | ||
} | ||
exports.matchSchemaAgainstRuleSet = matchSchemaAgainstRuleSet; | ||
function getUsefulSchema(sb) { | ||
if (typeof get(sb, 'ue_px.data.schema') === 'string') { | ||
if (typeof get(sb, 'ue_px.data.schema') === 'string') | ||
return get(sb, 'ue_px.data.schema'); | ||
} | ||
else if (typeof get(sb, 'ue_pr.data.schema') === 'string') { | ||
else if (typeof get(sb, 'ue_pr.data.schema') === 'string') | ||
return get(sb, 'ue_pr.data.schema'); | ||
} | ||
else if (typeof get(sb, 'schema') === 'string') { | ||
else if (typeof get(sb, 'schema') === 'string') | ||
return get(sb, 'schema'); | ||
} | ||
return ''; | ||
} | ||
exports.getUsefulSchema = getUsefulSchema; | ||
function getDecodedEvent(sb) { | ||
var decodedEvent = __assign({}, sb); | ||
if (has(decodedEvent, 'ue_px')) { | ||
decodedEvent['ue_px'] = JSON.parse(base64_1.base64urldecode(get(decodedEvent, ['ue_px']))); | ||
try { | ||
if (has(decodedEvent, 'ue_px')) { | ||
decodedEvent['ue_px'] = JSON.parse(base64_1.base64urldecode(get(decodedEvent, ['ue_px']))); | ||
} | ||
} | ||
catch (e) { } | ||
return decodedEvent; | ||
} | ||
exports.getDecodedEvent = getDecodedEvent; | ||
function getEventType(sb) { | ||
return get(sb, 'e', ''); | ||
} | ||
exports.getEventType = getEventType; | ||
function buildGenerator(generator, event, eventType, eventSchema) { | ||
var contextGeneratorResult = undefined; | ||
try { | ||
contextGeneratorResult = generator(event, eventType, eventSchema); | ||
var args = { | ||
event: event, | ||
eventType: eventType, | ||
eventSchema: eventSchema | ||
}; | ||
contextGeneratorResult = generator(args); | ||
if (isSelfDescribingJson(contextGeneratorResult)) { | ||
@@ -237,2 +285,3 @@ return contextGeneratorResult; | ||
} | ||
exports.buildGenerator = buildGenerator; | ||
function normalizeToArray(input) { | ||
@@ -244,2 +293,3 @@ if (Array.isArray(input)) { | ||
} | ||
exports.normalizeToArray = normalizeToArray; | ||
function generatePrimitives(contextPrimitives, event, eventType, eventSchema) { | ||
@@ -256,2 +306,3 @@ var normalizedInputs = normalizeToArray(contextPrimitives); | ||
} | ||
exports.generatePrimitives = generatePrimitives; | ||
function evaluatePrimitive(contextPrimitive, event, eventType, eventSchema) { | ||
@@ -272,8 +323,14 @@ if (isSelfDescribingJson(contextPrimitive)) { | ||
} | ||
exports.evaluatePrimitive = evaluatePrimitive; | ||
function evaluateProvider(provider, event, eventType, eventSchema) { | ||
if (isFilterContextProvider(provider)) { | ||
if (isFilterProvider(provider)) { | ||
var filter = provider[0]; | ||
var filterResult = false; | ||
try { | ||
filterResult = filter(event, eventType, eventSchema); | ||
var args = { | ||
event: event, | ||
eventType: eventType, | ||
eventSchema: eventSchema | ||
}; | ||
filterResult = filter(args); | ||
} | ||
@@ -287,3 +344,3 @@ catch (error) { | ||
} | ||
else if (isPathContextProvider(provider)) { | ||
else if (isRuleSetProvider(provider)) { | ||
if (matchSchemaAgainstRuleSet(provider[0], eventSchema)) { | ||
@@ -295,2 +352,3 @@ return generatePrimitives(provider[1], event, eventType, eventSchema); | ||
} | ||
exports.evaluateProvider = evaluateProvider; | ||
function generateConditionals(providers, event, eventType, eventSchema) { | ||
@@ -307,2 +365,3 @@ var normalizedInput = normalizeToArray(providers); | ||
} | ||
exports.generateConditionals = generateConditionals; | ||
function contextModule() { | ||
@@ -322,2 +381,8 @@ var globalPrimitives = []; | ||
return { | ||
getGlobalPrimitives: function () { | ||
return globalPrimitives; | ||
}, | ||
getConditionalProviders: function () { | ||
return conditionalProviders; | ||
}, | ||
addGlobalContexts: function (contexts) { | ||
@@ -338,3 +403,3 @@ var acceptedConditionalContexts = []; | ||
}, | ||
clearAllContexts: function () { | ||
clearGlobalContexts: function () { | ||
conditionalProviders = []; | ||
@@ -341,0 +406,0 @@ globalPrimitives = []; |
@@ -0,1 +1,16 @@ | ||
/* | ||
* JavaScript tracker core for Snowplow: contexts.js | ||
* | ||
* Copyright (c) 2014-2018 Snowplow Analytics Ltd. All rights reserved. | ||
* | ||
* This program is licensed to you under the Apache License Version 2.0, | ||
* and you may not use this file except in compliance with the Apache License Version 2.0. | ||
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | ||
* | ||
* Unless required by applicable law or agreed to in writing, | ||
* software distributed under the Apache License Version 2.0 is distributed on an | ||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | ||
*/ | ||
import { PayloadData, isNonEmptyJson } from "./payload"; | ||
@@ -15,6 +30,30 @@ import { SelfDescribingJson } from "./core"; | ||
*/ | ||
export type ContextGenerator = (payload: SelfDescribingJson, eventType: string, schema: string) => SelfDescribingJson; | ||
/** | ||
* A context generator is a callback that returns a self-describing JSON | ||
* @param {Object} args - Object that contains: event, eventType, eventSchema | ||
* @return {SelfDescribingJson} A self-describing JSON | ||
*/ | ||
export type ContextGenerator = (args?: Object) => SelfDescribingJson; | ||
/** | ||
* A context primitive is either a self-describing JSON or a context generator | ||
*/ | ||
export type ContextPrimitive = SelfDescribingJson | ContextGenerator; | ||
export type ContextFilter = (payload: SelfDescribingJson, eventType: string, schema: string) => boolean; | ||
export type FilterContextProvider = [ContextFilter, Array<ContextPrimitive> | ContextPrimitive]; | ||
/** | ||
* A context filter is a user-supplied callback that is evaluated for each event | ||
* to determine if the context associated with the filter should be attached to the event | ||
*/ | ||
export type ContextFilter = (args?: Object) => boolean; | ||
/** | ||
* A filter provider is an array that has two parts: a context filter and context primitives | ||
* If the context filter evaluates to true, the tracker will attach the context primitive(s) | ||
*/ | ||
export type FilterProvider = [ContextFilter, Array<ContextPrimitive> | ContextPrimitive]; | ||
/** | ||
* A ruleset has accept or reject properties that contain rules for matching Iglu schema URIs | ||
*/ | ||
export interface RuleSet { | ||
@@ -24,34 +63,63 @@ accept?: string[] | string; | ||
} | ||
export type PathContextProvider = [RuleSet, Array<ContextPrimitive> | ContextPrimitive]; | ||
export type ConditionalContextProvider = FilterContextProvider | PathContextProvider; | ||
/** | ||
* A ruleset provider is an array that has two parts: a ruleset and context primitives | ||
* If the ruleset allows the current event schema URI, the tracker will attach the context primitive(s) | ||
*/ | ||
export type RuleSetProvider = [RuleSet, Array<ContextPrimitive> | ContextPrimitive]; | ||
/** | ||
* Conditional context providers are two element arrays used to decide when to attach contexts, where: | ||
* - the first element is some conditional criterion | ||
* - the second element is any number of context primitives | ||
*/ | ||
export type ConditionalContextProvider = FilterProvider | RuleSetProvider; | ||
export function getSchemaParts(input: string): Array<string> | undefined { | ||
let re = new RegExp('^iglu:([a-zA-Z0-9-_]+|\.)\/([a-zA-Z0-9-_]+|\.)\/([a-zA-Z0-9-_]+|\.)\/([0-9]+-[0-9]+-[0-9]|\.)$'); | ||
let re = new RegExp('^iglu:([a-zA-Z0-9-_\.]+)\/([a-zA-Z0-9-_]+)\/jsonschema\/([1-9][0-9]*)\-(0|[1-9][0-9]*)\-(0|[1-9][0-9]*)$'); | ||
let matches = re.exec(input); | ||
if (matches !== null) { | ||
return matches.slice(1, 5); | ||
} | ||
if (matches !== null) | ||
return matches.slice(1, 6); | ||
return undefined; | ||
} | ||
export function isValidMatcher(input: any): boolean { | ||
let schemaParts = getSchemaParts(input); | ||
if (schemaParts) { | ||
return schemaParts.length === 4; | ||
export function validateVendorParts(parts: Array<string>): boolean { | ||
if (parts[0] === '*' || parts[1] === '*') { | ||
return false; // no wildcard in first or second part | ||
} | ||
if (parts.slice(2).length > 0) { | ||
let asterisk = false; | ||
for (let part of parts.slice(2)) { | ||
if (part === '*') // mark when we've found a wildcard | ||
asterisk = true; | ||
else if (asterisk) // invalid if alpha parts come after wildcard | ||
return false; | ||
} | ||
return true; | ||
} else if (parts.length == 2) | ||
return true; | ||
return false; | ||
} | ||
export function isStringArray(input: any): boolean { | ||
if (Array.isArray(input)) { | ||
return input.every(function(i){ return typeof i === 'string' }); | ||
} | ||
export function validateVendor(input: string): boolean { | ||
let parts = input.split('.'); | ||
if (parts && parts.length > 1) | ||
return validateVendorParts(parts); | ||
return false; | ||
} | ||
export function isValidRuleSetArg(input: any): boolean{ | ||
if (isStringArray(input)) { | ||
input.every(function(i){ return isValidMatcher(i) }); | ||
} else if (typeof input === 'string') { | ||
return isValidMatcher(input); | ||
export function getRuleParts(input: string): Array<string> | undefined { | ||
const re = new RegExp('^iglu:((?:(?:[a-zA-Z0-9-_]+|\\*)\.)+(?:[a-zA-Z0-9-_]+|\\*))\/([a-zA-Z0-9-_.]+|\\*)\/jsonschema\/([1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)-(0|[1-9][0-9]*|\\*)$'); | ||
let matches = re.exec(input); | ||
if (matches !== null && validateVendor(matches[1])) | ||
return matches.slice(1,6); | ||
return undefined; | ||
} | ||
export function isValidRule(input: string): boolean { | ||
let ruleParts = getRuleParts(input); | ||
if (ruleParts) { | ||
let vendor = ruleParts[0]; | ||
return ruleParts.length === 5 && validateVendor(vendor); | ||
} | ||
@@ -61,8 +129,18 @@ return false; | ||
export function isStringArray(input: any): boolean { | ||
return Array.isArray(input) && input.every((x) => { return typeof x === 'string' }); | ||
} | ||
export function isValidRuleSetArg(input: any): boolean { | ||
if (isStringArray(input)) | ||
return input.every((x) => { return isValidRule(x) }); | ||
else if (typeof input === 'string') | ||
return isValidRule(input); | ||
return false; | ||
} | ||
export function isSelfDescribingJson(input: any) : boolean { | ||
if (isNonEmptyJson(input)) { | ||
if ('schema' in input && 'data' in input) { | ||
if (isNonEmptyJson(input)) | ||
if ('schema' in input && 'data' in input) | ||
return (typeof(input.schema) === 'string' && typeof(input.data) === 'object'); | ||
} | ||
} | ||
return false; | ||
@@ -72,7 +150,4 @@ } | ||
export function isEventJson(input: any) : boolean { | ||
if (isNonEmptyJson(input)) { | ||
if ('e' in input) { | ||
return (typeof(input.e) === 'string'); | ||
} | ||
} | ||
if (isNonEmptyJson(input) && ('e' in input)) | ||
return (typeof(input.e) === 'string'); | ||
return false; | ||
@@ -106,13 +181,7 @@ } | ||
export function isContextGenerator(input: any) : boolean { | ||
if (typeof(input) === 'function') { | ||
return input.length === 3; | ||
} | ||
return false; | ||
return typeof(input) === 'function' && input.length <= 1; | ||
} | ||
export function isContextFilter(input: any) : boolean { | ||
if (typeof(input) === 'function') { | ||
return input.length === 3; | ||
} | ||
return false; | ||
return typeof(input) === 'function' && input.length <= 1; | ||
} | ||
@@ -124,3 +193,3 @@ | ||
export function isFilterContextProvider(input: any) : boolean { | ||
export function isFilterProvider(input: any) : boolean { | ||
if (Array.isArray(input)) { | ||
@@ -137,8 +206,9 @@ if (input.length === 2) { | ||
export function isPathContextProvider(input: any) : boolean { | ||
export function isRuleSetProvider(input: any) : boolean { | ||
if (Array.isArray(input) && input.length === 2) { | ||
if (Array.isArray(input[1])) { | ||
return isRuleSet(input[0]) && every(input[1], isContextPrimitive); | ||
} | ||
return isRuleSet(input[0]) && isContextPrimitive(input[1]); | ||
if (!isRuleSet(input[0])) | ||
return false; | ||
if (Array.isArray(input[1])) | ||
return every(input[1], isContextPrimitive); | ||
return isContextPrimitive(input[1]); | ||
} | ||
@@ -149,36 +219,55 @@ return false; | ||
export function isConditionalContextProvider(input: any) : boolean { | ||
return isFilterContextProvider(input) || isPathContextProvider(input); | ||
return isFilterProvider(input) || isRuleSetProvider(input); | ||
} | ||
export function matchSchemaAgainstRule(rule: string, schema: string) : boolean { | ||
let ruleParts = getSchemaParts(rule); | ||
if (!isValidRule(rule)) | ||
return false; | ||
let ruleParts = getRuleParts(rule); | ||
let schemaParts = getSchemaParts(schema); | ||
if (ruleParts === undefined || schemaParts === undefined || | ||
ruleParts.length !== 4 || schemaParts.length !== 4) { | ||
return false; | ||
if (ruleParts && schemaParts) { | ||
if (!matchVendor(ruleParts[0], schemaParts[0])) | ||
return false; | ||
for (let i=1; i<5; i++) { | ||
if (!matchPart(ruleParts[i], schemaParts[i])) | ||
return false; | ||
} | ||
return true; // if it hasn't failed, it passes | ||
} | ||
let matchCount = 0; | ||
for (let i = 0; i <= 3; i++) { | ||
if (ruleParts[0] === schemaParts[0] || ruleParts[0] === '.') { | ||
matchCount++; | ||
} else { | ||
return false; | ||
} | ||
export function matchVendor(rule: string, vendor: string): boolean { | ||
// rule and vendor must have same number of elements | ||
let vendorParts = vendor.split('.'); | ||
let ruleParts = rule.split('.'); | ||
if (vendorParts && ruleParts) { | ||
if (vendorParts.length !== ruleParts.length) | ||
return false; | ||
for (let i=0; i<ruleParts.length; i++) { | ||
if (!matchPart(vendorParts[i], ruleParts[i])) | ||
return false; | ||
} | ||
return true; | ||
} | ||
return matchCount === 4; | ||
return false; | ||
} | ||
export function matchPart(rule: string, schema: string): boolean { | ||
// parts should be the string nested between slashes in the URI: /example/ | ||
return (rule && schema && rule === '*' || rule === schema); | ||
} | ||
export function matchSchemaAgainstRuleSet(ruleSet: RuleSet, schema: string) : boolean { | ||
let matchCount = 0; | ||
let rejectCount = 0; | ||
let acceptCount = 0; | ||
let acceptRules = get(ruleSet, 'accept'); | ||
if (Array.isArray(acceptRules)) { | ||
if (!(ruleSet.accept as Array<string>).every((rule) => (matchSchemaAgainstRule(rule, schema)))) { | ||
return false; | ||
if ((ruleSet.accept as Array<string>).some((rule) => (matchSchemaAgainstRule(rule, schema)))) { | ||
acceptCount++; | ||
} | ||
matchCount++; | ||
} else if (typeof(acceptRules) === 'string') { | ||
if (!matchSchemaAgainstRule(acceptRules, schema)) { | ||
return false; | ||
if (matchSchemaAgainstRule(acceptRules, schema)) { | ||
acceptCount++; | ||
} | ||
matchCount++; | ||
} | ||
@@ -188,13 +277,18 @@ | ||
if (Array.isArray(rejectRules)) { | ||
if (!(ruleSet.reject as Array<string>).every((rule) => (matchSchemaAgainstRule(rule, schema)))) { | ||
return false; | ||
if ((ruleSet.reject as Array<string>).some((rule) => (matchSchemaAgainstRule(rule, schema)))) { | ||
rejectCount++; | ||
} | ||
matchCount++; | ||
} else if (typeof(rejectRules) === 'string') { | ||
if (!matchSchemaAgainstRule(rejectRules, schema)) { | ||
return false; | ||
if (matchSchemaAgainstRule(rejectRules, schema)) { | ||
rejectCount++; | ||
} | ||
matchCount++; | ||
} | ||
return matchCount > 0; | ||
if (acceptCount > 0 && rejectCount === 0) { | ||
return true; | ||
} else if (acceptCount === 0 && rejectCount > 0) { | ||
return false; | ||
} | ||
return false; | ||
} | ||
@@ -207,26 +301,27 @@ | ||
// This doesn't decode ue_px, it works because it's called by code that has already decoded it | ||
function getUsefulSchema(sb: SelfDescribingJson): string { | ||
if (typeof get(sb, 'ue_px.data.schema') === 'string') { | ||
export function getUsefulSchema(sb: SelfDescribingJson): string { | ||
if (typeof get(sb, 'ue_px.data.schema') === 'string') | ||
return get(sb, 'ue_px.data.schema'); | ||
} else if (typeof get(sb, 'ue_pr.data.schema') === 'string') { | ||
else if (typeof get(sb, 'ue_pr.data.schema') === 'string') | ||
return get(sb, 'ue_pr.data.schema'); | ||
} else if (typeof get(sb, 'schema') === 'string') { | ||
else if (typeof get(sb, 'schema') === 'string') | ||
return get(sb, 'schema'); | ||
} | ||
return ''; | ||
} | ||
function getDecodedEvent(sb: SelfDescribingJson): SelfDescribingJson { | ||
export function getDecodedEvent(sb: SelfDescribingJson): SelfDescribingJson { | ||
let decodedEvent = {...sb}; // spread operator, instantiates new object | ||
if (has(decodedEvent, 'ue_px')) { | ||
decodedEvent['ue_px'] = JSON.parse(base64urldecode(get(decodedEvent, ['ue_px']))); | ||
} | ||
try { | ||
if (has(decodedEvent, 'ue_px')) { | ||
decodedEvent['ue_px'] = JSON.parse(base64urldecode(get(decodedEvent, ['ue_px']))); | ||
} | ||
} catch(e) {} | ||
return decodedEvent; | ||
} | ||
function getEventType(sb: {}): string { | ||
export function getEventType(sb: {}): string { | ||
return get(sb, 'e', ''); | ||
} | ||
function buildGenerator(generator: ContextGenerator, | ||
export function buildGenerator(generator: ContextGenerator, | ||
event: SelfDescribingJson, | ||
@@ -238,3 +333,8 @@ eventType: string, | ||
// try to evaluate context generator | ||
contextGeneratorResult = generator(event, eventType, eventSchema); | ||
let args = { | ||
event: event, | ||
eventType: eventType, | ||
eventSchema: eventSchema | ||
}; | ||
contextGeneratorResult = generator(args); | ||
// determine if the produced result is a valid SDJ | ||
@@ -254,3 +354,3 @@ if (isSelfDescribingJson(contextGeneratorResult)) { | ||
function normalizeToArray(input: any) : Array<any> { | ||
export function normalizeToArray(input: any) : Array<any> { | ||
if (Array.isArray(input)) { | ||
@@ -262,3 +362,3 @@ return input; | ||
function generatePrimitives(contextPrimitives: Array<ContextPrimitive> | ContextPrimitive, | ||
export function generatePrimitives(contextPrimitives: Array<ContextPrimitive> | ContextPrimitive, | ||
event: SelfDescribingJson, | ||
@@ -278,3 +378,3 @@ eventType: string, | ||
function evaluatePrimitive(contextPrimitive: ContextPrimitive, | ||
export function evaluatePrimitive(contextPrimitive: ContextPrimitive, | ||
event: SelfDescribingJson, | ||
@@ -296,11 +396,16 @@ eventType: string, | ||
function evaluateProvider(provider: ConditionalContextProvider, | ||
export function evaluateProvider(provider: ConditionalContextProvider, | ||
event: SelfDescribingJson, | ||
eventType: string, | ||
eventSchema: string): Array<SelfDescribingJson> { | ||
if (isFilterContextProvider(provider)) { | ||
let filter : ContextFilter = (provider as FilterContextProvider)[0]; | ||
if (isFilterProvider(provider)) { | ||
let filter : ContextFilter = (provider as FilterProvider)[0]; | ||
let filterResult = false; | ||
try { | ||
filterResult = filter(event, eventType, eventSchema); | ||
let args = { | ||
event: event, | ||
eventType: eventType, | ||
eventSchema: eventSchema | ||
}; | ||
filterResult = filter(args); | ||
} catch(error) { | ||
@@ -310,7 +415,7 @@ filterResult = false; | ||
if (filterResult === true) { | ||
return generatePrimitives((provider as FilterContextProvider)[1], event, eventType, eventSchema); | ||
return generatePrimitives((provider as FilterProvider)[1], event, eventType, eventSchema); | ||
} | ||
} else if (isPathContextProvider(provider)) { | ||
if (matchSchemaAgainstRuleSet((provider as PathContextProvider)[0], eventSchema)) { | ||
return generatePrimitives((provider as PathContextProvider)[1], event, eventType, eventSchema); | ||
} else if (isRuleSetProvider(provider)) { | ||
if (matchSchemaAgainstRuleSet((provider as RuleSetProvider)[0], eventSchema)) { | ||
return generatePrimitives((provider as RuleSetProvider)[1], event, eventType, eventSchema); | ||
} | ||
@@ -321,3 +426,3 @@ } | ||
function generateConditionals(providers: Array<ConditionalContextProvider> | ConditionalContextProvider, | ||
export function generateConditionals(providers: Array<ConditionalContextProvider> | ConditionalContextProvider, | ||
event: SelfDescribingJson, | ||
@@ -355,2 +460,10 @@ eventType: string, | ||
return { | ||
getGlobalPrimitives: function () { | ||
return globalPrimitives; | ||
}, | ||
getConditionalProviders: function () { | ||
return conditionalProviders; | ||
}, | ||
addGlobalContexts: function (contexts: Array<any>) { | ||
@@ -370,3 +483,3 @@ let acceptedConditionalContexts : ConditionalContextProvider[] = []; | ||
clearAllContexts: function () { | ||
clearGlobalContexts: function () { | ||
conditionalProviders = []; | ||
@@ -373,0 +486,0 @@ globalPrimitives = []; |
@@ -301,5 +301,12 @@ "use strict"; | ||
}, | ||
trackFormChange: function (formId, elementId, nodeName, type, elementClasses, value, context, tstamp) { | ||
trackFormFocusOrChange: function (schema, formId, elementId, nodeName, type, elementClasses, value, context, tstamp) { | ||
var event_schema = ''; | ||
if (schema === 'change_form') { | ||
event_schema = 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0'; | ||
} | ||
else if (schema === 'focus_form') { | ||
event_schema = 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0'; | ||
} | ||
return trackSelfDescribingEvent({ | ||
schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', | ||
schema: event_schema, | ||
data: removeEmptyProperties({ | ||
@@ -374,3 +381,3 @@ formId: formId, | ||
clearGlobalContexts: function () { | ||
contextModule.clearAllContexts(); | ||
contextModule.clearGlobalContexts(); | ||
}, | ||
@@ -377,0 +384,0 @@ removeGlobalContexts: function (contexts) { |
@@ -821,4 +821,5 @@ /* | ||
/** | ||
* Track the value of a form field changing | ||
* Track the value of a form field changing or receiving focus | ||
* | ||
* @param schema The schema type of the event | ||
* @param formId The parent form ID | ||
@@ -836,3 +837,4 @@ * @param elementId ID of the changed element | ||
*/ | ||
trackFormChange: function ( | ||
trackFormFocusOrChange: function ( | ||
schema: string, | ||
formId: string, | ||
@@ -847,4 +849,10 @@ elementId: string, | ||
let event_schema = ''; | ||
if (schema === 'change_form'){ | ||
event_schema = 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0'; | ||
} else if (schema === 'focus_form') { | ||
event_schema = 'iglu:com.snowplowanalytics.snowplow/focus_form/jsonschema/1-0-0'; | ||
} | ||
return trackSelfDescribingEvent({ | ||
schema: 'iglu:com.snowplowanalytics.snowplow/change_form/jsonschema/1-0-0', | ||
schema: event_schema, | ||
data: removeEmptyProperties({ | ||
@@ -1001,3 +1009,3 @@ formId: formId, | ||
clearGlobalContexts: function() { | ||
contextModule.clearAllContexts(); | ||
contextModule.clearGlobalContexts(); | ||
}, | ||
@@ -1004,0 +1012,0 @@ |
@@ -22,6 +22,6 @@ declare module 'snowplow-tracker/lib/base64' { | ||
import { SelfDescribingJson } from 'snowplow-tracker/lib/core'; | ||
export type ContextGenerator = (payload: SelfDescribingJson, eventType: string, schema: string) => SelfDescribingJson; | ||
export type ContextGenerator = (args?: Object) => SelfDescribingJson; | ||
export type ContextPrimitive = SelfDescribingJson | ContextGenerator; | ||
export type ContextFilter = (payload: SelfDescribingJson, eventType: string, schema: string) => boolean; | ||
export type FilterContextProvider = [ContextFilter, Array<ContextPrimitive> | ContextPrimitive]; | ||
export type ContextFilter = (args?: Object) => boolean; | ||
export type FilterProvider = [ContextFilter, Array<ContextPrimitive> | ContextPrimitive]; | ||
export interface RuleSet { | ||
@@ -31,6 +31,9 @@ accept?: string[] | string; | ||
} | ||
export type PathContextProvider = [RuleSet, Array<ContextPrimitive> | ContextPrimitive]; | ||
export type ConditionalContextProvider = FilterContextProvider | PathContextProvider; | ||
export type RuleSetProvider = [RuleSet, Array<ContextPrimitive> | ContextPrimitive]; | ||
export type ConditionalContextProvider = FilterProvider | RuleSetProvider; | ||
export function getSchemaParts(input: string): Array<string> | undefined; | ||
export function isValidMatcher(input: any): boolean; | ||
export function validateVendorParts(parts: Array<string>): boolean; | ||
export function validateVendor(input: string): boolean; | ||
export function getRuleParts(input: string): Array<string> | undefined; | ||
export function isValidRule(input: string): boolean; | ||
export function isStringArray(input: any): boolean; | ||
@@ -44,10 +47,23 @@ export function isValidRuleSetArg(input: any): boolean; | ||
export function isContextPrimitive(input: any): boolean; | ||
export function isFilterContextProvider(input: any): boolean; | ||
export function isPathContextProvider(input: any): boolean; | ||
export function isFilterProvider(input: any): boolean; | ||
export function isRuleSetProvider(input: any): boolean; | ||
export function isConditionalContextProvider(input: any): boolean; | ||
export function matchSchemaAgainstRule(rule: string, schema: string): boolean; | ||
export function matchVendor(rule: string, vendor: string): boolean; | ||
export function matchPart(rule: string, schema: string): boolean; | ||
export function matchSchemaAgainstRuleSet(ruleSet: RuleSet, schema: string): boolean; | ||
export function getUsefulSchema(sb: SelfDescribingJson): string; | ||
export function getDecodedEvent(sb: SelfDescribingJson): SelfDescribingJson; | ||
export function getEventType(sb: {}): string; | ||
export function buildGenerator(generator: ContextGenerator, event: SelfDescribingJson, eventType: string, eventSchema: string): SelfDescribingJson | Array<SelfDescribingJson> | undefined; | ||
export function normalizeToArray(input: any): Array<any>; | ||
export function generatePrimitives(contextPrimitives: Array<ContextPrimitive> | ContextPrimitive, event: SelfDescribingJson, eventType: string, eventSchema: string): Array<SelfDescribingJson>; | ||
export function evaluatePrimitive(contextPrimitive: ContextPrimitive, event: SelfDescribingJson, eventType: string, eventSchema: string): Array<SelfDescribingJson> | undefined; | ||
export function evaluateProvider(provider: ConditionalContextProvider, event: SelfDescribingJson, eventType: string, eventSchema: string): Array<SelfDescribingJson>; | ||
export function generateConditionals(providers: Array<ConditionalContextProvider> | ConditionalContextProvider, event: SelfDescribingJson, eventType: string, eventSchema: string): Array<SelfDescribingJson>; | ||
export function contextModule(): { | ||
getGlobalPrimitives: () => ContextPrimitive[]; | ||
getConditionalProviders: () => ConditionalContextProvider[]; | ||
addGlobalContexts: (contexts: any[]) => void; | ||
clearAllContexts: () => void; | ||
clearGlobalContexts: () => void; | ||
removeGlobalContexts: (contexts: any[]) => void; | ||
@@ -104,3 +120,3 @@ getApplicableContexts: (event: PayloadData) => SelfDescribingJson[]; | ||
trackRemoveFromCart: (sku: string, name: string, category: string, unitPrice: string, quantity: string, currency?: string | undefined, context?: SelfDescribingJson[] | undefined, tstamp?: number | TrueTimestamp | DeviceTimestamp | undefined) => payload.PayloadData; | ||
trackFormChange: (formId: string, elementId: string, nodeName: string, type: string, elementClasses: string[], value: string, context?: SelfDescribingJson[] | undefined, tstamp?: number | TrueTimestamp | DeviceTimestamp | undefined) => payload.PayloadData; | ||
trackFormFocusOrChange: (schema: string, formId: string, elementId: string, nodeName: string, type: string, elementClasses: string[], value: string, context?: SelfDescribingJson[] | undefined, tstamp?: number | TrueTimestamp | DeviceTimestamp | undefined) => payload.PayloadData; | ||
trackFormSubmission: (formId: string, formClasses: string[], elements: string[], context?: SelfDescribingJson[] | undefined, tstamp?: number | TrueTimestamp | DeviceTimestamp | undefined) => payload.PayloadData; | ||
@@ -107,0 +123,0 @@ trackSiteSearch: (terms: string[], filters: Object, totalResults: number, pageResults: number, context?: SelfDescribingJson[] | undefined, tstamp?: number | TrueTimestamp | DeviceTimestamp | undefined) => payload.PayloadData; |
{ | ||
"name": "snowplow-tracker-core", | ||
"version": "0.7.0-alpha.5", | ||
"version": "0.7.0", | ||
"devDependencies": { | ||
@@ -5,0 +5,0 @@ "@types/es6-shim": "0.31.34", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Unidentified License
License(Experimental) Something that seems like a license was found, but its contents could not be matched with a known license.
Found 1 instance in 1 package
155172
2738
28
3
1