jsxpression 0.1.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.
Files changed (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +368 -0
  3. package/lib/analyze/analysis-error.d.ts.map +1 -0
  4. package/lib/analyze/analysis-report.d.ts +33 -0
  5. package/lib/analyze/analysis-report.d.ts.map +1 -0
  6. package/lib/analyze/analysis-report.js +194 -0
  7. package/lib/analyze/analysis-report.js.map +1 -0
  8. package/lib/analyze/analyze.d.ts.map +1 -0
  9. package/lib/analyze/analyze.test.d.ts.map +1 -0
  10. package/lib/analyze/analyze.test.js +765 -0
  11. package/lib/analyze/analyze.test.js.map +1 -0
  12. package/lib/analyze/data/analyze.d.ts.map +1 -0
  13. package/lib/analyze/data/data-access.d.ts.map +1 -0
  14. package/lib/analyze/data/index.d.ts.map +1 -0
  15. package/lib/analyze/data/method-calls.d.ts.map +1 -0
  16. package/lib/analyze/data/utils.d.ts.map +1 -0
  17. package/lib/analyze/index.d.ts.map +1 -0
  18. package/lib/analyze/jsx/analyze.d.ts.map +1 -0
  19. package/lib/analyze/jsx/element-attributes.d.ts.map +1 -0
  20. package/lib/analyze/jsx/element-attributes.js +89 -0
  21. package/lib/analyze/jsx/element-attributes.js.map +1 -0
  22. package/lib/analyze/jsx/element-children.d.ts.map +1 -0
  23. package/lib/analyze/jsx/element-tags.d.ts.map +1 -0
  24. package/lib/analyze/jsx/index.d.ts.map +1 -0
  25. package/lib/analyze/security/analyze.d.ts.map +1 -0
  26. package/lib/analyze/security/call-expressions.d.ts.map +1 -0
  27. package/lib/analyze/security/declarations.d.ts.map +1 -0
  28. package/lib/analyze/security/expressions.d.ts.map +1 -0
  29. package/lib/analyze/security/identifiers.d.ts.map +1 -0
  30. package/lib/analyze/security/index.d.ts.map +1 -0
  31. package/lib/analyze/security/member-access.d.ts.map +1 -0
  32. package/lib/builtins.d.ts +50 -0
  33. package/lib/builtins.d.ts.map +1 -0
  34. package/lib/builtins.js +1065 -0
  35. package/lib/builtins.js.map +1 -0
  36. package/lib/codegen/builtin-types.d.ts +11 -0
  37. package/lib/codegen/builtin-types.d.ts.map +1 -0
  38. package/lib/codegen/builtin-types.js +151 -0
  39. package/lib/codegen/builtin-types.js.map +1 -0
  40. package/lib/codegen/builtins/builtin-types.d.ts +2 -0
  41. package/lib/codegen/builtins/builtin-types.d.ts.map +1 -0
  42. package/lib/codegen/builtins/builtin-types.js +143 -0
  43. package/lib/codegen/builtins/builtin-types.js.map +1 -0
  44. package/lib/codegen/builtins/index.d.ts +2 -0
  45. package/lib/codegen/builtins/index.d.ts.map +1 -0
  46. package/lib/codegen/builtins/index.js +6 -0
  47. package/lib/codegen/builtins/index.js.map +1 -0
  48. package/lib/codegen/declare-types.d.ts +20 -0
  49. package/lib/codegen/declare-types.d.ts.map +1 -0
  50. package/lib/codegen/declare-types.js +299 -0
  51. package/lib/codegen/declare-types.js.map +1 -0
  52. package/lib/codegen/generate-typescript-definitions.d.ts +31 -0
  53. package/lib/codegen/generate-typescript-definitions.d.ts.map +1 -0
  54. package/lib/codegen/generate-typescript-definitions.js +37 -0
  55. package/lib/codegen/generate-typescript-definitions.js.map +1 -0
  56. package/lib/codegen/generate-typescript-definitions.test.d.ts +2 -0
  57. package/lib/codegen/generate-typescript-definitions.test.d.ts.map +1 -0
  58. package/lib/codegen/generate-typescript-definitions.test.js +587 -0
  59. package/lib/codegen/generate-typescript-definitions.test.js.map +1 -0
  60. package/lib/codegen/index.d.ts +2 -0
  61. package/lib/codegen/index.d.ts.map +1 -0
  62. package/lib/codegen/index.js +6 -0
  63. package/lib/codegen/index.js.map +1 -0
  64. package/lib/codegen/schema/component-types.d.ts +3 -0
  65. package/lib/codegen/schema/component-types.d.ts.map +1 -0
  66. package/lib/codegen/schema/component-types.js +118 -0
  67. package/lib/codegen/schema/component-types.js.map +1 -0
  68. package/lib/codegen/schema/data-types.d.ts +3 -0
  69. package/lib/codegen/schema/data-types.d.ts.map +1 -0
  70. package/lib/codegen/schema/data-types.js +98 -0
  71. package/lib/codegen/schema/data-types.js.map +1 -0
  72. package/lib/codegen/schema/index.d.ts +3 -0
  73. package/lib/codegen/schema/index.d.ts.map +1 -0
  74. package/lib/codegen/schema/index.js +8 -0
  75. package/lib/codegen/schema/index.js.map +1 -0
  76. package/lib/codegen/schema/utils.d.ts +4 -0
  77. package/lib/codegen/schema/utils.d.ts.map +1 -0
  78. package/lib/codegen/schema/utils.js +103 -0
  79. package/lib/codegen/schema/utils.js.map +1 -0
  80. package/lib/codegen/schema-to-types.d.ts +14 -0
  81. package/lib/codegen/schema-to-types.d.ts.map +1 -0
  82. package/lib/codegen/schema-to-types.js +203 -0
  83. package/lib/codegen/schema-to-types.js.map +1 -0
  84. package/lib/compile/compile.d.ts.map +1 -0
  85. package/lib/compile/compile.js +245 -0
  86. package/lib/compile/compile.js.map +1 -0
  87. package/lib/compile/compile.test.d.ts.map +1 -0
  88. package/lib/compile/compile.test.js +148 -0
  89. package/lib/compile/compile.test.js.map +1 -0
  90. package/lib/evaluate/evaluate.d.ts +26 -0
  91. package/lib/evaluate/evaluate.d.ts.map +1 -0
  92. package/lib/evaluate/evaluate.js +40 -0
  93. package/lib/evaluate/evaluation-error.d.ts +4 -0
  94. package/lib/evaluate/evaluation-error.d.ts.map +1 -0
  95. package/lib/evaluate/evaluation-error.js +6 -0
  96. package/lib/index.d.ts +8 -0
  97. package/lib/index.d.ts.map +1 -0
  98. package/lib/index.js +16 -0
  99. package/lib/index.js.map +1 -0
  100. package/lib/render.d.ts +58 -0
  101. package/lib/render.d.ts.map +1 -0
  102. package/lib/render.js +52 -0
  103. package/lib/render.test.d.ts.map +1 -0
  104. package/lib/schema.d.ts +68 -0
  105. package/lib/schema.d.ts.map +1 -0
  106. package/lib/schema.js +106 -0
  107. package/lib/validate.d.ts +41 -0
  108. package/lib/validate.d.ts.map +1 -0
  109. package/lib/validate.js +42 -0
  110. package/package.json +27 -0
  111. package/src/analyze/analysis-error.ts +26 -0
  112. package/src/analyze/analysis-report.ts +228 -0
  113. package/src/analyze/analyze.test.ts +829 -0
  114. package/src/analyze/analyze.ts +10 -0
  115. package/src/analyze/data/analyze.ts +15 -0
  116. package/src/analyze/data/data-access.ts +349 -0
  117. package/src/analyze/data/index.ts +1 -0
  118. package/src/analyze/data/method-calls.ts +96 -0
  119. package/src/analyze/data/utils.ts +329 -0
  120. package/src/analyze/index.ts +3 -0
  121. package/src/analyze/jsx/analyze.ts +17 -0
  122. package/src/analyze/jsx/element-attributes.ts +143 -0
  123. package/src/analyze/jsx/element-children.ts +97 -0
  124. package/src/analyze/jsx/element-tags.ts +55 -0
  125. package/src/analyze/jsx/index.ts +1 -0
  126. package/src/analyze/security/analyze.ts +21 -0
  127. package/src/analyze/security/call-expressions.ts +41 -0
  128. package/src/analyze/security/declarations.ts +67 -0
  129. package/src/analyze/security/expressions.ts +100 -0
  130. package/src/analyze/security/identifiers.ts +113 -0
  131. package/src/analyze/security/index.ts +1 -0
  132. package/src/analyze/security/member-access.ts +35 -0
  133. package/src/analyze/utils.ts +118 -0
  134. package/src/analyze/validation-context.ts +32 -0
  135. package/src/builtins.ts +1149 -0
  136. package/src/codegen/builtins/builtin-types.ts +174 -0
  137. package/src/codegen/builtins/index.ts +1 -0
  138. package/src/codegen/generate-typescript-definitions.test.ts +676 -0
  139. package/src/codegen/generate-typescript-definitions.ts +35 -0
  140. package/src/codegen/index.ts +1 -0
  141. package/src/codegen/schema/component-types.ts +140 -0
  142. package/src/codegen/schema/data-types.ts +109 -0
  143. package/src/codegen/schema/index.ts +2 -0
  144. package/src/codegen/schema/utils.ts +111 -0
  145. package/src/compile/compilation-error.ts +37 -0
  146. package/src/compile/compile.test.ts +180 -0
  147. package/src/compile/compile.ts +282 -0
  148. package/src/compile/index.ts +2 -0
  149. package/src/evaluate/evaluate.test.ts +316 -0
  150. package/src/evaluate/evaluate.ts +81 -0
  151. package/src/evaluate/evaluation-error.ts +6 -0
  152. package/src/evaluate/index.ts +2 -0
  153. package/src/index.ts +10 -0
  154. package/src/jsx.ts +161 -0
  155. package/src/parse/index.ts +2 -0
  156. package/src/parse/parse-error.ts +14 -0
  157. package/src/parse/parse.test.ts +99 -0
  158. package/src/parse/parse.ts +40 -0
  159. package/src/render.test.ts +425 -0
  160. package/src/render.ts +75 -0
  161. package/src/schema.ts +195 -0
  162. package/src/traverse.test.ts +104 -0
  163. package/src/traverse.ts +78 -0
  164. package/src/types.ts +17 -0
  165. package/src/validate.ts +59 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Divid AB
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,368 @@
1
+ # JSXpression
2
+
3
+ **Safe JSX expressions with schema validation**
4
+
5
+ JSXpression lets you render dynamic JSX templates in a controlled, type-safe sandbox. Perfect for user-configurable components, low-code environments, and other places where you want flexibility without giving up control.
6
+
7
+ Under the hood it parses your JSX into an AST, validates it against a schema, compiles it to safe JavaScript, and runs it in isolation – with only your data and components available.
8
+
9
+ ## What's it for?
10
+
11
+ Let users write JSX – safely. You define a schema describing which components and data are available, and JSXpression takes care of the rest: parsing, validation, and execution. No risk, no globals, no surprises.
12
+
13
+ **Bonus:** You can generate `.d.ts` files straight from your schema for full editor support – autocomplete, error highlighting, inline docs – all the TypeScript DX, none of the compilation overhead. Your schema stays the single source of truth.
14
+
15
+ ## Features
16
+
17
+ - 🛡️ **Secure by design** – Static analysis blocks everything unsafe. No `eval`, no `window`, no `document`, only pure, allowed operations
18
+ - 📋 **Schema-driven** – Explicitly define what data and components exist. Anything not in the schema simply doesn't exist
19
+ - ⚡ **Fast** – Parse and validate once, then run freely. No runtime compilation required
20
+ - 🎯 **Familiar** – It's just JSX. The same syntax developers already know, now with guardrails
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ npm install jsxpression
26
+ ```
27
+
28
+ or
29
+
30
+ ```bash
31
+ pnpm add jsxpression
32
+ ```
33
+
34
+ ## Quick Start
35
+
36
+ ```typescript
37
+ import { render } from "jsxpression";
38
+
39
+ const schema = {
40
+ data: {
41
+ user: { type: "object", shape: { name: { type: "string" } } },
42
+ items: { type: "array", shape: { type: "string" } },
43
+ },
44
+ elements: {
45
+ Text: { props: { size: { type: "number" } } },
46
+ },
47
+ };
48
+
49
+ const result = render("<Text size={16}>Hello {data.user.name}!</Text>", schema, {
50
+ data: { user: { name: "Peter" }, items: ["apple", "banana"] },
51
+ components: { Text: ({ size, children }) => `<span style="font-size: ${size}px">${children}</span>` },
52
+ });
53
+ // Result: <span style="font-size: 16px">Hello Peter!</span>
54
+ ```
55
+
56
+ ## React Example
57
+
58
+ ```tsx
59
+ import { createElement } from "react";
60
+ import { render } from "jsxpression";
61
+
62
+ function DynamicComponent({ template, userData }) {
63
+ const schema = {
64
+ data: {
65
+ user: {
66
+ type: "object",
67
+ shape: {
68
+ name: {
69
+ type: "string",
70
+ },
71
+ role: {
72
+ type: "string",
73
+ },
74
+ },
75
+ },
76
+ },
77
+ elements: {
78
+ Text: {
79
+ props: {
80
+ className: {
81
+ type: "string",
82
+ },
83
+ },
84
+ },
85
+ Card: {
86
+ props: {
87
+ title: {
88
+ type: "string",
89
+ },
90
+ },
91
+ },
92
+ },
93
+ };
94
+
95
+ const result = render(template, schema, {
96
+ data: { user: userData },
97
+ components: {
98
+ Text: ({ className, children }) => <span className={className}>{children}</span>,
99
+ Card: ({ title, children }) => (
100
+ <div className="card">
101
+ <h3>{title}</h3>
102
+ <div>{children}</div>
103
+ </div>
104
+ ),
105
+ },
106
+ createElement,
107
+ });
108
+
109
+ return <div className="dynamic-content">{result}</div>;
110
+ }
111
+
112
+ // Usage
113
+ <DynamicComponent
114
+ template="<Card title={data.user.role}><Text className='username'>{data.user.name}</Text></Card>"
115
+ userData={{ name: "Alice", role: "Developer" }}
116
+ />;
117
+ ```
118
+
119
+ ## Expression Types
120
+
121
+ JSXpression supports different expression patterns:
122
+
123
+ ```typescript
124
+ // JSX Elements
125
+ "<Text>Hello {data.user.name}</Text>";
126
+
127
+ // Fragments (for mixed content)
128
+ "<>Hello {data.user.name}, you have {data.items.length} items!</>";
129
+
130
+ // Bare expressions (single values)
131
+ "{data.user.name}";
132
+ "{data.items.length * 2}";
133
+ ```
134
+
135
+ **Important:** Like React components, mixed content needs fragment wrapping:
136
+
137
+ - ❌ `"Hello {data.user.name}!"` - Won't work
138
+ - ✅ `"<>Hello {data.user.name}!</>"` - Correct approach
139
+
140
+ ## Supported Methods
141
+
142
+ JSXpression gives you access to common JavaScript methods for working with data - but only the safe ones. No methods that modify arrays in place, no DOM access, no network calls. Just the everyday operations you need for formatting and transforming data in templates.
143
+
144
+ **Why?** When users write templates, they should be able to format dates, filter lists, and do basic math - but not delete files or make API calls. By exposing only pure, read-only methods, templates stay predictable and safe while covering 99% of real-world needs.
145
+
146
+ **Array (static):** `isArray`
147
+
148
+ **Array (prototype):** `map`, `filter`, `reduce`, `find`, `findIndex`, `some`, `every`, `slice`, `includes`, `indexOf`, `join`, `at`, `concat`, `flat`, `flatMap`, `length`
149
+
150
+ **String (prototype):** `charAt`, `charCodeAt`, `concat`, `endsWith`, `includes`, `indexOf`, `lastIndexOf`, `slice`, `split`, `startsWith`, `substring`, `toLowerCase`, `toUpperCase`, `trim`, `trimStart`, `trimEnd`, `replace`, `repeat`, `padStart`, `padEnd`, `replaceAll`, `length`
151
+
152
+ **Number (static):** `isNaN`, `isFinite`, `parseInt`, `parseFloat`
153
+
154
+ **Number (prototype):** `toFixed`, `toPrecision`, `toExponential`
155
+
156
+ **Math:** `max`, `min`, `floor`, `ceil`, `round`, `abs`, `sqrt`, `pow`, `sign`, `sin`, `cos`, `atan2`, `PI`, `E`
157
+
158
+ ### Examples
159
+
160
+ ```typescript
161
+ // Array operations
162
+ "{data.items.map(item => item.toUpperCase())}";
163
+ "{data.numbers.filter(n => n > 10).length}";
164
+ "{data.items.at(-1)}"; // Last item
165
+ "{data.arrays.flat()}"; // Flatten nested arrays
166
+ "{data.items.findIndex(item => item.id === 5)}"; // Find index
167
+ "{Array.isArray(data.value) ? data.value.length : 0}"; // Type check
168
+
169
+ // String operations
170
+ "{data.text.toUpperCase().trim()}";
171
+ "{data.name.slice(0, 3)}";
172
+ "{data.label.padStart(10, '0')}"; // "00000label"
173
+ "{data.text.repeat(3)}"; // Repeat string
174
+ "{data.str.replaceAll('old', 'new')}"; // Replace all occurrences
175
+
176
+ // Math operations
177
+ "{Math.max(...data.scores)}";
178
+ "{Math.round(data.price * 1.2)}";
179
+ "{Math.sqrt(data.area)}"; // Square root
180
+ "{Math.pow(2, 8)}"; // 2^8 = 256
181
+ "{Math.sin(data.angle)}"; // Trigonometry
182
+
183
+ // Number operations
184
+ "{Number.isNaN(data.value)}";
185
+ "{Number.parseInt(data.stringNumber, 10)}";
186
+ "{data.temperature.toFixed(1)}°C"; // 23.5°C
187
+ "{data.price.toFixed(2)}"; // 19.99
188
+ "{data.airflow.toPrecision(4)} m³/h"; // Technical measurements
189
+ ```
190
+
191
+ ## Schema Definition
192
+
193
+ Define what data and components are available:
194
+
195
+ ```typescript
196
+ import type { Schema } from "jsxpression";
197
+
198
+ const schema = {
199
+ //
200
+ // Data schema – everything under `data.*` is available in expressions
201
+ //
202
+ data: {
203
+ user: {
204
+ type: "object",
205
+ description: "User info shown in templates",
206
+ shape: {
207
+ name: { type: "string", required: true },
208
+ age: { type: "number" },
209
+ isAdmin: { type: "boolean" },
210
+ role: { type: "string", enum: ["user", "admin", "guest"] },
211
+ address: {
212
+ type: "object",
213
+ shape: {
214
+ city: { type: "string" },
215
+ zip: { type: "number" },
216
+ },
217
+ },
218
+ tags: {
219
+ type: "array",
220
+ description: "User tags (array of strings)",
221
+ shape: { type: "string" },
222
+ },
223
+ },
224
+ },
225
+
226
+ stats: {
227
+ type: "object",
228
+ shape: {
229
+ scores: { type: "array", shape: { type: "number" } },
230
+ },
231
+ },
232
+
233
+ onClick: {
234
+ type: "function",
235
+ description: "A safe callback (pure, no side effects)",
236
+ },
237
+ },
238
+
239
+ //
240
+ // Element schema – defines which JSX elements can be used
241
+ //
242
+ elements: {
243
+ Text: {
244
+ description: "Simple text element",
245
+ props: {
246
+ size: { type: "number" },
247
+ weight: { type: "string", enum: ["regular", "bold"] },
248
+ color: { type: "string" },
249
+ },
250
+ // no allowedChildren = can contain anything
251
+ },
252
+
253
+ Image: {
254
+ description: "Self-closing image element",
255
+ props: {
256
+ src: { type: "string", required: true },
257
+ alt: { type: "string" },
258
+ width: { type: "number" },
259
+ height: { type: "number" },
260
+ },
261
+ allowedChildren: [], // means <Image src="..." /> only
262
+ },
263
+
264
+ Button: {
265
+ description: "Button with event handler and label",
266
+ props: {
267
+ label: { type: "string", required: true },
268
+ onClick: { type: "function" },
269
+ variant: { type: "string", enum: ["primary", "secondary"] },
270
+ },
271
+ allowedChildren: ["Text"], // can only contain <Text>
272
+ },
273
+
274
+ Card: {
275
+ description: "Wrapper element for grouping content",
276
+ props: {
277
+ title: { type: "string", required: true },
278
+ highlighted: { type: "boolean" },
279
+ },
280
+ allowedChildren: ["Text", "Image", "Button"], // allowed inside <Card>...</Card>
281
+ },
282
+ },
283
+ } satisfies Schema;
284
+
285
+ // <Text size={16} color="blue">{data.user.name}</Text>
286
+ // <Image src={data.user.avatar} />
287
+ // <Button label="Click" onClick={data.onClick}><Text>OK</Text></Button>
288
+ // <Card title="Profile"><Text>{data.user.role}</Text><Button label="Edit" /></Card>
289
+ ```
290
+
291
+ ## API
292
+
293
+ ### `render(source, schema, options?)`
294
+
295
+ Renders a JSX expression with data and components.
296
+
297
+ **Arguments:**
298
+
299
+ - `source: string` - The JSX expression to render (e.g., `"<Text>{data.name}</Text>"`)
300
+ - `schema: Schema` - Schema defining available data properties and components
301
+ - `options?: RenderOptions` - Optional rendering settings:
302
+ - `data?: Record<string, any>` - The actual data available as `data.*` in expressions
303
+ - `components?: Record<string, Component>` - Component implementations
304
+ - `createElement?: Function` - Optional createElement function (e.g., React's `createElement`)
305
+ - `minSeverity?: 1 | 2 | 3` - Minimum severity to abort (1=info, 2=warning, 3=error). Default: 3
306
+
307
+ **Returns:** The rendered result (type depends on the provided createElement function)
308
+
309
+ **Throws:** `AnalysisError` if validation fails
310
+
311
+ **Example:**
312
+
313
+ ```typescript
314
+ const result = render("<Card title={data.title}>{data.content}</Card>", schema, {
315
+ data: { title: "Hello", content: "World" },
316
+ components: { Card: MyCardComponent },
317
+ createElement: React.createElement,
318
+ });
319
+ ```
320
+
321
+ ### `validate(source, schema, options?)`
322
+
323
+ Validatesa JSX expression against a schema without rendering. Great for checking templates before persisting or execution.
324
+
325
+ **Arguments:**
326
+
327
+ - `source: string` - The JSX expression to validate
328
+ - `schema: Schema` - Schema to validate against
329
+ - `options?: ValidateOptions` - Optional validation settings:
330
+ - `minSeverity?: 1 | 2 | 3` - Minimum severity to count as failure. Default: 3
331
+
332
+ **Returns:** `ValidateResult` - Either `{ ok: true }` or `{ ok: false, error: AnalysisError | ParseError }`
333
+
334
+ **Example:**
335
+
336
+ ```typescript
337
+ const result = validate("{data.user.invalidProperty}", schema);
338
+
339
+ if (!result.ok) {
340
+ console.error("Validation failed:", result.error.message);
341
+
342
+ // Analysis errors give you the full breakdown
343
+ if (result.error instanceof AnalysisError) {
344
+ result.error.report.issues.forEach((issue) => {
345
+ console.error(`${issue.message} at line ${issue.range.start.line}`);
346
+ });
347
+ // Also available: .errors (severity 3), .warnings (severity 2), .infos (severity 1)
348
+ }
349
+ }
350
+ ```
351
+
352
+ ### `generateTypeScriptDefinitions(schema)`
353
+
354
+ Generates TypeScript type definitions from a schema. Use this to enable autocomplete and type checking in code editors like Monaco Editor or VS Code.
355
+
356
+ **Arguments:**
357
+
358
+ - `schema: Schema` - The schema to generate types from
359
+
360
+ **Returns:** `string` - Complete TypeScript `.d.ts` file content
361
+
362
+ **Example:**
363
+
364
+ ```typescript
365
+ const definitions = generateTypeScriptDefinitions(schema);
366
+ // Add to Monaco Editor:
367
+ monaco.languages.typescript.javascriptDefaults.addExtraLib(definitions, "jsxpression-types.d.ts");
368
+ ```
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-error.d.ts","sourceRoot":"","sources":["../../src/analyze/analysis-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,qBAAa,aAAc,SAAQ,KAAK;IACtC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,cAAc,GAAG,aAAa;IAWxD,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc;CASpD"}
@@ -0,0 +1,33 @@
1
+ import { Range } from "./utils";
2
+ import { ValidationContextSnapshot } from "./validation-context";
3
+ type IssueSeverity = 1 | 2 | 3;
4
+ interface Issue {
5
+ code: IssueCode;
6
+ message: string;
7
+ severity: IssueSeverity;
8
+ custom: boolean;
9
+ range: Range;
10
+ suggestions: string[];
11
+ snapshot: ValidationContextSnapshot;
12
+ }
13
+ interface IssueDefinition {
14
+ severity: IssueSeverity;
15
+ custom: boolean;
16
+ }
17
+ declare const ISSUES_DEFINITIONS: Record<string, IssueDefinition>;
18
+ export type IssueCode = keyof typeof ISSUES_DEFINITIONS;
19
+ export declare class AnalysisReport {
20
+ #private;
21
+ get issues(): Issue[];
22
+ get errors(): Issue[];
23
+ get warnings(): Issue[];
24
+ get infos(): Issue[];
25
+ get hasErrors(): boolean;
26
+ get hasWarnings(): boolean;
27
+ get hasInfos(): boolean;
28
+ addIssue(code: IssueCode, message: string, range: Range, snapshot: ValidationContextSnapshot, suggestions?: string[]): void;
29
+ hasIssues(minSeverity?: IssueSeverity): boolean;
30
+ merge(...analysisReports: AnalysisReport[]): this;
31
+ }
32
+ export {};
33
+ //# sourceMappingURL=analysis-report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-report.d.ts","sourceRoot":"","sources":["../../src/analyze/analysis-report.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AAEjE,KAAK,aAAa,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAE/B,UAAU,KAAK;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,QAAQ,EAAE,yBAAyB,CAAC;CACrC;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,QAAA,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CA6I9C,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,MAAM,OAAO,kBAAkB,CAAC;AAExD,qBAAa,cAAc;;IAGzB,IAAI,MAAM,IAAI,KAAK,EAAE,CAEpB;IAED,IAAI,MAAM,IAAI,KAAK,EAAE,CAEpB;IAED,IAAI,QAAQ,IAAI,KAAK,EAAE,CAEtB;IAED,IAAI,KAAK,IAAI,KAAK,EAAE,CAEnB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,QAAQ,CACN,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,yBAAyB,EACnC,WAAW,GAAE,MAAM,EAAO,GACzB,IAAI;IAaP,SAAS,CAAC,WAAW,GAAE,aAAiB,GAAG,OAAO;IAIlD,KAAK,CAAC,GAAG,eAAe,EAAE,cAAc,EAAE,GAAG,IAAI;CAQlD"}
@@ -0,0 +1,194 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalysisReport = void 0;
4
+ const ISSUES_DEFINITIONS = {
5
+ VARIABLE_NOT_ALLOWED: {
6
+ severity: 3,
7
+ custom: true,
8
+ },
9
+ IDENTIFIER_NOT_ALLOWED: {
10
+ severity: 3,
11
+ custom: true,
12
+ },
13
+ IMPORT_NOT_ALLOWED: {
14
+ severity: 3,
15
+ custom: true,
16
+ },
17
+ EXPORT_NOT_ALLOWED: {
18
+ severity: 3,
19
+ custom: true,
20
+ },
21
+ ASSIGNMENT_NOT_ALLOWED: {
22
+ severity: 3,
23
+ custom: true,
24
+ },
25
+ UPDATE_NOT_ALLOWED: {
26
+ severity: 3,
27
+ custom: true,
28
+ },
29
+ DELETE_NOT_ALLOWED: {
30
+ severity: 3,
31
+ custom: true,
32
+ },
33
+ NEW_NOT_ALLOWED: {
34
+ severity: 3,
35
+ custom: true,
36
+ },
37
+ THIS_NOT_ALLOWED: {
38
+ severity: 3,
39
+ custom: true,
40
+ },
41
+ SUPER_NOT_ALLOWED: {
42
+ severity: 3,
43
+ custom: true,
44
+ },
45
+ YIELD_NOT_ALLOWED: {
46
+ severity: 3,
47
+ custom: true,
48
+ },
49
+ AWAIT_NOT_ALLOWED: {
50
+ severity: 3,
51
+ custom: true,
52
+ },
53
+ ARROW_FUNCTION_BLOCK_BODY_NOT_ALLOWED: {
54
+ severity: 3,
55
+ custom: true,
56
+ },
57
+ FUNCTION_NOT_ALLOWED: {
58
+ severity: 3,
59
+ custom: true,
60
+ },
61
+ CLASS_NOT_ALLOWED: {
62
+ severity: 3,
63
+ custom: true,
64
+ },
65
+ TRY_NOT_ALLOWED: {
66
+ severity: 3,
67
+ custom: true,
68
+ },
69
+ THROW_NOT_ALLOWED: {
70
+ severity: 3,
71
+ custom: true,
72
+ },
73
+ WITH_NOT_ALLOWED: {
74
+ severity: 3,
75
+ custom: true,
76
+ },
77
+ DEBUGGER_NOT_ALLOWED: {
78
+ severity: 3,
79
+ custom: true,
80
+ },
81
+ COMPUTED_ACCESS_NOT_ALLOWED: {
82
+ severity: 3,
83
+ custom: true,
84
+ },
85
+ COMPUTED_PROPERTY_NOT_ALLOWED: {
86
+ severity: 3,
87
+ custom: true,
88
+ },
89
+ DIRECT_CALL_NOT_ALLOWED: {
90
+ severity: 3,
91
+ custom: true,
92
+ },
93
+ DYNAMIC_METHOD_NOT_ALLOWED: {
94
+ severity: 3,
95
+ custom: true,
96
+ },
97
+ METHOD_NOT_ALLOWED: {
98
+ severity: 3,
99
+ custom: false,
100
+ },
101
+ INVALID_DATA_ACCESS: {
102
+ severity: 3,
103
+ custom: false,
104
+ },
105
+ INVALID_PARAMETER_ACCESS: {
106
+ severity: 3,
107
+ custom: false,
108
+ },
109
+ INVALID_ELEMENT: {
110
+ severity: 3,
111
+ custom: false,
112
+ },
113
+ INVALID_ATTRIBUTE: {
114
+ severity: 3,
115
+ custom: false,
116
+ },
117
+ MISSING_REQUIRED_ATTRIBUTE: {
118
+ severity: 3,
119
+ custom: false,
120
+ },
121
+ INVALID_CHILD_ELEMENT: {
122
+ severity: 3,
123
+ custom: true,
124
+ },
125
+ MEMBER_CHAIN_TOO_DEEP: {
126
+ severity: 2,
127
+ custom: true,
128
+ },
129
+ TOO_MANY_PARAMETERS: {
130
+ severity: 2,
131
+ custom: false,
132
+ },
133
+ INSUFFICIENT_PARAMETERS: {
134
+ severity: 2,
135
+ custom: false,
136
+ },
137
+ INVALID_ATTRIBUTE_VALUE: {
138
+ severity: 3,
139
+ custom: false,
140
+ },
141
+ SELF_CLOSING_WITH_CHILDREN: {
142
+ severity: 1,
143
+ custom: true,
144
+ },
145
+ };
146
+ class AnalysisReport {
147
+ #issues = [];
148
+ get issues() {
149
+ return this.#issues.slice();
150
+ }
151
+ get errors() {
152
+ return this.#issues.filter((issue) => issue.severity === 3);
153
+ }
154
+ get warnings() {
155
+ return this.#issues.filter((issue) => issue.severity === 2);
156
+ }
157
+ get infos() {
158
+ return this.#issues.filter((issue) => issue.severity === 1);
159
+ }
160
+ get hasErrors() {
161
+ return this.errors.length > 0;
162
+ }
163
+ get hasWarnings() {
164
+ return this.warnings.length > 0;
165
+ }
166
+ get hasInfos() {
167
+ return this.infos.length > 0;
168
+ }
169
+ addIssue(code, message, range, snapshot, suggestions = []) {
170
+ const { severity, custom } = ISSUES_DEFINITIONS[code];
171
+ this.#issues.push({
172
+ code,
173
+ message,
174
+ range,
175
+ snapshot,
176
+ suggestions,
177
+ severity,
178
+ custom,
179
+ });
180
+ }
181
+ hasIssues(minSeverity = 3) {
182
+ return this.#issues.some((issue) => issue.severity >= minSeverity);
183
+ }
184
+ merge(...analysisReports) {
185
+ for (const analysisReport of analysisReports) {
186
+ for (const issue of analysisReport.issues) {
187
+ this.addIssue(issue.code, issue.message, issue.range, issue.snapshot, issue.suggestions);
188
+ }
189
+ }
190
+ return this;
191
+ }
192
+ }
193
+ exports.AnalysisReport = AnalysisReport;
194
+ //# sourceMappingURL=analysis-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analysis-report.js","sourceRoot":"","sources":["../../src/analyze/analysis-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../../src/analyze/analyze.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKnD,wBAAgB,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CAEpE"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyze.test.d.ts","sourceRoot":"","sources":["../../src/analyze/analyze.test.ts"],"names":[],"mappings":""}