@constela/compiler 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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Constela Contributors
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.
@@ -0,0 +1,198 @@
1
+ import { Program, ConstelaError } from '@constela/core';
2
+ export { createUndefinedVarError } from '@constela/core';
3
+
4
+ /**
5
+ * Analyze Pass - Static analysis for semantic validation
6
+ *
7
+ * This pass performs semantic analysis on the validated AST:
8
+ * - Collects state and action names
9
+ * - Validates state references
10
+ * - Validates action references
11
+ * - Validates variable scopes in each loops
12
+ * - Detects duplicate action names
13
+ */
14
+
15
+ interface AnalysisContext {
16
+ stateNames: Set<string>;
17
+ actionNames: Set<string>;
18
+ }
19
+ interface AnalyzePassSuccess {
20
+ ok: true;
21
+ ast: Program;
22
+ context: AnalysisContext;
23
+ }
24
+ interface AnalyzePassFailure {
25
+ ok: false;
26
+ errors: ConstelaError[];
27
+ }
28
+ type AnalyzePassResult = AnalyzePassSuccess | AnalyzePassFailure;
29
+
30
+ /**
31
+ * Performs static analysis on the validated AST
32
+ *
33
+ * - Collects state names
34
+ * - Collects action names
35
+ * - Validates state references
36
+ * - Validates action references
37
+ * - Validates variable scopes
38
+ *
39
+ * @param ast - Validated AST from validate pass
40
+ * @returns AnalyzePassResult
41
+ */
42
+ declare function analyzePass(ast: Program): AnalyzePassResult;
43
+
44
+ /**
45
+ * Transform Pass - AST to CompiledProgram transformation
46
+ *
47
+ * This pass transforms the validated and analyzed AST into a CompiledProgram
48
+ * that is optimized for runtime execution.
49
+ */
50
+
51
+ interface CompiledProgram {
52
+ version: '1.0';
53
+ state: Record<string, {
54
+ type: string;
55
+ initial: unknown;
56
+ }>;
57
+ actions: Record<string, CompiledAction>;
58
+ view: CompiledNode;
59
+ }
60
+ interface CompiledAction {
61
+ name: string;
62
+ steps: CompiledActionStep[];
63
+ }
64
+ type CompiledActionStep = CompiledSetStep | CompiledUpdateStep | CompiledFetchStep;
65
+ interface CompiledSetStep {
66
+ do: 'set';
67
+ target: string;
68
+ value: CompiledExpression;
69
+ }
70
+ interface CompiledUpdateStep {
71
+ do: 'update';
72
+ target: string;
73
+ operation: string;
74
+ value?: CompiledExpression;
75
+ }
76
+ interface CompiledFetchStep {
77
+ do: 'fetch';
78
+ url: CompiledExpression;
79
+ method?: string;
80
+ body?: CompiledExpression;
81
+ result?: string;
82
+ onSuccess?: CompiledActionStep[];
83
+ onError?: CompiledActionStep[];
84
+ }
85
+ type CompiledNode = CompiledElementNode | CompiledTextNode | CompiledIfNode | CompiledEachNode;
86
+ interface CompiledElementNode {
87
+ kind: 'element';
88
+ tag: string;
89
+ props?: Record<string, CompiledExpression | CompiledEventHandler>;
90
+ children?: CompiledNode[];
91
+ }
92
+ interface CompiledTextNode {
93
+ kind: 'text';
94
+ value: CompiledExpression;
95
+ }
96
+ interface CompiledIfNode {
97
+ kind: 'if';
98
+ condition: CompiledExpression;
99
+ then: CompiledNode;
100
+ else?: CompiledNode;
101
+ }
102
+ interface CompiledEachNode {
103
+ kind: 'each';
104
+ items: CompiledExpression;
105
+ as: string;
106
+ index?: string;
107
+ key?: CompiledExpression;
108
+ body: CompiledNode;
109
+ }
110
+ type CompiledExpression = CompiledLitExpr | CompiledStateExpr | CompiledVarExpr | CompiledBinExpr | CompiledNotExpr;
111
+ interface CompiledLitExpr {
112
+ expr: 'lit';
113
+ value: string | number | boolean | null | unknown[];
114
+ }
115
+ interface CompiledStateExpr {
116
+ expr: 'state';
117
+ name: string;
118
+ }
119
+ interface CompiledVarExpr {
120
+ expr: 'var';
121
+ name: string;
122
+ path?: string;
123
+ }
124
+ interface CompiledBinExpr {
125
+ expr: 'bin';
126
+ op: string;
127
+ left: CompiledExpression;
128
+ right: CompiledExpression;
129
+ }
130
+ interface CompiledNotExpr {
131
+ expr: 'not';
132
+ operand: CompiledExpression;
133
+ }
134
+ interface CompiledEventHandler {
135
+ event: string;
136
+ action: string;
137
+ payload?: CompiledExpression;
138
+ }
139
+ /**
140
+ * Transforms the validated and analyzed AST into a CompiledProgram
141
+ *
142
+ * @param ast - Validated AST from validate pass
143
+ * @param _context - Analysis context from analyze pass (unused in current implementation)
144
+ * @returns CompiledProgram
145
+ */
146
+ declare function transformPass(ast: Program, _context: AnalysisContext): CompiledProgram;
147
+
148
+ /**
149
+ * Main compile function for @constela/compiler
150
+ *
151
+ * This module provides the main compile function that orchestrates
152
+ * the three compilation passes: validate -> analyze -> transform.
153
+ */
154
+
155
+ interface CompileSuccess {
156
+ ok: true;
157
+ program: CompiledProgram;
158
+ }
159
+ interface CompileFailure {
160
+ ok: false;
161
+ errors: ConstelaError[];
162
+ }
163
+ type CompileResult = CompileSuccess | CompileFailure;
164
+ /**
165
+ * Compiles a Constela AST into a CompiledProgram
166
+ *
167
+ * Pipeline: validate -> analyze -> transform
168
+ *
169
+ * @param input - Raw AST input to compile
170
+ * @returns CompileResult with either compiled program or errors
171
+ */
172
+ declare function compile(input: unknown): CompileResult;
173
+
174
+ /**
175
+ * Validate Pass - Schema validation using @constela/core
176
+ *
177
+ * This pass validates the raw input against the Constela AST schema
178
+ * and performs basic semantic validation.
179
+ */
180
+
181
+ interface ValidatePassSuccess {
182
+ ok: true;
183
+ ast: Program;
184
+ }
185
+ interface ValidatePassFailure {
186
+ ok: false;
187
+ error: ConstelaError;
188
+ }
189
+ type ValidatePassResult = ValidatePassSuccess | ValidatePassFailure;
190
+ /**
191
+ * Validates the AST using @constela/core validateAst
192
+ *
193
+ * @param input - Raw input to validate
194
+ * @returns ValidatePassResult
195
+ */
196
+ declare function validatePass(input: unknown): ValidatePassResult;
197
+
198
+ export { type AnalysisContext, type AnalyzePassFailure, type AnalyzePassResult, type AnalyzePassSuccess, type CompileFailure, type CompileResult, type CompileSuccess, type CompiledAction, type CompiledActionStep, type CompiledEachNode, type CompiledElementNode, type CompiledEventHandler, type CompiledExpression, type CompiledIfNode, type CompiledNode, type CompiledProgram, type CompiledTextNode, type ValidatePassFailure, type ValidatePassResult, type ValidatePassSuccess, analyzePass, compile, transformPass, validatePass };
package/dist/index.js ADDED
@@ -0,0 +1,483 @@
1
+ // src/passes/validate.ts
2
+ import { validateAst } from "@constela/core";
3
+ function validatePass(input) {
4
+ const result = validateAst(input);
5
+ if (result.ok) {
6
+ return {
7
+ ok: true,
8
+ ast: result.ast
9
+ };
10
+ }
11
+ return {
12
+ ok: false,
13
+ error: result.error
14
+ };
15
+ }
16
+
17
+ // src/passes/analyze.ts
18
+ import {
19
+ createUndefinedStateError,
20
+ createUndefinedActionError,
21
+ createUndefinedVarError,
22
+ createDuplicateActionError,
23
+ isEventHandler
24
+ } from "@constela/core";
25
+ function buildPath(base, ...segments) {
26
+ return segments.reduce((p, s) => `${p}/${s}`, base);
27
+ }
28
+ function collectContext(ast) {
29
+ const stateNames = new Set(Object.keys(ast.state));
30
+ const actionNames = new Set(ast.actions.map((a) => a.name));
31
+ return { stateNames, actionNames };
32
+ }
33
+ function checkDuplicateActions(ast) {
34
+ const errors = [];
35
+ const seenNames = /* @__PURE__ */ new Set();
36
+ for (let i = 0; i < ast.actions.length; i++) {
37
+ const action = ast.actions[i];
38
+ if (action === void 0) continue;
39
+ if (seenNames.has(action.name)) {
40
+ errors.push(createDuplicateActionError(action.name, `/actions/${i}`));
41
+ }
42
+ seenNames.add(action.name);
43
+ }
44
+ return errors;
45
+ }
46
+ function validateExpression(expr, path, context, scope) {
47
+ const errors = [];
48
+ switch (expr.expr) {
49
+ case "state":
50
+ if (!context.stateNames.has(expr.name)) {
51
+ errors.push(createUndefinedStateError(expr.name, path));
52
+ }
53
+ break;
54
+ case "var":
55
+ if (!scope.has(expr.name)) {
56
+ errors.push(createUndefinedVarError(expr.name, path));
57
+ }
58
+ break;
59
+ case "bin":
60
+ errors.push(...validateExpression(expr.left, buildPath(path, "left"), context, scope));
61
+ errors.push(...validateExpression(expr.right, buildPath(path, "right"), context, scope));
62
+ break;
63
+ case "not":
64
+ errors.push(...validateExpression(expr.operand, buildPath(path, "operand"), context, scope));
65
+ break;
66
+ case "lit":
67
+ break;
68
+ }
69
+ return errors;
70
+ }
71
+ function validateActionStep(step, path, context) {
72
+ const errors = [];
73
+ switch (step.do) {
74
+ case "set":
75
+ if (!context.stateNames.has(step.target)) {
76
+ errors.push(createUndefinedStateError(step.target, buildPath(path, "target")));
77
+ }
78
+ errors.push(
79
+ ...validateExpressionStateOnly(step.value, buildPath(path, "value"), context)
80
+ );
81
+ break;
82
+ case "update":
83
+ if (!context.stateNames.has(step.target)) {
84
+ errors.push(createUndefinedStateError(step.target, buildPath(path, "target")));
85
+ }
86
+ if (step.value) {
87
+ errors.push(
88
+ ...validateExpressionStateOnly(step.value, buildPath(path, "value"), context)
89
+ );
90
+ }
91
+ break;
92
+ case "fetch":
93
+ errors.push(
94
+ ...validateExpressionStateOnly(step.url, buildPath(path, "url"), context)
95
+ );
96
+ if (step.body) {
97
+ errors.push(
98
+ ...validateExpressionStateOnly(step.body, buildPath(path, "body"), context)
99
+ );
100
+ }
101
+ if (step.onSuccess) {
102
+ for (let i = 0; i < step.onSuccess.length; i++) {
103
+ const successStep = step.onSuccess[i];
104
+ if (successStep === void 0) continue;
105
+ errors.push(
106
+ ...validateActionStep(successStep, buildPath(path, "onSuccess", i), context)
107
+ );
108
+ }
109
+ }
110
+ if (step.onError) {
111
+ for (let i = 0; i < step.onError.length; i++) {
112
+ const errorStep = step.onError[i];
113
+ if (errorStep === void 0) continue;
114
+ errors.push(
115
+ ...validateActionStep(errorStep, buildPath(path, "onError", i), context)
116
+ );
117
+ }
118
+ }
119
+ break;
120
+ }
121
+ return errors;
122
+ }
123
+ function validateExpressionStateOnly(expr, path, context) {
124
+ const errors = [];
125
+ switch (expr.expr) {
126
+ case "state":
127
+ if (!context.stateNames.has(expr.name)) {
128
+ errors.push(createUndefinedStateError(expr.name, path));
129
+ }
130
+ break;
131
+ case "var":
132
+ break;
133
+ case "bin":
134
+ errors.push(...validateExpressionStateOnly(expr.left, buildPath(path, "left"), context));
135
+ errors.push(...validateExpressionStateOnly(expr.right, buildPath(path, "right"), context));
136
+ break;
137
+ case "not":
138
+ errors.push(
139
+ ...validateExpressionStateOnly(expr.operand, buildPath(path, "operand"), context)
140
+ );
141
+ break;
142
+ case "lit":
143
+ break;
144
+ }
145
+ return errors;
146
+ }
147
+ function validateExpressionInEventPayload(expr, path, context, scope) {
148
+ const errors = [];
149
+ switch (expr.expr) {
150
+ case "state":
151
+ if (!context.stateNames.has(expr.name)) {
152
+ errors.push(createUndefinedStateError(expr.name, path));
153
+ }
154
+ break;
155
+ case "var":
156
+ break;
157
+ case "bin":
158
+ errors.push(
159
+ ...validateExpressionInEventPayload(expr.left, buildPath(path, "left"), context, scope)
160
+ );
161
+ errors.push(
162
+ ...validateExpressionInEventPayload(expr.right, buildPath(path, "right"), context, scope)
163
+ );
164
+ break;
165
+ case "not":
166
+ errors.push(
167
+ ...validateExpressionInEventPayload(
168
+ expr.operand,
169
+ buildPath(path, "operand"),
170
+ context,
171
+ scope
172
+ )
173
+ );
174
+ break;
175
+ case "lit":
176
+ break;
177
+ }
178
+ return errors;
179
+ }
180
+ function validateViewNode(node, path, context, scope) {
181
+ const errors = [];
182
+ switch (node.kind) {
183
+ case "element":
184
+ if (node.props) {
185
+ for (const [propName, propValue] of Object.entries(node.props)) {
186
+ const propPath = buildPath(path, "props", propName);
187
+ if (isEventHandler(propValue)) {
188
+ if (!context.actionNames.has(propValue.action)) {
189
+ errors.push(createUndefinedActionError(propValue.action, propPath));
190
+ }
191
+ if (propValue.payload) {
192
+ errors.push(
193
+ ...validateExpressionInEventPayload(
194
+ propValue.payload,
195
+ buildPath(propPath, "payload"),
196
+ context,
197
+ scope
198
+ )
199
+ );
200
+ }
201
+ } else {
202
+ errors.push(...validateExpression(propValue, propPath, context, scope));
203
+ }
204
+ }
205
+ }
206
+ if (node.children) {
207
+ for (let i = 0; i < node.children.length; i++) {
208
+ const child = node.children[i];
209
+ if (child === void 0) continue;
210
+ errors.push(
211
+ ...validateViewNode(child, buildPath(path, "children", i), context, scope)
212
+ );
213
+ }
214
+ }
215
+ break;
216
+ case "text":
217
+ errors.push(...validateExpression(node.value, buildPath(path, "value"), context, scope));
218
+ break;
219
+ case "if":
220
+ errors.push(
221
+ ...validateExpression(node.condition, buildPath(path, "condition"), context, scope)
222
+ );
223
+ errors.push(...validateViewNode(node.then, buildPath(path, "then"), context, scope));
224
+ if (node.else) {
225
+ errors.push(...validateViewNode(node.else, buildPath(path, "else"), context, scope));
226
+ }
227
+ break;
228
+ case "each":
229
+ errors.push(...validateExpression(node.items, buildPath(path, "items"), context, scope));
230
+ const bodyScope = new Set(scope);
231
+ bodyScope.add(node.as);
232
+ if (node.index) {
233
+ bodyScope.add(node.index);
234
+ }
235
+ if (node.key) {
236
+ errors.push(...validateExpression(node.key, buildPath(path, "key"), context, bodyScope));
237
+ }
238
+ errors.push(...validateViewNode(node.body, buildPath(path, "body"), context, bodyScope));
239
+ break;
240
+ }
241
+ return errors;
242
+ }
243
+ function validateActions(ast, context) {
244
+ const errors = [];
245
+ for (let i = 0; i < ast.actions.length; i++) {
246
+ const action = ast.actions[i];
247
+ if (action === void 0) continue;
248
+ for (let j = 0; j < action.steps.length; j++) {
249
+ const step = action.steps[j];
250
+ if (step === void 0) continue;
251
+ errors.push(
252
+ ...validateActionStep(step, buildPath("", "actions", i, "steps", j), context)
253
+ );
254
+ }
255
+ }
256
+ return errors;
257
+ }
258
+ function analyzePass(ast) {
259
+ const context = collectContext(ast);
260
+ const errors = [];
261
+ errors.push(...checkDuplicateActions(ast));
262
+ errors.push(...validateActions(ast, context));
263
+ errors.push(...validateViewNode(ast.view, "/view", context, /* @__PURE__ */ new Set()));
264
+ if (errors.length > 0) {
265
+ return {
266
+ ok: false,
267
+ errors
268
+ };
269
+ }
270
+ return {
271
+ ok: true,
272
+ ast,
273
+ context
274
+ };
275
+ }
276
+
277
+ // src/passes/transform.ts
278
+ import { isEventHandler as isEventHandler2 } from "@constela/core";
279
+ function transformExpression(expr) {
280
+ switch (expr.expr) {
281
+ case "lit":
282
+ return {
283
+ expr: "lit",
284
+ value: expr.value
285
+ };
286
+ case "state":
287
+ return {
288
+ expr: "state",
289
+ name: expr.name
290
+ };
291
+ case "var": {
292
+ const varExpr = {
293
+ expr: "var",
294
+ name: expr.name
295
+ };
296
+ if (expr.path) {
297
+ varExpr.path = expr.path;
298
+ }
299
+ return varExpr;
300
+ }
301
+ case "bin":
302
+ return {
303
+ expr: "bin",
304
+ op: expr.op,
305
+ left: transformExpression(expr.left),
306
+ right: transformExpression(expr.right)
307
+ };
308
+ case "not":
309
+ return {
310
+ expr: "not",
311
+ operand: transformExpression(expr.operand)
312
+ };
313
+ }
314
+ }
315
+ function transformEventHandler(handler) {
316
+ const result = {
317
+ event: handler.event,
318
+ action: handler.action
319
+ };
320
+ if (handler.payload) {
321
+ result.payload = transformExpression(handler.payload);
322
+ }
323
+ return result;
324
+ }
325
+ function transformActionStep(step) {
326
+ switch (step.do) {
327
+ case "set":
328
+ return {
329
+ do: "set",
330
+ target: step.target,
331
+ value: transformExpression(step.value)
332
+ };
333
+ case "update": {
334
+ const updateStep = {
335
+ do: "update",
336
+ target: step.target,
337
+ operation: step.operation
338
+ };
339
+ if (step.value) {
340
+ updateStep.value = transformExpression(step.value);
341
+ }
342
+ return updateStep;
343
+ }
344
+ case "fetch": {
345
+ const fetchStep = {
346
+ do: "fetch",
347
+ url: transformExpression(step.url)
348
+ };
349
+ if (step.method) {
350
+ fetchStep.method = step.method;
351
+ }
352
+ if (step.body) {
353
+ fetchStep.body = transformExpression(step.body);
354
+ }
355
+ if (step.result) {
356
+ fetchStep.result = step.result;
357
+ }
358
+ if (step.onSuccess) {
359
+ fetchStep.onSuccess = step.onSuccess.map(transformActionStep);
360
+ }
361
+ if (step.onError) {
362
+ fetchStep.onError = step.onError.map(transformActionStep);
363
+ }
364
+ return fetchStep;
365
+ }
366
+ }
367
+ }
368
+ function transformViewNode(node) {
369
+ switch (node.kind) {
370
+ case "element": {
371
+ const compiledElement = {
372
+ kind: "element",
373
+ tag: node.tag
374
+ };
375
+ if (node.props) {
376
+ compiledElement.props = {};
377
+ for (const [propName, propValue] of Object.entries(node.props)) {
378
+ if (isEventHandler2(propValue)) {
379
+ compiledElement.props[propName] = transformEventHandler(propValue);
380
+ } else {
381
+ compiledElement.props[propName] = transformExpression(propValue);
382
+ }
383
+ }
384
+ }
385
+ if (node.children && node.children.length > 0) {
386
+ compiledElement.children = node.children.map(transformViewNode);
387
+ }
388
+ return compiledElement;
389
+ }
390
+ case "text":
391
+ return {
392
+ kind: "text",
393
+ value: transformExpression(node.value)
394
+ };
395
+ case "if": {
396
+ const compiledIf = {
397
+ kind: "if",
398
+ condition: transformExpression(node.condition),
399
+ then: transformViewNode(node.then)
400
+ };
401
+ if (node.else) {
402
+ compiledIf.else = transformViewNode(node.else);
403
+ }
404
+ return compiledIf;
405
+ }
406
+ case "each": {
407
+ const compiledEach = {
408
+ kind: "each",
409
+ items: transformExpression(node.items),
410
+ as: node.as,
411
+ body: transformViewNode(node.body)
412
+ };
413
+ if (node.index) {
414
+ compiledEach.index = node.index;
415
+ }
416
+ if (node.key) {
417
+ compiledEach.key = transformExpression(node.key);
418
+ }
419
+ return compiledEach;
420
+ }
421
+ }
422
+ }
423
+ function transformState(state) {
424
+ const compiledState = {};
425
+ for (const [name, field] of Object.entries(state)) {
426
+ compiledState[name] = {
427
+ type: field.type,
428
+ initial: field.initial
429
+ };
430
+ }
431
+ return compiledState;
432
+ }
433
+ function transformActions(actions) {
434
+ const compiledActions = {};
435
+ for (const action of actions) {
436
+ compiledActions[action.name] = {
437
+ name: action.name,
438
+ steps: action.steps.map(transformActionStep)
439
+ };
440
+ }
441
+ return compiledActions;
442
+ }
443
+ function transformPass(ast, _context) {
444
+ return {
445
+ version: "1.0",
446
+ state: transformState(ast.state),
447
+ actions: transformActions(ast.actions),
448
+ view: transformViewNode(ast.view)
449
+ };
450
+ }
451
+
452
+ // src/compile.ts
453
+ function compile(input) {
454
+ const validateResult = validatePass(input);
455
+ if (!validateResult.ok) {
456
+ return {
457
+ ok: false,
458
+ errors: [validateResult.error]
459
+ };
460
+ }
461
+ const analyzeResult = analyzePass(validateResult.ast);
462
+ if (!analyzeResult.ok) {
463
+ return {
464
+ ok: false,
465
+ errors: analyzeResult.errors
466
+ };
467
+ }
468
+ const program = transformPass(analyzeResult.ast, analyzeResult.context);
469
+ return {
470
+ ok: true,
471
+ program
472
+ };
473
+ }
474
+
475
+ // src/index.ts
476
+ import { createUndefinedVarError as createUndefinedVarError2 } from "@constela/core";
477
+ export {
478
+ analyzePass,
479
+ compile,
480
+ createUndefinedVarError2 as createUndefinedVarError,
481
+ transformPass,
482
+ validatePass
483
+ };
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@constela/compiler",
3
+ "version": "0.1.0",
4
+ "description": "Compiler for Constela UI framework - AST to Program transformation",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist"
16
+ ],
17
+ "dependencies": {
18
+ "@constela/core": "0.1.0"
19
+ },
20
+ "devDependencies": {
21
+ "@types/node": "^20.10.0",
22
+ "tsup": "^8.0.0",
23
+ "typescript": "^5.3.0",
24
+ "vitest": "^2.0.0"
25
+ },
26
+ "engines": {
27
+ "node": ">=20.0.0"
28
+ },
29
+ "license": "MIT",
30
+ "scripts": {
31
+ "build": "tsup src/index.ts --format esm --dts --clean",
32
+ "type-check": "tsc --noEmit",
33
+ "test": "vitest run",
34
+ "test:watch": "vitest",
35
+ "clean": "rm -rf dist"
36
+ }
37
+ }