@solid-analytics/babel-plugin 1.0.0-alpha.0

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/README.md ADDED
@@ -0,0 +1,160 @@
1
+ # @solid-analytics/babel-plugin
2
+
3
+ Babel plugin for transforming analytics directives in SolidJS applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add -D @solid-analytics/babel-plugin
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### With Babel
14
+
15
+ ```js
16
+ // babel.config.js
17
+ module.exports = {
18
+ plugins: [
19
+ ['@solid-analytics/babel-plugin', {
20
+ runtimeImport: '@solid-analytics/solid',
21
+ prefix: 'analytics',
22
+ debug: false,
23
+ validate: true,
24
+ sanitize: true,
25
+ warnPII: true
26
+ }]
27
+ ]
28
+ }
29
+ ```
30
+
31
+ ### With Vite
32
+
33
+ Use the Vite plugin wrapper instead:
34
+
35
+ ```bash
36
+ pnpm add -D @solid-analytics/vite-plugin
37
+ ```
38
+
39
+ ```ts
40
+ // vite.config.ts
41
+ import { defineConfig } from 'vite'
42
+ import solidAnalytics from '@solid-analytics/vite-plugin'
43
+
44
+ export default defineConfig({
45
+ plugins: [
46
+ solidAnalytics({
47
+ debug: true
48
+ })
49
+ ]
50
+ })
51
+ ```
52
+
53
+ ## What It Does
54
+
55
+ Transforms analytics directives into event handlers at build time:
56
+
57
+ ### Input
58
+
59
+ ```tsx
60
+ <button analytics:click="button_clicked">
61
+ Click Me
62
+ </button>
63
+ ```
64
+
65
+ ### Output
66
+
67
+ ```tsx
68
+ <button onClick={(e) => __analytics.track('button_clicked', undefined, e)}>
69
+ Click Me
70
+ </button>
71
+ ```
72
+
73
+ ## Supported Directives
74
+
75
+ ### Event Directives
76
+ - `analytics:click`
77
+ - `analytics:submit`
78
+ - `analytics:focus`
79
+ - `analytics:blur`
80
+ - `analytics:change`
81
+ - `analytics:hover`
82
+ - `analytics:scroll`
83
+ - `analytics:input`
84
+ - `analytics:keydown`
85
+ - `analytics:keyup`
86
+ - `analytics:mouseenter`
87
+ - `analytics:mouseleave`
88
+ - `analytics:touchstart`
89
+ - `analytics:touchend`
90
+
91
+ ### Special Directives
92
+ - `analytics:visible` - Intersection Observer
93
+ - `analytics:identify` - User identification
94
+ - `analytics:page` - Page tracking
95
+ - `analytics:track` - Generic tracking
96
+
97
+ ## Options
98
+
99
+ ### `runtimeImport`
100
+ - Type: `string`
101
+ - Default: `'@solid-analytics/solid'`
102
+ - The module to import the runtime from
103
+
104
+ ### `prefix`
105
+ - Type: `string`
106
+ - Default: `'analytics'`
107
+ - The directive prefix (e.g., `analytics:click`)
108
+
109
+ ### `debug`
110
+ - Type: `boolean`
111
+ - Default: `false`
112
+ - Enable debug logging during transformation
113
+
114
+ ### `validate`
115
+ - Type: `boolean`
116
+ - Default: `true`
117
+ - Validate directives at build time
118
+
119
+ ### `sanitize`
120
+ - Type: `boolean`
121
+ - Default: `true`
122
+ - Sanitize event names (lowercase, underscores)
123
+
124
+ ### `warnPII`
125
+ - Type: `boolean`
126
+ - Default: `true`
127
+ - Warn about potential PII in payloads
128
+
129
+ ## Build-Time Validation
130
+
131
+ The plugin validates directives at build time:
132
+
133
+ ```tsx
134
+ // ✅ Valid
135
+ <button analytics:click="button_clicked">Click</button>
136
+
137
+ // ❌ Invalid - wrong element
138
+ <div analytics:submit="form_submitted">Submit</div>
139
+
140
+ // ⚠️ Warning - potential PII
141
+ <input analytics:change={["input_changed", { password: value }]} />
142
+ ```
143
+
144
+ ## Features
145
+
146
+ - **Zero Runtime Overhead** - Transformations happen at build time
147
+ - **Type Safety** - TypeScript definitions for all directives
148
+ - **Build-Time Validation** - Catch errors before runtime
149
+ - **PII Detection** - Warns about potential sensitive data
150
+ - **Event Sanitization** - Automatic event name normalization
151
+
152
+ ## Documentation
153
+
154
+ - [Main Documentation](../../README.md)
155
+ - [Vite Plugin](../vite-plugin/README.md)
156
+ - [Configuration](../../CONFIGURATION.md)
157
+
158
+ ## License
159
+
160
+ MIT
@@ -0,0 +1,23 @@
1
+ import { PluginObj } from '@babel/core';
2
+ import { PluginPass } from '@babel/core';
3
+ import * as t from '@babel/types';
4
+
5
+ declare const _default: (api: object, options: PluginOptions | null | undefined, dirname: string) => PluginObj<PluginState>;
6
+ export default _default;
7
+
8
+ declare interface PluginOptions {
9
+ runtimeImport?: string;
10
+ prefix?: string;
11
+ debug?: boolean;
12
+ validate?: boolean;
13
+ sanitize?: boolean;
14
+ warnPII?: boolean;
15
+ }
16
+
17
+ declare interface PluginState extends PluginPass {
18
+ opts: PluginOptions;
19
+ runtimeImportAdded?: boolean;
20
+ runtimeIdentifier?: t.Identifier;
21
+ }
22
+
23
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";const k=require("@babel/helper-plugin-utils"),v=require("@babel/types");function w(t){const i=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const n in t)if(n!=="default"){const s=Object.getOwnPropertyDescriptor(t,n);Object.defineProperty(i,n,s.get?s:{enumerable:!0,get:()=>t[n]})}}return i.default=t,Object.freeze(i)}const e=w(v);function j(t){const i=["click","submit","focus","blur","change","hover","scroll","visible","identify","page","track","input","keydown","keyup","keypress","mouseenter","mouseleave","mousedown","mouseup","touchstart","touchend","touchmove"];return i.includes(t)?null:{message:`Unknown analytics directive: "analytics:${t}". Valid directives: ${i.join(", ")}`}}function $(t,i){if(typeof t=="string"){if(t.trim().length===0)return{message:`Event name cannot be empty for analytics:${i}`};if(/\s/.test(t))return{message:`Event name "${t}" contains spaces. Did you mean to use underscores?`};/[A-Z]/.test(t)&&!/^[A-Z_]+$/.test(t)&&console.warn(`[babel-plugin] Event name "${t}" uses camelCase. Consider using snake_case for consistency.`)}return null}function A(t,i){if(e.isIdentifier(t)){const n=t.name;if(n==="undefined"||n==="null")return{message:`Invalid payload value "${n}" for analytics:${i}. Use undefined or omit the payload instead.`}}return e.isObjectExpression(t)&&C(t)?{message:`Duplicate keys in payload object for analytics:${i}`}:null}function C(t){const i=new Set;for(const n of t.properties)if(e.isObjectProperty(n)&&e.isIdentifier(n.key)){const s=n.key.name;if(i.has(s))return!0;i.add(s)}return!1}function S(t,i){const s={submit:["form"],change:["input","select","textarea"],input:["input","textarea"],focus:["input","textarea","select","button","a"],blur:["input","textarea","select","button","a"]}[t];return s&&!s.includes(i.toLowerCase())?{message:`analytics:${t} should only be used on ${s.join(", ")} elements, but found on <${i}>`}:null}function _(t,i){if(t==="identify"){if(e.isStringLiteral(i))return{message:"analytics:identify requires tuple syntax: [userId, traits]"};if(e.isJSXExpressionContainer(i)){const n=i.expression;if(e.isArrayExpression(n)){if(n.elements.length<1)return{message:"analytics:identify requires at least userId: [userId, traits?]"};if(n.elements.length>2)return{message:"analytics:identify takes exactly 2 arguments: [userId, traits?]"}}else return{message:"analytics:identify must be an array: [userId, traits?]"}}}return null}function x(t){return t.replace(/[^\w\s\-_.]/g,"").trim()}function D(t){const i=[];if(e.isObjectExpression(t)){const n=["password","ssn","credit","card","cvv","pin"];for(const s of t.properties)if(e.isObjectProperty(s)&&e.isIdentifier(s.key)){const a=s.key.name.toLowerCase();n.some(o=>a.includes(o))&&i.push(`Potential PII detected in payload key "${s.key.name}". Consider anonymizing this data.`)}}return i}const P={click:"onClick",submit:"onSubmit",focus:"onFocus",blur:"onBlur",change:"onChange",hover:"onMouseEnter",scroll:"onScroll",input:"onInput",keydown:"onKeyDown",keyup:"onKeyUp",keypress:"onKeyPress",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",mousedown:"onMouseDown",mouseup:"onMouseUp",touchstart:"onTouchStart",touchend:"onTouchEnd",touchmove:"onTouchMove"},L=["visible","identify","page","track"],O=k.declare((t,i)=>{t.assertVersion(7);const n=i.runtimeImport||"@solid-analytics/runtime",s=i.prefix||"analytics",a=i.debug||!1,o=i.validate!==!1,r=i.sanitize!==!1,m=i.warnPII!==!1;return{name:"@solid-analytics/babel-plugin",visitor:{Program:{enter(d,c){c.runtimeImportAdded=!1,c.runtimeIdentifier=void 0}},JSXElement(d,c){const y=d.node.openingElement,g=y.attributes,l=e.isJSXIdentifier(y.name)?y.name.name:"Unknown",p=[];if(g.forEach(u=>{if(e.isJSXAttribute(u)&&e.isJSXNamespacedName(u.name)){const f=u.name.namespace.name,b=u.name.name.name;f===s&&p.push({attr:u,directive:b})}}),p.length!==0){c.runtimeImportAdded||T(d,c,n);for(const{attr:u,directive:f}of p){if(a&&console.log(`[babel-plugin] Found directive: ${s}:${f}`),o){const b=j(f);if(b)throw d.buildCodeFrameError(b.message);const E=S(f,l);E&&console.warn(`[babel-plugin] ${E.message}`);const h=_(f,u.value);if(h)throw d.buildCodeFrameError(h.message)}z(y,u,f,c,{debug:a,validate:o,sanitize:r,warnPII:m})}}}}}});function T(t,i,n){const s=t.findParent(o=>o.isProgram());if(!s)return;const a=e.importDeclaration([e.importSpecifier(e.identifier("__analytics"),e.identifier("__analytics"))],e.stringLiteral(n));s.unshiftContainer("body",a),i.runtimeImportAdded=!0,i.runtimeIdentifier=e.identifier("__analytics")}function z(t,i,n,s,a){const o=i.value;let r,m=null;if(e.isStringLiteral(o)){if(r=o.value,a.validate){const l=$(r,n);l&&console.warn(`[babel-plugin] ${l.message}`)}a.sanitize&&typeof r=="string"&&(r=x(r))}else if(e.isJSXExpressionContainer(o)){const l=o.expression;if(e.isArrayExpression(l)){const[p,u]=l.elements;if(p&&e.isStringLiteral(p))r=p.value,a.sanitize&&(r=x(r));else if(p&&e.isExpression(p))r=p;else throw new Error(`Invalid event name in analytics:${n}`);if(u&&e.isExpression(u)){if(m=u,a.validate){const f=A(m,n);f&&console.warn(`[babel-plugin] ${f.message}`)}a.warnPII&&D(m).forEach(b=>{console.warn(`[babel-plugin] ${b}`)})}}else if(e.isStringLiteral(l))r=l.value,a.sanitize&&(r=x(r));else if(e.isExpression(l))r=l;else throw new Error(`Invalid value for analytics:${n}`)}else throw new Error(`Invalid value for analytics:${n}`);const d=t.attributes.indexOf(i);if(d!==-1&&t.attributes.splice(d,1),L.includes(n)){M(t,n,r,m,s,a.debug);return}const c=P[n];if(!c&&a.validate)throw new Error(`Unknown analytics directive: ${n}`);if(!c)return;const y=I(n,r,m,s),g=e.jsxAttribute(e.jsxIdentifier(c),e.jsxExpressionContainer(y));t.attributes.push(g),a.debug&&console.log(`[babel-plugin] Transformed ${n} -> ${c}`)}function I(t,i,n,s,a){const o=s.runtimeIdentifier||e.identifier("__analytics"),r=e.callExpression(e.memberExpression(o,e.identifier("track")),[typeof i=="string"?e.stringLiteral(i):i,n||e.identifier("undefined"),e.identifier("e")]);return e.arrowFunctionExpression([e.identifier("e")],r)}function M(t,i,n,s,a,o){switch(i){case"visible":const r=e.jsxAttribute(e.jsxIdentifier("data-analytics-visible"),e.stringLiteral(typeof n=="string"?n:JSON.stringify({dynamic:!0})));if(t.attributes.push(r),s){const g=e.jsxAttribute(e.jsxIdentifier("data-analytics-visible-payload"),e.jsxExpressionContainer(s));t.attributes.push(g)}break;case"identify":const m=e.jsxAttribute(e.jsxIdentifier("data-analytics-identify"),e.jsxExpressionContainer(e.arrayExpression([typeof n=="string"?e.stringLiteral(n):n,s||e.identifier("undefined")])));t.attributes.push(m);break;case"page":const d=e.jsxAttribute(e.jsxIdentifier("data-analytics-page"),e.jsxExpressionContainer(e.arrayExpression([typeof n=="string"?e.stringLiteral(n):n,s||e.identifier("undefined")])));t.attributes.push(d);break;case"track":const c=I("track",n,s,a),y=e.jsxAttribute(e.jsxIdentifier("onClick"),e.jsxExpressionContainer(c));t.attributes.push(y);break}o&&console.log(`[babel-plugin] Handled special directive: ${i}`)}module.exports=O;
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/validation.ts","../src/index.ts"],"sourcesContent":["/**\n * Validation utilities for analytics directives\n */\n\nimport * as t from \"@babel/types\";\n\nexport interface ValidationError {\n message: string;\n loc?: {\n line: number;\n column: number;\n };\n}\n\n/**\n * Validate directive name\n */\nexport function validateDirective(directive: string): ValidationError | null {\n const validDirectives = [\n \"click\",\n \"submit\",\n \"focus\",\n \"blur\",\n \"change\",\n \"hover\",\n \"scroll\",\n \"visible\",\n \"identify\",\n \"page\",\n \"track\",\n \"input\",\n \"keydown\",\n \"keyup\",\n \"keypress\",\n \"mouseenter\",\n \"mouseleave\",\n \"mousedown\",\n \"mouseup\",\n \"touchstart\",\n \"touchend\",\n \"touchmove\",\n ];\n\n if (!validDirectives.includes(directive)) {\n return {\n message: `Unknown analytics directive: \"analytics:${directive}\". Valid directives: ${validDirectives.join(\n \", \"\n )}`,\n };\n }\n\n return null;\n}\n\n/**\n * Validate event name\n */\nexport function validateEventName(\n eventName: string | t.Expression,\n directive: string\n): ValidationError | null {\n if (typeof eventName === \"string\") {\n // String event names\n if (eventName.trim().length === 0) {\n return {\n message: `Event name cannot be empty for analytics:${directive}`,\n };\n }\n\n // Warn about potential typos (spaces, special characters)\n if (/\\s/.test(eventName)) {\n return {\n message: `Event name \"${eventName}\" contains spaces. Did you mean to use underscores?`,\n };\n }\n\n // Recommend snake_case\n if (/[A-Z]/.test(eventName) && !/^[A-Z_]+$/.test(eventName)) {\n // Has mixed case but not all caps (which might be intentional)\n console.warn(\n `[babel-plugin] Event name \"${eventName}\" uses camelCase. Consider using snake_case for consistency.`\n );\n }\n }\n\n return null;\n}\n\n/**\n * Validate payload structure\n */\nexport function validatePayload(\n payload: t.Expression,\n directive: string\n): ValidationError | null {\n // Check for common mistakes\n if (t.isIdentifier(payload)) {\n const name = payload.name;\n if (name === \"undefined\" || name === \"null\") {\n return {\n message: `Invalid payload value \"${name}\" for analytics:${directive}. Use undefined or omit the payload instead.`,\n };\n }\n }\n\n // Validate object expression structure\n if (t.isObjectExpression(payload)) {\n const hasDuplicateKeys = checkDuplicateKeys(payload);\n if (hasDuplicateKeys) {\n return {\n message: `Duplicate keys in payload object for analytics:${directive}`,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Check for duplicate keys in object expression\n */\nfunction checkDuplicateKeys(obj: t.ObjectExpression): boolean {\n const keys = new Set<string>();\n\n for (const prop of obj.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n const key = prop.key.name;\n if (keys.has(key)) {\n return true;\n }\n keys.add(key);\n }\n }\n\n return false;\n}\n\n/**\n * Validate directive is used on appropriate element\n */\nexport function validateDirectiveOnElement(\n directive: string,\n elementName: string\n): ValidationError | null {\n const restrictions: Record<string, string[]> = {\n submit: [\"form\"],\n change: [\"input\", \"select\", \"textarea\"],\n input: [\"input\", \"textarea\"],\n focus: [\"input\", \"textarea\", \"select\", \"button\", \"a\"],\n blur: [\"input\", \"textarea\", \"select\", \"button\", \"a\"],\n };\n\n const allowedElements = restrictions[directive];\n if (allowedElements && !allowedElements.includes(elementName.toLowerCase())) {\n return {\n message: `analytics:${directive} should only be used on ${allowedElements.join(\n \", \"\n )} elements, but found on <${elementName}>`,\n };\n }\n\n return null;\n}\n\n/**\n * Validate special directives (identify, page)\n */\nexport function validateSpecialDirective(\n directive: string,\n value: t.JSXAttribute[\"value\"]\n): ValidationError | null {\n if (directive === \"identify\") {\n // identify must use tuple syntax: [userId, traits]\n if (t.isStringLiteral(value)) {\n return {\n message: \"analytics:identify requires tuple syntax: [userId, traits]\",\n };\n }\n\n if (t.isJSXExpressionContainer(value)) {\n const expr = value.expression;\n if (t.isArrayExpression(expr)) {\n if (expr.elements.length < 1) {\n return {\n message:\n \"analytics:identify requires at least userId: [userId, traits?]\",\n };\n }\n if (expr.elements.length > 2) {\n return {\n message:\n \"analytics:identify takes exactly 2 arguments: [userId, traits?]\",\n };\n }\n } else {\n return {\n message: \"analytics:identify must be an array: [userId, traits?]\",\n };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Sanitize event names (prevent injection)\n */\nexport function sanitizeEventName(eventName: string): string {\n // Remove any potentially dangerous characters\n return eventName\n .replace(/[^\\w\\s\\-_.]/g, \"\") // Only allow word chars, spaces, hyphens, underscores, dots\n .trim();\n}\n\n/**\n * Check for PII in payload (warning only)\n */\nexport function checkForPII(payload: t.Expression): string[] {\n const warnings: string[] = [];\n\n if (t.isObjectExpression(payload)) {\n const piiKeys = [\"password\", \"ssn\", \"credit\", \"card\", \"cvv\", \"pin\"];\n\n for (const prop of payload.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n const key = prop.key.name.toLowerCase();\n\n if (piiKeys.some((piiKey) => key.includes(piiKey))) {\n warnings.push(\n `Potential PII detected in payload key \"${prop.key.name}\". Consider anonymizing this data.`\n );\n }\n }\n }\n }\n\n return warnings;\n}\n","/**\n * @solid-analytics/babel-plugin (Enhanced with Validation)\n *\n * Transforms analytics directives into event handlers with build-time validation\n */\n\nimport { declare } from \"@babel/helper-plugin-utils\";\nimport type { PluginObj, PluginPass } from \"@babel/core\";\nimport * as t from \"@babel/types\";\nimport {\n validateDirective,\n validateEventName,\n validatePayload,\n validateDirectiveOnElement,\n validateSpecialDirective,\n sanitizeEventName,\n checkForPII,\n} from \"./validation\";\n\n// Directive to event handler mapping (expanded in Phase 2)\nconst DIRECTIVE_TO_EVENT_MAP: Record<string, string> = {\n click: \"onClick\",\n submit: \"onSubmit\",\n focus: \"onFocus\",\n blur: \"onBlur\",\n change: \"onChange\",\n hover: \"onMouseEnter\",\n scroll: \"onScroll\",\n input: \"onInput\",\n keydown: \"onKeyDown\",\n keyup: \"onKeyUp\",\n keypress: \"onKeyPress\",\n mouseenter: \"onMouseEnter\",\n mouseleave: \"onMouseLeave\",\n mousedown: \"onMouseDown\",\n mouseup: \"onMouseUp\",\n touchstart: \"onTouchStart\",\n touchend: \"onTouchEnd\",\n touchmove: \"onTouchMove\",\n};\n\nconst SPECIAL_DIRECTIVES = [\"visible\", \"identify\", \"page\", \"track\"];\n\ninterface PluginOptions {\n runtimeImport?: string;\n prefix?: string;\n debug?: boolean;\n validate?: boolean;\n sanitize?: boolean;\n warnPII?: boolean;\n}\n\ninterface PluginState extends PluginPass {\n opts: PluginOptions;\n runtimeImportAdded?: boolean;\n runtimeIdentifier?: t.Identifier;\n}\n\nexport default declare<PluginOptions, PluginObj<PluginState>>(\n (api, options) => {\n api.assertVersion(7);\n\n const runtimeImport = options.runtimeImport || \"@solid-analytics/runtime\";\n const prefix = options.prefix || \"analytics\";\n const debug = options.debug || false;\n const validate = options.validate !== false;\n const sanitize = options.sanitize !== false;\n const warnPII = options.warnPII !== false;\n\n return {\n name: \"@solid-analytics/babel-plugin\",\n\n visitor: {\n Program: {\n enter(_path, state) {\n state.runtimeImportAdded = false;\n state.runtimeIdentifier = undefined;\n },\n },\n\n JSXElement(path, state) {\n const openingElement = path.node.openingElement;\n const attributes = openingElement.attributes;\n\n // Get element name for validation\n const elementName = t.isJSXIdentifier(openingElement.name)\n ? openingElement.name.name\n : \"Unknown\";\n\n // Find analytics directives\n const analyticsAttrs: Array<{\n attr: t.JSXAttribute;\n directive: string;\n }> = [];\n\n attributes.forEach((attr) => {\n if (t.isJSXAttribute(attr) && t.isJSXNamespacedName(attr.name)) {\n const namespace = attr.name.namespace.name;\n const name = attr.name.name.name;\n\n if (namespace === prefix) {\n analyticsAttrs.push({\n attr,\n directive: name,\n });\n }\n }\n });\n\n if (analyticsAttrs.length === 0) return;\n\n // Ensure runtime import is added\n if (!state.runtimeImportAdded) {\n addRuntimeImport(path, state, runtimeImport);\n }\n\n // Transform each analytics directive\n for (const { attr, directive } of analyticsAttrs) {\n if (debug) {\n console.log(\n `[babel-plugin] Found directive: ${prefix}:${directive}`\n );\n }\n\n // Validate directive\n if (validate) {\n const directiveError = validateDirective(directive);\n if (directiveError) {\n throw path.buildCodeFrameError(directiveError.message);\n }\n\n const elementError = validateDirectiveOnElement(\n directive,\n elementName\n );\n if (elementError) {\n console.warn(`[babel-plugin] ${elementError.message}`);\n }\n\n const specialError = validateSpecialDirective(\n directive,\n attr.value\n );\n if (specialError) {\n throw path.buildCodeFrameError(specialError.message);\n }\n }\n\n transformDirective(openingElement, attr, directive, state, {\n debug,\n validate,\n sanitize,\n warnPII,\n });\n }\n },\n },\n };\n }\n);\n\nfunction addRuntimeImport(\n path: any,\n state: PluginState,\n runtimeImport: string\n) {\n const program = path.findParent((p: any) => p.isProgram());\n if (!program) return;\n\n const importDeclaration = t.importDeclaration(\n [\n t.importSpecifier(\n t.identifier(\"__analytics\"),\n t.identifier(\"__analytics\")\n ),\n ],\n t.stringLiteral(runtimeImport)\n );\n\n program.unshiftContainer(\"body\", importDeclaration);\n state.runtimeImportAdded = true;\n state.runtimeIdentifier = t.identifier(\"__analytics\");\n}\n\nfunction transformDirective(\n openingElement: t.JSXOpeningElement,\n attr: t.JSXAttribute,\n directive: string,\n state: PluginState,\n options: {\n debug: boolean;\n validate: boolean;\n sanitize: boolean;\n warnPII: boolean;\n }\n) {\n const value = attr.value;\n let eventName: string | t.Expression;\n let payload: t.Expression | null = null;\n\n if (t.isStringLiteral(value)) {\n eventName = value.value;\n\n // Validate event name\n if (options.validate) {\n const nameError = validateEventName(eventName, directive);\n if (nameError) {\n console.warn(`[babel-plugin] ${nameError.message}`);\n }\n }\n\n // Sanitize event name\n if (options.sanitize && typeof eventName === \"string\") {\n eventName = sanitizeEventName(eventName);\n }\n } else if (t.isJSXExpressionContainer(value)) {\n const expr = value.expression;\n\n if (t.isArrayExpression(expr)) {\n const [eventExpr, payloadExpr] = expr.elements;\n\n if (eventExpr && t.isStringLiteral(eventExpr)) {\n eventName = eventExpr.value;\n\n if (options.sanitize) {\n eventName = sanitizeEventName(eventName);\n }\n } else if (eventExpr && t.isExpression(eventExpr)) {\n eventName = eventExpr;\n } else {\n throw new Error(`Invalid event name in analytics:${directive}`);\n }\n\n if (payloadExpr && t.isExpression(payloadExpr)) {\n payload = payloadExpr;\n\n // Validate payload\n if (options.validate) {\n const payloadError = validatePayload(payload, directive);\n if (payloadError) {\n console.warn(`[babel-plugin] ${payloadError.message}`);\n }\n }\n\n // Check for PII\n if (options.warnPII) {\n const piiWarnings = checkForPII(payload);\n piiWarnings.forEach((warning) => {\n console.warn(`[babel-plugin] ${warning}`);\n });\n }\n }\n } else if (t.isStringLiteral(expr)) {\n eventName = expr.value;\n if (options.sanitize) {\n eventName = sanitizeEventName(eventName);\n }\n } else if (t.isExpression(expr)) {\n eventName = expr;\n } else {\n throw new Error(`Invalid value for analytics:${directive}`);\n }\n } else {\n throw new Error(`Invalid value for analytics:${directive}`);\n }\n\n // Remove the analytics directive attribute by finding it\n const attrIndex = openingElement.attributes.indexOf(attr);\n if (attrIndex !== -1) {\n openingElement.attributes.splice(attrIndex, 1);\n }\n\n // Handle special directives\n if (SPECIAL_DIRECTIVES.includes(directive)) {\n handleSpecialDirective(\n openingElement,\n directive,\n eventName,\n payload,\n state,\n options.debug\n );\n return;\n }\n\n // Get the corresponding DOM event\n const domEvent = DIRECTIVE_TO_EVENT_MAP[directive];\n if (!domEvent && options.validate) {\n throw new Error(`Unknown analytics directive: ${directive}`);\n }\n\n // If validation is disabled and we don't know this directive, skip it\n if (!domEvent) {\n return;\n }\n\n // Create the event handler\n const handler = createEventHandler(\n directive,\n eventName,\n payload,\n state,\n options.debug\n );\n\n // Add the event handler as a JSX attribute\n const eventAttr = t.jsxAttribute(\n t.jsxIdentifier(domEvent),\n t.jsxExpressionContainer(handler)\n );\n\n openingElement.attributes.push(eventAttr);\n\n if (options.debug) {\n console.log(`[babel-plugin] Transformed ${directive} -> ${domEvent}`);\n }\n}\n\nfunction createEventHandler(\n _directive: string,\n eventName: string | t.Expression,\n payload: t.Expression | null,\n state: PluginState,\n _debug: boolean\n): t.ArrowFunctionExpression {\n const runtimeId = state.runtimeIdentifier || t.identifier(\"__analytics\");\n\n const trackCall = t.callExpression(\n t.memberExpression(runtimeId, t.identifier(\"track\")),\n [\n typeof eventName === \"string\" ? t.stringLiteral(eventName) : eventName,\n payload || t.identifier(\"undefined\"),\n t.identifier(\"e\"),\n ]\n );\n\n return t.arrowFunctionExpression([t.identifier(\"e\")], trackCall);\n}\n\nfunction handleSpecialDirective(\n openingElement: t.JSXOpeningElement,\n directive: string,\n eventName: string | t.Expression,\n payload: t.Expression | null,\n state: PluginState,\n debug: boolean\n) {\n switch (directive) {\n case \"visible\":\n const visibleAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-visible\"),\n t.stringLiteral(\n typeof eventName === \"string\"\n ? eventName\n : JSON.stringify({ dynamic: true })\n )\n );\n openingElement.attributes.push(visibleAttr);\n\n if (payload) {\n const payloadAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-visible-payload\"),\n t.jsxExpressionContainer(payload)\n );\n openingElement.attributes.push(payloadAttr);\n }\n break;\n\n case \"identify\":\n const identifyAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-identify\"),\n t.jsxExpressionContainer(\n t.arrayExpression([\n typeof eventName === \"string\"\n ? t.stringLiteral(eventName)\n : eventName,\n payload || t.identifier(\"undefined\"),\n ])\n )\n );\n openingElement.attributes.push(identifyAttr);\n break;\n\n case \"page\":\n const pageAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-page\"),\n t.jsxExpressionContainer(\n t.arrayExpression([\n typeof eventName === \"string\"\n ? t.stringLiteral(eventName)\n : eventName,\n payload || t.identifier(\"undefined\"),\n ])\n )\n );\n openingElement.attributes.push(pageAttr);\n break;\n\n case \"track\":\n const trackHandler = createEventHandler(\n \"track\",\n eventName,\n payload,\n state,\n debug\n );\n\n const trackAttr = t.jsxAttribute(\n t.jsxIdentifier(\"onClick\"),\n t.jsxExpressionContainer(trackHandler)\n );\n openingElement.attributes.push(trackAttr);\n break;\n }\n\n if (debug) {\n console.log(`[babel-plugin] Handled special directive: ${directive}`);\n }\n}\n"],"names":["validateDirective","directive","validDirectives","validateEventName","eventName","validatePayload","payload","t","name","checkDuplicateKeys","obj","keys","prop","key","validateDirectiveOnElement","elementName","allowedElements","validateSpecialDirective","value","expr","sanitizeEventName","checkForPII","warnings","piiKeys","piiKey","DIRECTIVE_TO_EVENT_MAP","SPECIAL_DIRECTIVES","index","declare","api","options","runtimeImport","prefix","debug","validate","sanitize","warnPII","_path","state","path","openingElement","attributes","analyticsAttrs","attr","namespace","addRuntimeImport","directiveError","elementError","specialError","transformDirective","program","p","importDeclaration","nameError","eventExpr","payloadExpr","payloadError","warning","attrIndex","handleSpecialDirective","domEvent","handler","createEventHandler","eventAttr","_directive","_debug","runtimeId","trackCall","visibleAttr","payloadAttr","identifyAttr","pageAttr","trackHandler","trackAttr"],"mappings":"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"}
package/dist/index.mjs ADDED
@@ -0,0 +1,352 @@
1
+ import { declare as k } from "@babel/helper-plugin-utils";
2
+ import * as e from "@babel/types";
3
+ function v(i) {
4
+ const t = [
5
+ "click",
6
+ "submit",
7
+ "focus",
8
+ "blur",
9
+ "change",
10
+ "hover",
11
+ "scroll",
12
+ "visible",
13
+ "identify",
14
+ "page",
15
+ "track",
16
+ "input",
17
+ "keydown",
18
+ "keyup",
19
+ "keypress",
20
+ "mouseenter",
21
+ "mouseleave",
22
+ "mousedown",
23
+ "mouseup",
24
+ "touchstart",
25
+ "touchend",
26
+ "touchmove"
27
+ ];
28
+ return t.includes(i) ? null : {
29
+ message: `Unknown analytics directive: "analytics:${i}". Valid directives: ${t.join(
30
+ ", "
31
+ )}`
32
+ };
33
+ }
34
+ function w(i, t) {
35
+ if (typeof i == "string") {
36
+ if (i.trim().length === 0)
37
+ return {
38
+ message: `Event name cannot be empty for analytics:${t}`
39
+ };
40
+ if (/\s/.test(i))
41
+ return {
42
+ message: `Event name "${i}" contains spaces. Did you mean to use underscores?`
43
+ };
44
+ /[A-Z]/.test(i) && !/^[A-Z_]+$/.test(i) && console.warn(
45
+ `[babel-plugin] Event name "${i}" uses camelCase. Consider using snake_case for consistency.`
46
+ );
47
+ }
48
+ return null;
49
+ }
50
+ function $(i, t) {
51
+ if (e.isIdentifier(i)) {
52
+ const n = i.name;
53
+ if (n === "undefined" || n === "null")
54
+ return {
55
+ message: `Invalid payload value "${n}" for analytics:${t}. Use undefined or omit the payload instead.`
56
+ };
57
+ }
58
+ return e.isObjectExpression(i) && j(i) ? {
59
+ message: `Duplicate keys in payload object for analytics:${t}`
60
+ } : null;
61
+ }
62
+ function j(i) {
63
+ const t = /* @__PURE__ */ new Set();
64
+ for (const n of i.properties)
65
+ if (e.isObjectProperty(n) && e.isIdentifier(n.key)) {
66
+ const s = n.key.name;
67
+ if (t.has(s))
68
+ return !0;
69
+ t.add(s);
70
+ }
71
+ return !1;
72
+ }
73
+ function A(i, t) {
74
+ const s = {
75
+ submit: ["form"],
76
+ change: ["input", "select", "textarea"],
77
+ input: ["input", "textarea"],
78
+ focus: ["input", "textarea", "select", "button", "a"],
79
+ blur: ["input", "textarea", "select", "button", "a"]
80
+ }[i];
81
+ return s && !s.includes(t.toLowerCase()) ? {
82
+ message: `analytics:${i} should only be used on ${s.join(
83
+ ", "
84
+ )} elements, but found on <${t}>`
85
+ } : null;
86
+ }
87
+ function C(i, t) {
88
+ if (i === "identify") {
89
+ if (e.isStringLiteral(t))
90
+ return {
91
+ message: "analytics:identify requires tuple syntax: [userId, traits]"
92
+ };
93
+ if (e.isJSXExpressionContainer(t)) {
94
+ const n = t.expression;
95
+ if (e.isArrayExpression(n)) {
96
+ if (n.elements.length < 1)
97
+ return {
98
+ message: "analytics:identify requires at least userId: [userId, traits?]"
99
+ };
100
+ if (n.elements.length > 2)
101
+ return {
102
+ message: "analytics:identify takes exactly 2 arguments: [userId, traits?]"
103
+ };
104
+ } else
105
+ return {
106
+ message: "analytics:identify must be an array: [userId, traits?]"
107
+ };
108
+ }
109
+ }
110
+ return null;
111
+ }
112
+ function x(i) {
113
+ return i.replace(/[^\w\s\-_.]/g, "").trim();
114
+ }
115
+ function S(i) {
116
+ const t = [];
117
+ if (e.isObjectExpression(i)) {
118
+ const n = ["password", "ssn", "credit", "card", "cvv", "pin"];
119
+ for (const s of i.properties)
120
+ if (e.isObjectProperty(s) && e.isIdentifier(s.key)) {
121
+ const a = s.key.name.toLowerCase();
122
+ n.some((o) => a.includes(o)) && t.push(
123
+ `Potential PII detected in payload key "${s.key.name}". Consider anonymizing this data.`
124
+ );
125
+ }
126
+ }
127
+ return t;
128
+ }
129
+ const _ = {
130
+ click: "onClick",
131
+ submit: "onSubmit",
132
+ focus: "onFocus",
133
+ blur: "onBlur",
134
+ change: "onChange",
135
+ hover: "onMouseEnter",
136
+ scroll: "onScroll",
137
+ input: "onInput",
138
+ keydown: "onKeyDown",
139
+ keyup: "onKeyUp",
140
+ keypress: "onKeyPress",
141
+ mouseenter: "onMouseEnter",
142
+ mouseleave: "onMouseLeave",
143
+ mousedown: "onMouseDown",
144
+ mouseup: "onMouseUp",
145
+ touchstart: "onTouchStart",
146
+ touchend: "onTouchEnd",
147
+ touchmove: "onTouchMove"
148
+ }, D = ["visible", "identify", "page", "track"], z = k(
149
+ (i, t) => {
150
+ i.assertVersion(7);
151
+ const n = t.runtimeImport || "@solid-analytics/runtime", s = t.prefix || "analytics", a = t.debug || !1, o = t.validate !== !1, r = t.sanitize !== !1, m = t.warnPII !== !1;
152
+ return {
153
+ name: "@solid-analytics/babel-plugin",
154
+ visitor: {
155
+ Program: {
156
+ enter(d, c) {
157
+ c.runtimeImportAdded = !1, c.runtimeIdentifier = void 0;
158
+ }
159
+ },
160
+ JSXElement(d, c) {
161
+ const y = d.node.openingElement, g = y.attributes, u = e.isJSXIdentifier(y.name) ? y.name.name : "Unknown", p = [];
162
+ if (g.forEach((l) => {
163
+ if (e.isJSXAttribute(l) && e.isJSXNamespacedName(l.name)) {
164
+ const f = l.name.namespace.name, b = l.name.name.name;
165
+ f === s && p.push({
166
+ attr: l,
167
+ directive: b
168
+ });
169
+ }
170
+ }), p.length !== 0) {
171
+ c.runtimeImportAdded || P(d, c, n);
172
+ for (const { attr: l, directive: f } of p) {
173
+ if (a && console.log(
174
+ `[babel-plugin] Found directive: ${s}:${f}`
175
+ ), o) {
176
+ const b = v(f);
177
+ if (b)
178
+ throw d.buildCodeFrameError(b.message);
179
+ const E = A(
180
+ f,
181
+ u
182
+ );
183
+ E && console.warn(`[babel-plugin] ${E.message}`);
184
+ const I = C(
185
+ f,
186
+ l.value
187
+ );
188
+ if (I)
189
+ throw d.buildCodeFrameError(I.message);
190
+ }
191
+ L(y, l, f, c, {
192
+ debug: a,
193
+ validate: o,
194
+ sanitize: r,
195
+ warnPII: m
196
+ });
197
+ }
198
+ }
199
+ }
200
+ }
201
+ };
202
+ }
203
+ );
204
+ function P(i, t, n) {
205
+ const s = i.findParent((o) => o.isProgram());
206
+ if (!s) return;
207
+ const a = e.importDeclaration(
208
+ [
209
+ e.importSpecifier(
210
+ e.identifier("__analytics"),
211
+ e.identifier("__analytics")
212
+ )
213
+ ],
214
+ e.stringLiteral(n)
215
+ );
216
+ s.unshiftContainer("body", a), t.runtimeImportAdded = !0, t.runtimeIdentifier = e.identifier("__analytics");
217
+ }
218
+ function L(i, t, n, s, a) {
219
+ const o = t.value;
220
+ let r, m = null;
221
+ if (e.isStringLiteral(o)) {
222
+ if (r = o.value, a.validate) {
223
+ const u = w(r, n);
224
+ u && console.warn(`[babel-plugin] ${u.message}`);
225
+ }
226
+ a.sanitize && typeof r == "string" && (r = x(r));
227
+ } else if (e.isJSXExpressionContainer(o)) {
228
+ const u = o.expression;
229
+ if (e.isArrayExpression(u)) {
230
+ const [p, l] = u.elements;
231
+ if (p && e.isStringLiteral(p))
232
+ r = p.value, a.sanitize && (r = x(r));
233
+ else if (p && e.isExpression(p))
234
+ r = p;
235
+ else
236
+ throw new Error(`Invalid event name in analytics:${n}`);
237
+ if (l && e.isExpression(l)) {
238
+ if (m = l, a.validate) {
239
+ const f = $(m, n);
240
+ f && console.warn(`[babel-plugin] ${f.message}`);
241
+ }
242
+ a.warnPII && S(m).forEach((b) => {
243
+ console.warn(`[babel-plugin] ${b}`);
244
+ });
245
+ }
246
+ } else if (e.isStringLiteral(u))
247
+ r = u.value, a.sanitize && (r = x(r));
248
+ else if (e.isExpression(u))
249
+ r = u;
250
+ else
251
+ throw new Error(`Invalid value for analytics:${n}`);
252
+ } else
253
+ throw new Error(`Invalid value for analytics:${n}`);
254
+ const d = i.attributes.indexOf(t);
255
+ if (d !== -1 && i.attributes.splice(d, 1), D.includes(n)) {
256
+ O(
257
+ i,
258
+ n,
259
+ r,
260
+ m,
261
+ s,
262
+ a.debug
263
+ );
264
+ return;
265
+ }
266
+ const c = _[n];
267
+ if (!c && a.validate)
268
+ throw new Error(`Unknown analytics directive: ${n}`);
269
+ if (!c)
270
+ return;
271
+ const y = h(
272
+ n,
273
+ r,
274
+ m,
275
+ s
276
+ ), g = e.jsxAttribute(
277
+ e.jsxIdentifier(c),
278
+ e.jsxExpressionContainer(y)
279
+ );
280
+ i.attributes.push(g), a.debug && console.log(`[babel-plugin] Transformed ${n} -> ${c}`);
281
+ }
282
+ function h(i, t, n, s, a) {
283
+ const o = s.runtimeIdentifier || e.identifier("__analytics"), r = e.callExpression(
284
+ e.memberExpression(o, e.identifier("track")),
285
+ [
286
+ typeof t == "string" ? e.stringLiteral(t) : t,
287
+ n || e.identifier("undefined"),
288
+ e.identifier("e")
289
+ ]
290
+ );
291
+ return e.arrowFunctionExpression([e.identifier("e")], r);
292
+ }
293
+ function O(i, t, n, s, a, o) {
294
+ switch (t) {
295
+ case "visible":
296
+ const r = e.jsxAttribute(
297
+ e.jsxIdentifier("data-analytics-visible"),
298
+ e.stringLiteral(
299
+ typeof n == "string" ? n : JSON.stringify({ dynamic: !0 })
300
+ )
301
+ );
302
+ if (i.attributes.push(r), s) {
303
+ const g = e.jsxAttribute(
304
+ e.jsxIdentifier("data-analytics-visible-payload"),
305
+ e.jsxExpressionContainer(s)
306
+ );
307
+ i.attributes.push(g);
308
+ }
309
+ break;
310
+ case "identify":
311
+ const m = e.jsxAttribute(
312
+ e.jsxIdentifier("data-analytics-identify"),
313
+ e.jsxExpressionContainer(
314
+ e.arrayExpression([
315
+ typeof n == "string" ? e.stringLiteral(n) : n,
316
+ s || e.identifier("undefined")
317
+ ])
318
+ )
319
+ );
320
+ i.attributes.push(m);
321
+ break;
322
+ case "page":
323
+ const d = e.jsxAttribute(
324
+ e.jsxIdentifier("data-analytics-page"),
325
+ e.jsxExpressionContainer(
326
+ e.arrayExpression([
327
+ typeof n == "string" ? e.stringLiteral(n) : n,
328
+ s || e.identifier("undefined")
329
+ ])
330
+ )
331
+ );
332
+ i.attributes.push(d);
333
+ break;
334
+ case "track":
335
+ const c = h(
336
+ "track",
337
+ n,
338
+ s,
339
+ a
340
+ ), y = e.jsxAttribute(
341
+ e.jsxIdentifier("onClick"),
342
+ e.jsxExpressionContainer(c)
343
+ );
344
+ i.attributes.push(y);
345
+ break;
346
+ }
347
+ o && console.log(`[babel-plugin] Handled special directive: ${t}`);
348
+ }
349
+ export {
350
+ z as default
351
+ };
352
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sources":["../src/validation.ts","../src/index.ts"],"sourcesContent":["/**\n * Validation utilities for analytics directives\n */\n\nimport * as t from \"@babel/types\";\n\nexport interface ValidationError {\n message: string;\n loc?: {\n line: number;\n column: number;\n };\n}\n\n/**\n * Validate directive name\n */\nexport function validateDirective(directive: string): ValidationError | null {\n const validDirectives = [\n \"click\",\n \"submit\",\n \"focus\",\n \"blur\",\n \"change\",\n \"hover\",\n \"scroll\",\n \"visible\",\n \"identify\",\n \"page\",\n \"track\",\n \"input\",\n \"keydown\",\n \"keyup\",\n \"keypress\",\n \"mouseenter\",\n \"mouseleave\",\n \"mousedown\",\n \"mouseup\",\n \"touchstart\",\n \"touchend\",\n \"touchmove\",\n ];\n\n if (!validDirectives.includes(directive)) {\n return {\n message: `Unknown analytics directive: \"analytics:${directive}\". Valid directives: ${validDirectives.join(\n \", \"\n )}`,\n };\n }\n\n return null;\n}\n\n/**\n * Validate event name\n */\nexport function validateEventName(\n eventName: string | t.Expression,\n directive: string\n): ValidationError | null {\n if (typeof eventName === \"string\") {\n // String event names\n if (eventName.trim().length === 0) {\n return {\n message: `Event name cannot be empty for analytics:${directive}`,\n };\n }\n\n // Warn about potential typos (spaces, special characters)\n if (/\\s/.test(eventName)) {\n return {\n message: `Event name \"${eventName}\" contains spaces. Did you mean to use underscores?`,\n };\n }\n\n // Recommend snake_case\n if (/[A-Z]/.test(eventName) && !/^[A-Z_]+$/.test(eventName)) {\n // Has mixed case but not all caps (which might be intentional)\n console.warn(\n `[babel-plugin] Event name \"${eventName}\" uses camelCase. Consider using snake_case for consistency.`\n );\n }\n }\n\n return null;\n}\n\n/**\n * Validate payload structure\n */\nexport function validatePayload(\n payload: t.Expression,\n directive: string\n): ValidationError | null {\n // Check for common mistakes\n if (t.isIdentifier(payload)) {\n const name = payload.name;\n if (name === \"undefined\" || name === \"null\") {\n return {\n message: `Invalid payload value \"${name}\" for analytics:${directive}. Use undefined or omit the payload instead.`,\n };\n }\n }\n\n // Validate object expression structure\n if (t.isObjectExpression(payload)) {\n const hasDuplicateKeys = checkDuplicateKeys(payload);\n if (hasDuplicateKeys) {\n return {\n message: `Duplicate keys in payload object for analytics:${directive}`,\n };\n }\n }\n\n return null;\n}\n\n/**\n * Check for duplicate keys in object expression\n */\nfunction checkDuplicateKeys(obj: t.ObjectExpression): boolean {\n const keys = new Set<string>();\n\n for (const prop of obj.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n const key = prop.key.name;\n if (keys.has(key)) {\n return true;\n }\n keys.add(key);\n }\n }\n\n return false;\n}\n\n/**\n * Validate directive is used on appropriate element\n */\nexport function validateDirectiveOnElement(\n directive: string,\n elementName: string\n): ValidationError | null {\n const restrictions: Record<string, string[]> = {\n submit: [\"form\"],\n change: [\"input\", \"select\", \"textarea\"],\n input: [\"input\", \"textarea\"],\n focus: [\"input\", \"textarea\", \"select\", \"button\", \"a\"],\n blur: [\"input\", \"textarea\", \"select\", \"button\", \"a\"],\n };\n\n const allowedElements = restrictions[directive];\n if (allowedElements && !allowedElements.includes(elementName.toLowerCase())) {\n return {\n message: `analytics:${directive} should only be used on ${allowedElements.join(\n \", \"\n )} elements, but found on <${elementName}>`,\n };\n }\n\n return null;\n}\n\n/**\n * Validate special directives (identify, page)\n */\nexport function validateSpecialDirective(\n directive: string,\n value: t.JSXAttribute[\"value\"]\n): ValidationError | null {\n if (directive === \"identify\") {\n // identify must use tuple syntax: [userId, traits]\n if (t.isStringLiteral(value)) {\n return {\n message: \"analytics:identify requires tuple syntax: [userId, traits]\",\n };\n }\n\n if (t.isJSXExpressionContainer(value)) {\n const expr = value.expression;\n if (t.isArrayExpression(expr)) {\n if (expr.elements.length < 1) {\n return {\n message:\n \"analytics:identify requires at least userId: [userId, traits?]\",\n };\n }\n if (expr.elements.length > 2) {\n return {\n message:\n \"analytics:identify takes exactly 2 arguments: [userId, traits?]\",\n };\n }\n } else {\n return {\n message: \"analytics:identify must be an array: [userId, traits?]\",\n };\n }\n }\n }\n\n return null;\n}\n\n/**\n * Sanitize event names (prevent injection)\n */\nexport function sanitizeEventName(eventName: string): string {\n // Remove any potentially dangerous characters\n return eventName\n .replace(/[^\\w\\s\\-_.]/g, \"\") // Only allow word chars, spaces, hyphens, underscores, dots\n .trim();\n}\n\n/**\n * Check for PII in payload (warning only)\n */\nexport function checkForPII(payload: t.Expression): string[] {\n const warnings: string[] = [];\n\n if (t.isObjectExpression(payload)) {\n const piiKeys = [\"password\", \"ssn\", \"credit\", \"card\", \"cvv\", \"pin\"];\n\n for (const prop of payload.properties) {\n if (t.isObjectProperty(prop) && t.isIdentifier(prop.key)) {\n const key = prop.key.name.toLowerCase();\n\n if (piiKeys.some((piiKey) => key.includes(piiKey))) {\n warnings.push(\n `Potential PII detected in payload key \"${prop.key.name}\". Consider anonymizing this data.`\n );\n }\n }\n }\n }\n\n return warnings;\n}\n","/**\n * @solid-analytics/babel-plugin (Enhanced with Validation)\n *\n * Transforms analytics directives into event handlers with build-time validation\n */\n\nimport { declare } from \"@babel/helper-plugin-utils\";\nimport type { PluginObj, PluginPass } from \"@babel/core\";\nimport * as t from \"@babel/types\";\nimport {\n validateDirective,\n validateEventName,\n validatePayload,\n validateDirectiveOnElement,\n validateSpecialDirective,\n sanitizeEventName,\n checkForPII,\n} from \"./validation\";\n\n// Directive to event handler mapping (expanded in Phase 2)\nconst DIRECTIVE_TO_EVENT_MAP: Record<string, string> = {\n click: \"onClick\",\n submit: \"onSubmit\",\n focus: \"onFocus\",\n blur: \"onBlur\",\n change: \"onChange\",\n hover: \"onMouseEnter\",\n scroll: \"onScroll\",\n input: \"onInput\",\n keydown: \"onKeyDown\",\n keyup: \"onKeyUp\",\n keypress: \"onKeyPress\",\n mouseenter: \"onMouseEnter\",\n mouseleave: \"onMouseLeave\",\n mousedown: \"onMouseDown\",\n mouseup: \"onMouseUp\",\n touchstart: \"onTouchStart\",\n touchend: \"onTouchEnd\",\n touchmove: \"onTouchMove\",\n};\n\nconst SPECIAL_DIRECTIVES = [\"visible\", \"identify\", \"page\", \"track\"];\n\ninterface PluginOptions {\n runtimeImport?: string;\n prefix?: string;\n debug?: boolean;\n validate?: boolean;\n sanitize?: boolean;\n warnPII?: boolean;\n}\n\ninterface PluginState extends PluginPass {\n opts: PluginOptions;\n runtimeImportAdded?: boolean;\n runtimeIdentifier?: t.Identifier;\n}\n\nexport default declare<PluginOptions, PluginObj<PluginState>>(\n (api, options) => {\n api.assertVersion(7);\n\n const runtimeImport = options.runtimeImport || \"@solid-analytics/runtime\";\n const prefix = options.prefix || \"analytics\";\n const debug = options.debug || false;\n const validate = options.validate !== false;\n const sanitize = options.sanitize !== false;\n const warnPII = options.warnPII !== false;\n\n return {\n name: \"@solid-analytics/babel-plugin\",\n\n visitor: {\n Program: {\n enter(_path, state) {\n state.runtimeImportAdded = false;\n state.runtimeIdentifier = undefined;\n },\n },\n\n JSXElement(path, state) {\n const openingElement = path.node.openingElement;\n const attributes = openingElement.attributes;\n\n // Get element name for validation\n const elementName = t.isJSXIdentifier(openingElement.name)\n ? openingElement.name.name\n : \"Unknown\";\n\n // Find analytics directives\n const analyticsAttrs: Array<{\n attr: t.JSXAttribute;\n directive: string;\n }> = [];\n\n attributes.forEach((attr) => {\n if (t.isJSXAttribute(attr) && t.isJSXNamespacedName(attr.name)) {\n const namespace = attr.name.namespace.name;\n const name = attr.name.name.name;\n\n if (namespace === prefix) {\n analyticsAttrs.push({\n attr,\n directive: name,\n });\n }\n }\n });\n\n if (analyticsAttrs.length === 0) return;\n\n // Ensure runtime import is added\n if (!state.runtimeImportAdded) {\n addRuntimeImport(path, state, runtimeImport);\n }\n\n // Transform each analytics directive\n for (const { attr, directive } of analyticsAttrs) {\n if (debug) {\n console.log(\n `[babel-plugin] Found directive: ${prefix}:${directive}`\n );\n }\n\n // Validate directive\n if (validate) {\n const directiveError = validateDirective(directive);\n if (directiveError) {\n throw path.buildCodeFrameError(directiveError.message);\n }\n\n const elementError = validateDirectiveOnElement(\n directive,\n elementName\n );\n if (elementError) {\n console.warn(`[babel-plugin] ${elementError.message}`);\n }\n\n const specialError = validateSpecialDirective(\n directive,\n attr.value\n );\n if (specialError) {\n throw path.buildCodeFrameError(specialError.message);\n }\n }\n\n transformDirective(openingElement, attr, directive, state, {\n debug,\n validate,\n sanitize,\n warnPII,\n });\n }\n },\n },\n };\n }\n);\n\nfunction addRuntimeImport(\n path: any,\n state: PluginState,\n runtimeImport: string\n) {\n const program = path.findParent((p: any) => p.isProgram());\n if (!program) return;\n\n const importDeclaration = t.importDeclaration(\n [\n t.importSpecifier(\n t.identifier(\"__analytics\"),\n t.identifier(\"__analytics\")\n ),\n ],\n t.stringLiteral(runtimeImport)\n );\n\n program.unshiftContainer(\"body\", importDeclaration);\n state.runtimeImportAdded = true;\n state.runtimeIdentifier = t.identifier(\"__analytics\");\n}\n\nfunction transformDirective(\n openingElement: t.JSXOpeningElement,\n attr: t.JSXAttribute,\n directive: string,\n state: PluginState,\n options: {\n debug: boolean;\n validate: boolean;\n sanitize: boolean;\n warnPII: boolean;\n }\n) {\n const value = attr.value;\n let eventName: string | t.Expression;\n let payload: t.Expression | null = null;\n\n if (t.isStringLiteral(value)) {\n eventName = value.value;\n\n // Validate event name\n if (options.validate) {\n const nameError = validateEventName(eventName, directive);\n if (nameError) {\n console.warn(`[babel-plugin] ${nameError.message}`);\n }\n }\n\n // Sanitize event name\n if (options.sanitize && typeof eventName === \"string\") {\n eventName = sanitizeEventName(eventName);\n }\n } else if (t.isJSXExpressionContainer(value)) {\n const expr = value.expression;\n\n if (t.isArrayExpression(expr)) {\n const [eventExpr, payloadExpr] = expr.elements;\n\n if (eventExpr && t.isStringLiteral(eventExpr)) {\n eventName = eventExpr.value;\n\n if (options.sanitize) {\n eventName = sanitizeEventName(eventName);\n }\n } else if (eventExpr && t.isExpression(eventExpr)) {\n eventName = eventExpr;\n } else {\n throw new Error(`Invalid event name in analytics:${directive}`);\n }\n\n if (payloadExpr && t.isExpression(payloadExpr)) {\n payload = payloadExpr;\n\n // Validate payload\n if (options.validate) {\n const payloadError = validatePayload(payload, directive);\n if (payloadError) {\n console.warn(`[babel-plugin] ${payloadError.message}`);\n }\n }\n\n // Check for PII\n if (options.warnPII) {\n const piiWarnings = checkForPII(payload);\n piiWarnings.forEach((warning) => {\n console.warn(`[babel-plugin] ${warning}`);\n });\n }\n }\n } else if (t.isStringLiteral(expr)) {\n eventName = expr.value;\n if (options.sanitize) {\n eventName = sanitizeEventName(eventName);\n }\n } else if (t.isExpression(expr)) {\n eventName = expr;\n } else {\n throw new Error(`Invalid value for analytics:${directive}`);\n }\n } else {\n throw new Error(`Invalid value for analytics:${directive}`);\n }\n\n // Remove the analytics directive attribute by finding it\n const attrIndex = openingElement.attributes.indexOf(attr);\n if (attrIndex !== -1) {\n openingElement.attributes.splice(attrIndex, 1);\n }\n\n // Handle special directives\n if (SPECIAL_DIRECTIVES.includes(directive)) {\n handleSpecialDirective(\n openingElement,\n directive,\n eventName,\n payload,\n state,\n options.debug\n );\n return;\n }\n\n // Get the corresponding DOM event\n const domEvent = DIRECTIVE_TO_EVENT_MAP[directive];\n if (!domEvent && options.validate) {\n throw new Error(`Unknown analytics directive: ${directive}`);\n }\n\n // If validation is disabled and we don't know this directive, skip it\n if (!domEvent) {\n return;\n }\n\n // Create the event handler\n const handler = createEventHandler(\n directive,\n eventName,\n payload,\n state,\n options.debug\n );\n\n // Add the event handler as a JSX attribute\n const eventAttr = t.jsxAttribute(\n t.jsxIdentifier(domEvent),\n t.jsxExpressionContainer(handler)\n );\n\n openingElement.attributes.push(eventAttr);\n\n if (options.debug) {\n console.log(`[babel-plugin] Transformed ${directive} -> ${domEvent}`);\n }\n}\n\nfunction createEventHandler(\n _directive: string,\n eventName: string | t.Expression,\n payload: t.Expression | null,\n state: PluginState,\n _debug: boolean\n): t.ArrowFunctionExpression {\n const runtimeId = state.runtimeIdentifier || t.identifier(\"__analytics\");\n\n const trackCall = t.callExpression(\n t.memberExpression(runtimeId, t.identifier(\"track\")),\n [\n typeof eventName === \"string\" ? t.stringLiteral(eventName) : eventName,\n payload || t.identifier(\"undefined\"),\n t.identifier(\"e\"),\n ]\n );\n\n return t.arrowFunctionExpression([t.identifier(\"e\")], trackCall);\n}\n\nfunction handleSpecialDirective(\n openingElement: t.JSXOpeningElement,\n directive: string,\n eventName: string | t.Expression,\n payload: t.Expression | null,\n state: PluginState,\n debug: boolean\n) {\n switch (directive) {\n case \"visible\":\n const visibleAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-visible\"),\n t.stringLiteral(\n typeof eventName === \"string\"\n ? eventName\n : JSON.stringify({ dynamic: true })\n )\n );\n openingElement.attributes.push(visibleAttr);\n\n if (payload) {\n const payloadAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-visible-payload\"),\n t.jsxExpressionContainer(payload)\n );\n openingElement.attributes.push(payloadAttr);\n }\n break;\n\n case \"identify\":\n const identifyAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-identify\"),\n t.jsxExpressionContainer(\n t.arrayExpression([\n typeof eventName === \"string\"\n ? t.stringLiteral(eventName)\n : eventName,\n payload || t.identifier(\"undefined\"),\n ])\n )\n );\n openingElement.attributes.push(identifyAttr);\n break;\n\n case \"page\":\n const pageAttr = t.jsxAttribute(\n t.jsxIdentifier(\"data-analytics-page\"),\n t.jsxExpressionContainer(\n t.arrayExpression([\n typeof eventName === \"string\"\n ? t.stringLiteral(eventName)\n : eventName,\n payload || t.identifier(\"undefined\"),\n ])\n )\n );\n openingElement.attributes.push(pageAttr);\n break;\n\n case \"track\":\n const trackHandler = createEventHandler(\n \"track\",\n eventName,\n payload,\n state,\n debug\n );\n\n const trackAttr = t.jsxAttribute(\n t.jsxIdentifier(\"onClick\"),\n t.jsxExpressionContainer(trackHandler)\n );\n openingElement.attributes.push(trackAttr);\n break;\n }\n\n if (debug) {\n console.log(`[babel-plugin] Handled special directive: ${directive}`);\n }\n}\n"],"names":["validateDirective","directive","validDirectives","validateEventName","eventName","validatePayload","payload","t","name","checkDuplicateKeys","obj","keys","prop","key","validateDirectiveOnElement","elementName","allowedElements","validateSpecialDirective","value","expr","sanitizeEventName","checkForPII","warnings","piiKeys","piiKey","DIRECTIVE_TO_EVENT_MAP","SPECIAL_DIRECTIVES","index","declare","api","options","runtimeImport","prefix","debug","validate","sanitize","warnPII","_path","state","path","openingElement","attributes","analyticsAttrs","attr","namespace","addRuntimeImport","directiveError","elementError","specialError","transformDirective","program","p","importDeclaration","nameError","eventExpr","payloadExpr","payloadError","warning","attrIndex","handleSpecialDirective","domEvent","handler","createEventHandler","eventAttr","_directive","_debug","runtimeId","trackCall","visibleAttr","payloadAttr","identifyAttr","pageAttr","trackHandler","trackAttr"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@solid-analytics/babel-plugin",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Babel plugin for transforming analytics directives in SolidJS",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "vite build",
20
+ "dev": "vite build --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest"
23
+ },
24
+ "keywords": [
25
+ "solid",
26
+ "solidjs",
27
+ "analytics",
28
+ "babel-plugin",
29
+ "directives"
30
+ ],
31
+ "license": "MIT",
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "peerDependencies": {
36
+ "@babel/core": "^7.0.0"
37
+ },
38
+ "dependencies": {
39
+ "@babel/helper-plugin-utils": "^7.28.6",
40
+ "@babel/types": "^7.29.0"
41
+ },
42
+ "devDependencies": {
43
+ "@babel/core": "^7.29.0",
44
+ "@types/babel__core": "^7.20.5",
45
+ "@types/babel__helper-plugin-utils": "^7.10.3",
46
+ "tsup": "^8.5.1",
47
+ "typescript": "^5.9.3",
48
+ "vitest": "^4.0.18"
49
+ }
50
+ }