avo-inspector 2.2.2-alpha → 2.2.2-alpha.3

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.
Files changed (101) hide show
  1. package/.claude/settings.local.json +18 -0
  2. package/README.md +38 -3
  3. package/bin/avo-inspector.js +78 -26
  4. package/dist/AvoBatcher.d.ts +3 -12
  5. package/dist/AvoInspector.d.ts +13 -7
  6. package/dist/AvoNetworkCallsHandler.d.ts +28 -21
  7. package/dist/AvoSchemaParser.d.ts +2 -6
  8. package/dist/AvoStreamId.d.ts +58 -0
  9. package/dist/eventSpec/AvoEventSpecCache.d.ts +2 -1
  10. package/dist/eventSpec/AvoEventSpecFetchTypes.d.ts +103 -65
  11. package/dist/eventSpec/AvoEventSpecFetcher.d.ts +11 -5
  12. package/dist/eventSpec/EventValidator.d.ts +16 -72
  13. package/dist/eventSpec/fetcher.d.ts +52 -0
  14. package/dist/index.js +1 -1
  15. package/package.json +1 -1
  16. package/dist/browser.js.LICENSE.txt +0 -5
  17. package/dist-browser/AvoAnonymousId.d.ts +0 -26
  18. package/dist-browser/AvoBatcher.d.ts +0 -26
  19. package/dist-browser/AvoDeduplicator.d.ts +0 -20
  20. package/dist-browser/AvoEncryption.d.ts +0 -33
  21. package/dist-browser/AvoGuid.d.ts +0 -3
  22. package/dist-browser/AvoInspector.d.ts +0 -78
  23. package/dist-browser/AvoInspectorEnv.d.ts +0 -7
  24. package/dist-browser/AvoNetworkCallsHandler.d.ts +0 -74
  25. package/dist-browser/AvoSchemaParser.d.ts +0 -20
  26. package/dist-browser/AvoStorage.d.ts +0 -22
  27. package/dist-browser/__mocks__/xhr.d.ts +0 -12
  28. package/dist-browser/__mocks__/xhrError.d.ts +0 -12
  29. package/dist-browser/__tests__/AnonymousId_test.d.ts +0 -1
  30. package/dist-browser/__tests__/AvoEncryption_test.d.ts +0 -1
  31. package/dist-browser/__tests__/AvoInspectorEventSpec_test.d.ts +0 -1
  32. package/dist-browser/__tests__/AvoInspector_test.d.ts +0 -1
  33. package/dist-browser/__tests__/BatcherPublic_test.d.ts +0 -1
  34. package/dist-browser/__tests__/Batcher_test.d.ts +0 -1
  35. package/dist-browser/__tests__/Deduplicator_test.d.ts +0 -1
  36. package/dist-browser/__tests__/EncryptedPropertyTracking_test.d.ts +0 -1
  37. package/dist-browser/__tests__/EventSpecCache_test.d.ts +0 -1
  38. package/dist-browser/__tests__/EventSpecFetcher_test.d.ts +0 -1
  39. package/dist-browser/__tests__/EventValidator_test.d.ts +0 -1
  40. package/dist-browser/__tests__/NetworkCallsHandler_test.d.ts +0 -1
  41. package/dist-browser/__tests__/Parsing_test.d.ts +0 -1
  42. package/dist-browser/__tests__/Storage_test.d.ts +0 -1
  43. package/dist-browser/__tests__/ValidationIntegration_test.d.ts +0 -1
  44. package/dist-browser/__tests__/constants.d.ts +0 -36
  45. package/dist-browser/__tests__/helpers/encryptionHelpers.d.ts +0 -13
  46. package/dist-browser/__tests__/helpers/mockFactories.d.ts +0 -49
  47. package/dist-browser/eventSpec/AvoEventSpecCache.d.ts +0 -73
  48. package/dist-browser/eventSpec/AvoEventSpecFetchTypes.d.ts +0 -109
  49. package/dist-browser/eventSpec/AvoEventSpecFetcher.d.ts +0 -55
  50. package/dist-browser/eventSpec/EventValidator.d.ts +0 -90
  51. package/dist-browser/eventSpec/index.d.ts +0 -4
  52. package/dist-browser/index.d.ts +0 -2
  53. package/dist-browser/utils.d.ts +0 -3
  54. package/dist-native/AvoBatcher.d.ts +0 -24
  55. package/dist-native/AvoBatcher.js +0 -82
  56. package/dist-native/AvoDeduplicator.d.ts +0 -36
  57. package/dist-native/AvoDeduplicator.js +0 -142
  58. package/dist-native/AvoGuid.d.ts +0 -3
  59. package/dist-native/AvoGuid.js +0 -14
  60. package/dist-native/AvoInspector.d.ts +0 -52
  61. package/dist-native/AvoInspector.js +0 -220
  62. package/dist-native/AvoInspectorEnv.d.ts +0 -7
  63. package/dist-native/AvoInspectorEnv.js +0 -8
  64. package/dist-native/AvoInstallationId.d.ts +0 -5
  65. package/dist-native/AvoInstallationId.js +0 -36
  66. package/dist-native/AvoNetworkCallsHandler.d.ts +0 -48
  67. package/dist-native/AvoNetworkCallsHandler.js +0 -142
  68. package/dist-native/AvoSchemaParser.d.ts +0 -11
  69. package/dist-native/AvoSchemaParser.js +0 -95
  70. package/dist-native/AvoSessionTracker.d.ts +0 -15
  71. package/dist-native/AvoSessionTracker.js +0 -104
  72. package/dist-native/AvoStorage.d.ts +0 -22
  73. package/dist-native/AvoStorage.js +0 -336
  74. package/dist-native/__mocks__/xhr.d.ts +0 -12
  75. package/dist-native/__mocks__/xhr.js +0 -14
  76. package/dist-native/__mocks__/xhrError.d.ts +0 -12
  77. package/dist-native/__mocks__/xhrError.js +0 -14
  78. package/dist-native/__tests__/AvoInspector.d.ts +0 -1
  79. package/dist-native/__tests__/AvoInspector.js +0 -207
  80. package/dist-native/__tests__/Batcher.d.ts +0 -1
  81. package/dist-native/__tests__/Batcher.js +0 -280
  82. package/dist-native/__tests__/BatcherPublic.d.ts +0 -1
  83. package/dist-native/__tests__/BatcherPublic.js +0 -82
  84. package/dist-native/__tests__/Deduplicator.d.ts +0 -1
  85. package/dist-native/__tests__/Deduplicator.js +0 -111
  86. package/dist-native/__tests__/InstallationId.d.ts +0 -1
  87. package/dist-native/__tests__/InstallationId.js +0 -40
  88. package/dist-native/__tests__/NetworkCallsHandler.d.ts +0 -1
  89. package/dist-native/__tests__/NetworkCallsHandler.js +0 -132
  90. package/dist-native/__tests__/Parsing.d.ts +0 -1
  91. package/dist-native/__tests__/Parsing.js +0 -115
  92. package/dist-native/__tests__/Sessions.d.ts +0 -1
  93. package/dist-native/__tests__/Sessions.js +0 -179
  94. package/dist-native/__tests__/Storage.d.ts +0 -1
  95. package/dist-native/__tests__/Storage.js +0 -173
  96. package/dist-native/__tests__/constants.d.ts +0 -36
  97. package/dist-native/__tests__/constants.js +0 -47
  98. package/dist-native/index.d.ts +0 -2
  99. package/dist-native/index.js +0 -7
  100. package/dist-native/utils.d.ts +0 -3
  101. package/dist-native/utils.js +0 -42
@@ -4,98 +4,114 @@
4
4
  * changes directly to this file, and we'll apply them to the generator internally.
5
5
  */
6
6
  /**
7
- * Represents the type specification for a property.
8
- * Can be a primitive type or a nested object structure.
7
+ * Wire format - Property constraints with short field names.
8
+ * At most one constraint type will be present per property.
9
9
  */
10
- export interface PropertyTypeSpec {
11
- /** The type category: "primitive" for simple types, "object" for nested structures */
12
- type: "primitive" | "object";
13
- /** For primitive: the type name (e.g., "string", "int"). For object: nested property specs */
14
- value: string | Record<string, PropertySpec>;
10
+ export interface PropertyConstraintsWire {
11
+ /** Type name (for reference only, not validated) */
12
+ t: string;
13
+ /** Required flag (for reference only, not validated) */
14
+ r: boolean;
15
+ /** Pinned values: pinnedValue -> eventIds that require this exact value */
16
+ p?: Record<string, Array<string>>;
17
+ /** Allowed values: JSON array string -> eventIds that accept these values */
18
+ v?: Record<string, Array<string>>;
19
+ /** Regex patterns: pattern -> eventIds that require matching this regex */
20
+ rx?: Record<string, Array<string>>;
21
+ /** Min/max ranges: "min,max" -> eventIds that require value in this range */
22
+ minmax?: Record<string, Array<string>>;
23
+ /** Nested property constraints for object properties */
24
+ children?: Record<string, PropertyConstraintsWire>;
15
25
  }
16
26
  /**
17
- * Represents the specification for a single property in an event.
18
- * Supports recursive nesting for object types.
27
+ * Wire format - Event spec entry with short field names.
28
+ * A single event entry (base event + its variants).
29
+ * Multiple events can match the same name request due to name mapping.
19
30
  */
20
- export interface PropertySpec {
21
- /** Unique identifier for this property */
31
+ export interface EventSpecEntryWire {
32
+ /** Branch identifier */
33
+ b: string;
34
+ /** Base event ID */
22
35
  id: string;
23
- /** Type specification - contains type category and value */
24
- t: PropertyTypeSpec;
25
- /** Required flag */
26
- r: boolean;
27
- /** Is list (array) flag */
28
- l?: boolean;
29
- /** Minimum value (for numeric types) */
30
- min?: number;
31
- /** Maximum value (for numeric types) */
32
- max?: number;
33
- /** Enum values (allowed values for the property) */
34
- v?: string[];
35
- /** Regex pattern for string validation */
36
- rx?: string;
36
+ /** Variant IDs (baseEventId + variantIds = complete set) */
37
+ vids: Array<string>;
38
+ /** Property constraints keyed by property name */
39
+ p: Record<string, PropertyConstraintsWire>;
37
40
  }
38
41
  /**
39
- * Represents a variant of an event with additional or modified properties.
42
+ * Wire format - Response from getEventSpec endpoint.
43
+ * Contains array of events that match the requested name (due to name mapping).
40
44
  */
41
- export interface VariantSpec {
42
- /** Unique identifier for this variant */
43
- variantId: string;
44
- /** Event ID for this variant (base event id) */
45
- eventId: string;
46
- /** Suffix to append to the base event name */
47
- nameSuffix: string;
48
- /** Name of the variant in this source (if different from canonical name) */
49
- mappedName?: string;
50
- /** Properties specific to this variant */
51
- props: Record<string, PropertySpec>;
45
+ export interface EventSpecResponseWire {
46
+ /** Array of events matching the requested name */
47
+ events: Array<EventSpecEntryWire>;
48
+ /** Schema metadata (keeps long names - small, one per response) */
49
+ metadata: EventSpecMetadata;
52
50
  }
53
51
  /**
54
- * Represents the complete specification for an event, including base event
55
- * and optional variants.
52
+ * Internal - Property constraints with meaningful field names.
53
+ * At most one constraint type will be present per property.
56
54
  */
57
- export interface EventSpec {
58
- /** Unique identifier for this event */
59
- id: string;
60
- /** Canonical Avo name for this event */
61
- name: string;
62
- /** Name of the event in this source (if different from canonical name) */
63
- mappedName?: string;
64
- /** Properties for this event */
65
- props: Record<string, PropertySpec>;
66
- /** Variants of this event with additional/modified properties */
67
- variants: VariantSpec[];
55
+ export interface PropertyConstraints {
56
+ /** Type name (for reference only, not validated) */
57
+ type: string;
58
+ /** Required flag (for reference only, not validated) */
59
+ required: boolean;
60
+ /** Pinned values: pinnedValue -> eventIds that require this exact value */
61
+ pinnedValues?: Record<string, Array<string>>;
62
+ /** Allowed values: JSON array string -> eventIds that accept these values */
63
+ allowedValues?: Record<string, Array<string>>;
64
+ /** Regex patterns: pattern -> eventIds that require matching this regex */
65
+ regexPatterns?: Record<string, Array<string>>;
66
+ /** Min/max ranges: "min,max" -> eventIds that require value in this range */
67
+ minMaxRanges?: Record<string, Array<string>>;
68
+ /** Nested property constraints for object properties */
69
+ children?: Record<string, PropertyConstraints>;
70
+ }
71
+ /**
72
+ * Internal - Event spec entry with meaningful field names.
73
+ * A single event entry (base event + its variants).
74
+ */
75
+ export interface EventSpecEntry {
76
+ /** Branch identifier */
77
+ branchId: string;
78
+ /** Base event ID */
79
+ baseEventId: string;
80
+ /** Variant IDs (baseEventId + variantIds = complete set) */
81
+ variantIds: Array<string>;
82
+ /** Property constraints keyed by property name */
83
+ props: Record<string, PropertyConstraints>;
68
84
  }
69
85
  /**
70
- * Metadata returned with the event spec response.
86
+ * Internal - Parsed response from getEventSpec endpoint.
87
+ * Contains array of events that match the requested name (due to name mapping).
71
88
  */
89
+ export interface EventSpecResponse {
90
+ /** Array of events matching the requested name */
91
+ events: Array<EventSpecEntry>;
92
+ /** Schema metadata */
93
+ metadata: EventSpecMetadata;
94
+ }
95
+ /** Metadata returned with the event spec response. */
72
96
  export interface EventSpecMetadata {
73
97
  /** Schema identifier */
74
98
  schemaId: string;
75
99
  /** Branch identifier */
76
100
  branchId: string;
77
- /** Latest action identifier (replaces versionId/createdAt) */
101
+ /** Latest action identifier */
78
102
  latestActionId: string;
79
103
  /** Optional source identifier */
80
104
  sourceId?: string;
81
105
  }
82
- /**
83
- * Response structure from the getEventSpec endpoint.
84
- * Contains an array of potential event matches (due to name mapping).
85
- */
86
- export interface EventSpecResponse {
87
- /** Array of potential event matches */
88
- events: EventSpec[];
89
- /** Metadata about the schema and source */
90
- metadata: EventSpecMetadata;
91
- }
92
106
  /** Cache entry for storing event specs with metadata. */
93
107
  export interface EventSpecCacheEntry {
94
- /** The cached event specification response */
108
+ /** The cached event specification response (internal format) */
95
109
  spec: EventSpecResponse;
96
- /** Timestamp when this entry was cached */
110
+ /** Timestamp when this entry was cached (used for TTL expiration) */
97
111
  timestamp: number;
98
- /** Number of events processed since this entry was cached */
112
+ /** Timestamp when this entry was last accessed (used for LRU eviction) */
113
+ lastAccessed: number;
114
+ /** Number of cache hits since this entry was cached */
99
115
  eventCount: number;
100
116
  }
101
117
  /** Parameters for fetching event specifications from the API. */
@@ -107,3 +123,25 @@ export interface FetchEventSpecParams {
107
123
  /** The name of the event */
108
124
  eventName: string;
109
125
  }
126
+ /**
127
+ * Result of validating a single property.
128
+ * Contains either failedEventIds or passedEventIds (whichever is smaller for bandwidth).
129
+ */
130
+ export interface PropertyValidationResult {
131
+ /** Event/variant IDs that FAILED validation (present if smaller or equal to passed) */
132
+ failedEventIds?: Array<string>;
133
+ /** Event/variant IDs that PASSED validation (present if smaller than failed) */
134
+ passedEventIds?: Array<string>;
135
+ /** Nested validation results for child properties of object properties */
136
+ children?: Record<string, PropertyValidationResult>;
137
+ }
138
+ /**
139
+ * Result of validating all properties in an event.
140
+ * Maps property name to its validation result.
141
+ */
142
+ export interface ValidationResult {
143
+ /** Event spec metadata */
144
+ metadata: EventSpecMetadata | null;
145
+ /** Validation results per property */
146
+ propertyResults: Record<string, PropertyValidationResult>;
147
+ }
@@ -7,8 +7,8 @@ import type { EventSpecResponse, FetchEventSpecParams } from "./AvoEventSpecFetc
7
7
  /**
8
8
  * EventSpecFetcher handles fetching event specifications from the Avo API.
9
9
  *
10
- * Endpoint: GET /getEventSpec
11
- * Base URL: https://us-central1-avo-web-app.cloudfunctions.net
10
+ * Endpoint: GET /trackingPlan/eventSpec
11
+ * Base URL: https://api.avo.app
12
12
  */
13
13
  export declare class AvoEventSpecFetcher {
14
14
  /** Base URL for the event spec API */
@@ -34,7 +34,7 @@ export declare class AvoEventSpecFetcher {
34
34
  * - The request times out
35
35
  *
36
36
  * This method gracefully degrades - failures do not throw errors.
37
- * When null is returned, validation should be skipped for that event.
37
+ * When null is returned, Phase 2 should skip validation for that event.
38
38
  */
39
39
  fetch(params: FetchEventSpecParams): Promise<EventSpecResponse | null>;
40
40
  /** Internal fetch implementation. */
@@ -47,8 +47,14 @@ export declare class AvoEventSpecFetcher {
47
47
  */
48
48
  private makeRequest;
49
49
  /**
50
- * Basic shape check - ensures response has the minimum expected structure.
51
- * Does not perform deep validation of all fields.
50
+ * Basic shape check for wire format - ensures response has the minimum expected structure.
51
+ * Uses short field names from wire format.
52
52
  */
53
53
  private hasExpectedShape;
54
+ /** Parses the wire format response into internal format with meaningful field names. */
55
+ private static parseEventSpecResponse;
56
+ /** Parses a single event spec entry from wire format. */
57
+ private static parseEventSpecEntry;
58
+ /** Parses property constraints from wire format. */
59
+ private static parsePropertyConstraints;
54
60
  }
@@ -1,45 +1,16 @@
1
1
  /**
2
2
  * EventValidator - Client-side validation of tracking events against the Avo Tracking Plan.
3
3
  *
4
- * This module handles:
5
- * 1. Matching: Identifying the most likely Event and Variant from specs
6
- * 2. Validation: Checking runtime properties against the matched spec rules
7
- */
8
- import type { EventSpecResponse, EventSpec, EventSpecMetadata, VariantSpec } from "./AvoEventSpecFetchTypes";
9
- /**
10
- * Validation issue codes for client-side validation.
11
- */
12
- export type ValidationIssueCode = "RequiredMissing" | "ValueBelowMin" | "ValueAboveMax" | "RegexMismatch" | "NotInAllowedValues" | "UnexpectedProperty" | "UnexpectedEvent" | "TypeMismatch";
13
- /**
14
- * Represents a validation issue found during event validation.
4
+ * This module validates property values against constraints:
5
+ * - Pinned values (exact match required)
6
+ * - Allowed values (must be in list)
7
+ * - Regex patterns (must match pattern)
8
+ * - Min/max ranges (numeric values must be in range)
15
9
  *
16
- * Note: We do NOT include the received value to avoid sending user data to the backend.
17
- * The backend can correlate issues with encrypted values via propertyName matching
18
- * against eventProperties.encryptedPropertyValue in the payload.
10
+ * No schema validation (types/required) is performed - only value constraints.
11
+ * Validation runs against ALL events/variants in the response.
19
12
  */
20
- export interface ValidationIssue {
21
- /** The type of validation issue */
22
- code: ValidationIssueCode;
23
- /** Property ID (preferred over name) */
24
- propertyId?: string;
25
- /** Property name - used to correlate with encryptedPropertyValue in eventProperties */
26
- propertyName?: string;
27
- /** Expected value for the validation rule (from spec, not user data) */
28
- expected?: string | number | boolean;
29
- }
30
- /**
31
- * Result of the validation process.
32
- */
33
- export interface ValidationResult {
34
- /** ID of the matched event, null if no match found */
35
- eventId: string | null;
36
- /** ID of the matched variant, null if base event or no match */
37
- variantId: string | null;
38
- /** Event spec metadata from the response */
39
- eventSpecMetadata: EventSpecMetadata;
40
- /** List of all validation issues found */
41
- validationErrors: ValidationIssue[];
42
- }
13
+ import type { EventSpecResponse, ValidationResult } from "./AvoEventSpecFetchTypes";
43
14
  /**
44
15
  * Runtime property value - can be any JSON-compatible type
45
16
  */
@@ -49,42 +20,15 @@ export type RuntimePropertyValue = string | number | boolean | null | undefined
49
20
  */
50
21
  export type RuntimeProperties = Record<string, RuntimePropertyValue>;
51
22
  /**
52
- * Internal match result for scoring
53
- */
54
- interface MatchCandidate {
55
- event: EventSpec;
56
- variant: VariantSpec | null;
57
- score: number;
58
- }
59
- /**
60
- * Validates a runtime event against the EventSpecResponse.
23
+ * Validates runtime properties against all events in the EventSpecResponse.
24
+ *
25
+ * For each property:
26
+ * - If property not in spec: no validation needed (empty result)
27
+ * - If property in spec: check constraints and collect failed/passed eventIds
28
+ * - Return whichever list is smaller for bandwidth optimization
61
29
  *
62
- * @param eventName - The event name observed at runtime
63
30
  * @param properties - The properties observed at runtime
64
31
  * @param specResponse - The EventSpecResponse from the backend
65
- * @returns ValidationResult with match info and any validation errors
66
- */
67
- export declare function validateEvent(eventName: string, properties: RuntimeProperties, specResponse: EventSpecResponse): ValidationResult;
68
- /**
69
- * Finds the closest matching Event and Variant for the runtime data.
70
- *
71
- * @param eventName - Runtime event name
72
- * @param properties - Runtime properties
73
- * @param events - Array of EventSpecs to match against
74
- * @returns The best matching event and variant, or null if no match
75
- */
76
- export declare function findClosestMatch(eventName: string, properties: RuntimeProperties, events: EventSpec[]): MatchCandidate | null;
77
- /**
78
- * Validates runtime properties against the matched event and variant specs.
79
- *
80
- * @param properties - Runtime properties
81
- * @param event - Matched EventSpec
82
- * @param variant - Matched VariantSpec (or null for base event)
83
- * @returns Array of validation issues found
84
- */
85
- export declare function validateProperties(properties: RuntimeProperties, event: EventSpec, variant: VariantSpec | null): ValidationIssue[];
86
- /**
87
- * Quick check if an event exists in the spec (without full validation).
32
+ * @returns ValidationResult with baseEventId, metadata, and per-property results
88
33
  */
89
- export declare function eventExistsInSpec(eventName: string, specResponse: EventSpecResponse): boolean;
90
- export {};
34
+ export declare function validateEvent(properties: RuntimeProperties, specResponse: EventSpecResponse): ValidationResult;
@@ -0,0 +1,52 @@
1
+ import type { EventSpec, FetchEventSpecParams } from "./types";
2
+ /**
3
+ * EventSpecFetcher handles fetching event specifications from the Avo API.
4
+ *
5
+ * Endpoint: GET /getEventSpec
6
+ * Base URL: https://api.avo.app/inspector/v1
7
+ */
8
+ export declare class EventSpecFetcher {
9
+ /** Base URL for the event spec API */
10
+ private readonly baseUrl;
11
+ /** Network timeout in milliseconds */
12
+ private readonly timeout;
13
+ /** Whether to log debug information */
14
+ private readonly shouldLog;
15
+ /** In-flight requests to prevent duplicate fetches */
16
+ private inFlightRequests;
17
+ constructor(timeout?: number, shouldLog?: boolean, baseUrl?: string);
18
+ /**
19
+ * Generates a unique key for tracking in-flight requests.
20
+ */
21
+ private generateRequestKey;
22
+ /**
23
+ * Fetches an event specification from the API.
24
+ *
25
+ * Returns null if:
26
+ * - The network request fails
27
+ * - The response has an invalid status code (non-200)
28
+ * - The response is invalid or malformed
29
+ * - The request times out
30
+ *
31
+ * This method gracefully degrades - failures do not throw errors.
32
+ * When null is returned, Phase 2 should skip validation for that event.
33
+ */
34
+ fetch(params: FetchEventSpecParams): Promise<EventSpec | null>;
35
+ /**
36
+ * Internal fetch implementation.
37
+ */
38
+ private fetchInternal;
39
+ /**
40
+ * Builds the complete URL with query parameters.
41
+ */
42
+ private buildUrl;
43
+ /**
44
+ * Makes an HTTP GET request using XMLHttpRequest.
45
+ * Returns the parsed JSON response or null on failure.
46
+ */
47
+ private makeRequest;
48
+ /**
49
+ * Validates that the response matches the EventSpec structure.
50
+ */
51
+ private isValidEventSpec;
52
+ }