@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 +160 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +352 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +50 -0
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
|
package/dist/index.d.ts
ADDED
|
@@ -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
|
+
}
|