@v-ibe/core 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 +21 -0
- package/README.md +40 -0
- package/dist/DI/__tests__/scoped-container-dependencies.test.d.ts +1 -0
- package/dist/DI/bootstrap.d.ts +18 -0
- package/dist/DI/decorators/inject.d.ts +37 -0
- package/dist/DI/decorators/inject.js +45 -0
- package/dist/DI/decorators/service.d.ts +24 -0
- package/dist/DI/decorators/service.js +13 -0
- package/dist/DI/di-container.d.ts +53 -0
- package/dist/DI/di-container.js +158 -0
- package/dist/DI/lifecycle.d.ts +37 -0
- package/dist/DI/lifecycle.js +6 -0
- package/dist/DI/scoped-container.d.ts +68 -0
- package/dist/DI/scoped-container.js +193 -0
- package/dist/DI/service-metadata.d.ts +32 -0
- package/dist/DI/service-metadata.js +31 -0
- package/dist/DI/types.d.ts +4 -0
- package/dist/behaviors/__tests__/behavior-system.test.d.ts +1 -0
- package/dist/behaviors/behavior-manager.d.ts +60 -0
- package/dist/behaviors/behavior-manager.js +131 -0
- package/dist/behaviors/behavior-registry.d.ts +68 -0
- package/dist/behaviors/behavior-registry.js +105 -0
- package/dist/behaviors/constants.d.ts +16 -0
- package/dist/behaviors/constants.js +8 -0
- package/dist/behaviors/decorators.d.ts +87 -0
- package/dist/behaviors/decorators.js +46 -0
- package/dist/behaviors/index.d.ts +4 -0
- package/dist/components/__tests__/host.test.d.ts +1 -0
- package/dist/components/app-tree.d.ts +49 -0
- package/dist/components/app-tree.js +122 -0
- package/dist/components/base-component.d.ts +85 -0
- package/dist/components/base-component.js +438 -0
- package/dist/components/decorators/component.d.ts +27 -0
- package/dist/components/decorators/component.js +47 -0
- package/dist/components/decorators/prop.d.ts +14 -0
- package/dist/components/decorators/prop.js +37 -0
- package/dist/components/types.d.ts +26 -0
- package/dist/core.d.ts +23 -0
- package/dist/core.js +8 -0
- package/dist/custom-components/__tests__/for.test.d.ts +1 -0
- package/dist/custom-components/__tests__/show.test.d.ts +1 -0
- package/dist/custom-components/for.d.ts +58 -0
- package/dist/custom-components/for.js +313 -0
- package/dist/custom-components/index.d.ts +2 -0
- package/dist/custom-components/show.d.ts +78 -0
- package/dist/custom-components/show.js +88 -0
- package/dist/data-management/cache/cache-invalidate.decorator.d.ts +35 -0
- package/dist/data-management/cache/cache-invalidate.decorator.js +21 -0
- package/dist/data-management/cache/cache-metadata.d.ts +15 -0
- package/dist/data-management/cache/cache-provider.interface.d.ts +67 -0
- package/dist/data-management/cache/cache-tags.decorator.d.ts +52 -0
- package/dist/data-management/cache/cache-tags.decorator.js +13 -0
- package/dist/data-management/cache/cache-update.decorator.d.ts +28 -0
- package/dist/data-management/cache/cache-update.decorator.js +21 -0
- package/dist/data-management/cache/cache.decorator.d.ts +28 -0
- package/dist/data-management/cache/cache.decorator.js +13 -0
- package/dist/data-management/cache/index.d.ts +11 -0
- package/dist/data-management/cache/local-storage-cache.d.ts +40 -0
- package/dist/data-management/cache/local-storage-cache.js +268 -0
- package/dist/data-management/cache/memory-cache.d.ts +37 -0
- package/dist/data-management/cache/memory-cache.js +149 -0
- package/dist/data-management/cache/session-storage-cache.d.ts +35 -0
- package/dist/data-management/cache/session-storage-cache.js +242 -0
- package/dist/data-management/cache/ttl.decorator.d.ts +31 -0
- package/dist/data-management/cache/ttl.decorator.js +34 -0
- package/dist/data-management/decorators/consume.d.ts +29 -0
- package/dist/data-management/decorators/consume.js +28 -0
- package/dist/data-management/decorators/id.d.ts +28 -0
- package/dist/data-management/decorators/id.js +19 -0
- package/dist/data-management/decorators/model.d.ts +48 -0
- package/dist/data-management/decorators/model.js +24 -0
- package/dist/data-management/decorators/prop.d.ts +43 -0
- package/dist/data-management/decorators/prop.js +32 -0
- package/dist/data-management/index.d.ts +13 -0
- package/dist/data-management/store/json-to-model.d.ts +45 -0
- package/dist/data-management/store/json-to-model.js +36 -0
- package/dist/data-management/store/store.d.ts +108 -0
- package/dist/data-management/store/store.js +207 -0
- package/dist/data-management/store/types.d.ts +53 -0
- package/dist/events-handler/decorators/emit.d.ts +29 -0
- package/dist/events-handler/decorators/emit.js +51 -0
- package/dist/events-handler/event-decorators.d.ts +1 -0
- package/dist/events-handler/event-emitter.service.d.ts +21 -0
- package/dist/events-handler/event-emitter.service.js +85 -0
- package/dist/events-handler/event-types.d.ts +12 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +121 -0
- package/dist/jsx/dynamic/__tests__/granular-array-renderer.test.d.ts +1 -0
- package/dist/jsx/dynamic/__tests__/jsx-array-rendering.test.d.ts +1 -0
- package/dist/jsx/dynamic/array-renderer.d.ts +2 -0
- package/dist/jsx/dynamic/array-renderer.js +133 -0
- package/dist/jsx/dynamic/child-renderer.d.ts +1 -0
- package/dist/jsx/dynamic/child-renderer.js +180 -0
- package/dist/jsx/dynamic/dom-utils.d.ts +5 -0
- package/dist/jsx/dynamic/dom-utils.js +22 -0
- package/dist/jsx/dynamic/granular-array-renderer.d.ts +16 -0
- package/dist/jsx/dynamic/granular-array-renderer.js +153 -0
- package/dist/jsx/dynamic/node-renderer.d.ts +2 -0
- package/dist/jsx/dynamic/props-handler.d.ts +3 -0
- package/dist/jsx/dynamic/props-handler.js +281 -0
- package/dist/jsx/dynamic/text-renderer.d.ts +2 -0
- package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx/jsx-runtime.d.ts +3 -0
- package/dist/jsx/types.d.ts +35 -0
- package/dist/jsx/types.js +4 -0
- package/dist/jsx-dev-runtime.d.ts +2 -0
- package/dist/jsx-dev-runtime.js +8 -0
- package/dist/jsx-runtime.d.ts +2 -0
- package/dist/jsx-runtime.js +11 -0
- package/dist/reactivity/__tests__/context-stack.test.d.ts +1 -0
- package/dist/reactivity/__tests__/nested-effects-untrack.test.d.ts +22 -0
- package/dist/reactivity/context-scope.d.ts +57 -0
- package/dist/reactivity/context-scope.js +35 -0
- package/dist/reactivity/decorators/__tests__/ctx-integration.test.d.ts +5 -0
- package/dist/reactivity/decorators/__tests__/ctx-loop.test.d.ts +10 -0
- package/dist/reactivity/decorators/__tests__/state-intelligent.test.d.ts +1 -0
- package/dist/reactivity/decorators/computed.d.ts +6 -0
- package/dist/reactivity/decorators/computed.js +17 -0
- package/dist/reactivity/decorators/create-event-decorator.d.ts +5 -0
- package/dist/reactivity/decorators/create-event-decorator.js +28 -0
- package/dist/reactivity/decorators/ctx.d.ts +9 -0
- package/dist/reactivity/decorators/ctx.js +91 -0
- package/dist/reactivity/decorators/effect.d.ts +9 -0
- package/dist/reactivity/decorators/effect.js +24 -0
- package/dist/reactivity/decorators/resource.d.ts +48 -0
- package/dist/reactivity/decorators/resource.js +20 -0
- package/dist/reactivity/decorators/state.d.ts +8 -0
- package/dist/reactivity/decorators/state.js +68 -0
- package/dist/reactivity/decorators/store.d.ts +6 -0
- package/dist/reactivity/decorators/store.js +25 -0
- package/dist/reactivity/phase-scheduler.d.ts +81 -0
- package/dist/reactivity/phase-scheduler.js +88 -0
- package/dist/reactivity/phase-scheduler.test.d.ts +1 -0
- package/dist/reactivity/reactive-cache.d.ts +21 -0
- package/dist/reactivity/reactive-cache.js +31 -0
- package/dist/reactivity/reactive-cache.test.d.ts +1 -0
- package/dist/reactivity/reactive-context.d.ts +152 -0
- package/dist/reactivity/reactive-context.js +184 -0
- package/dist/reactivity/signals/__tests__/composicion-automatica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-1-estructura-basica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-2-registro-subscribers.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-3-notificaciones-basicas.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-4-comparacion-valores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-5-tracking-automatico.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-6-anti-glitch.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-7-objetos-anidados.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite/nivel-8-observable-array-support.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/composite-shallow-tracking.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/effect.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-1-estructura-basica.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-2-metodos-mutadores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-3-tracking-por-indice.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-4-tracking-length.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-5-tracking-mutation.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-6-metodos-no-mutadores.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-7-composicion-bidireccional.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-8-proxies.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/reactive-array/nivel-9-derived-cache-optimization.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/resource.test.d.ts +1 -0
- package/dist/reactivity/signals/__tests__/signal.test.d.ts +1 -0
- package/dist/reactivity/signals/array-strategies.d.ts +120 -0
- package/dist/reactivity/signals/array-strategies.js +261 -0
- package/dist/reactivity/signals/composite.d.ts +89 -0
- package/dist/reactivity/signals/composite.js +145 -0
- package/dist/reactivity/signals/computed.d.ts +61 -0
- package/dist/reactivity/signals/computed.js +107 -0
- package/dist/reactivity/signals/computed.test.d.ts +1 -0
- package/dist/reactivity/signals/derived.d.ts +10 -0
- package/dist/reactivity/signals/derived.js +24 -0
- package/dist/reactivity/signals/effect.d.ts +27 -0
- package/dist/reactivity/signals/effect.js +46 -0
- package/dist/reactivity/signals/event.d.ts +9 -0
- package/dist/reactivity/signals/event.js +15 -0
- package/dist/reactivity/signals/reactive-array.d.ts +133 -0
- package/dist/reactivity/signals/reactive-array.js +490 -0
- package/dist/reactivity/signals/reactive-proxy.d.ts +54 -0
- package/dist/reactivity/signals/reactive-proxy.js +299 -0
- package/dist/reactivity/signals/reactive-tracking.test.d.ts +1 -0
- package/dist/reactivity/signals/resource.d.ts +9 -0
- package/dist/reactivity/signals/resource.js +58 -0
- package/dist/reactivity/signals/signal.d.ts +39 -0
- package/dist/reactivity/signals/signal.js +56 -0
- package/dist/reactivity/signals/subscription-management.test.d.ts +1 -0
- package/dist/reactivity/types.d.ts +12 -0
- package/dist/router/__tests__/link-behavior-active-class.test.d.ts +1 -0
- package/dist/router/__tests__/loop-detector.test.d.ts +1 -0
- package/dist/router/__tests__/params-container-resolution.test.d.ts +1 -0
- package/dist/router/__tests__/router-generated-routes.test.d.ts +1 -0
- package/dist/router/__tests__/router-params-granular.test.d.ts +1 -0
- package/dist/router/__tests__/router-params-simple.test.d.ts +1 -0
- package/dist/router/__tests__/router-query-params.test.d.ts +1 -0
- package/dist/router/__tests__/router-route-candidates.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-app-articles.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-debug.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-integration.test.d.ts +1 -0
- package/dist/router/__tests__/routeview-this.test.d.ts +1 -0
- package/dist/router/decorators/base-policy.d.ts +141 -0
- package/dist/router/decorators/base-policy.js +63 -0
- package/dist/router/decorators/index.d.ts +6 -0
- package/dist/router/decorators/params.d.ts +31 -0
- package/dist/router/decorators/params.js +97 -0
- package/dist/router/decorators/route-metadata.d.ts +11 -0
- package/dist/router/decorators/route-metadata.js +23 -0
- package/dist/router/decorators/route.d.ts +39 -0
- package/dist/router/decorators/route.js +7 -0
- package/dist/router/link.behavior.d.ts +87 -0
- package/dist/router/link.behavior.js +227 -0
- package/dist/router/policy-evaluator.d.ts +81 -0
- package/dist/router/policy-evaluator.js +209 -0
- package/dist/router/route-view.d.ts +56 -0
- package/dist/router/route-view.js +156 -0
- package/dist/router/router.d.ts +67 -0
- package/dist/router/router.js +308 -0
- package/dist/router/static-analysis/index.d.ts +37 -0
- package/dist/router/static-analysis/parser.d.ts +14 -0
- package/dist/router/static-analysis/parser.js +147 -0
- package/dist/router/static-analysis/scanner.d.ts +27 -0
- package/dist/router/static-analysis/scanner.js +91 -0
- package/dist/router/trie.d.ts +14 -0
- package/dist/router/trie.js +126 -0
- package/dist/router/trie.types.d.ts +36 -0
- package/dist/styles/base-style-sheet.d.ts +96 -0
- package/dist/styles/base-style-sheet.js +149 -0
- package/dist/styles/decorators/factories.d.ts +76 -0
- package/dist/styles/decorators/factories.js +11 -0
- package/dist/styles/decorators/keyframes.d.ts +238 -0
- package/dist/styles/decorators/keyframes.js +79 -0
- package/dist/styles/decorators/rule.d.ts +177 -0
- package/dist/styles/decorators/rule.js +72 -0
- package/dist/styles/decorators/scope.d.ts +66 -0
- package/dist/styles/decorators/scope.js +17 -0
- package/dist/styles/decorators/style.d.ts +1 -0
- package/dist/styles/decorators/style.js +20 -0
- package/dist/styles/decorators/useStyles.d.ts +5 -0
- package/dist/styles/decorators/useStyles.js +29 -0
- package/dist/styles/global-styles-registry.d.ts +72 -0
- package/dist/styles/global-styles-registry.js +155 -0
- package/dist/types.d.ts +1 -0
- package/dist/vite-plugins/__tests__/jsx-control-flow-transform.test.d.ts +1 -0
- package/dist/vite-plugins/index.d.ts +4 -0
- package/dist/vite-plugins/index.js +10 -0
- package/dist/vite-plugins/jsx-contextual.d.ts +7 -0
- package/dist/vite-plugins/jsx-contextual.js +53 -0
- package/dist/vite-plugins/jsx-control-flow-transform.d.ts +60 -0
- package/dist/vite-plugins/jsx-control-flow-transform.js +180 -0
- package/dist/vite-plugins/jsx-signals.d.ts +2 -0
- package/dist/vite-plugins/jsx-signals.js +124 -0
- package/dist/vite-plugins/router/route-generator-plugin.d.ts +63 -0
- package/dist/vite-plugins/router/route-generator-plugin.js +310 -0
- package/package.json +85 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import ts__default from "typescript";
|
|
2
|
+
function jsxSignalsPlugin() {
|
|
3
|
+
return {
|
|
4
|
+
name: "jsx-signals",
|
|
5
|
+
enforce: "pre",
|
|
6
|
+
transform(code, id) {
|
|
7
|
+
if (!id.endsWith(".tsx") && !id.endsWith(".jsx")) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
const sourceFile = ts__default.createSourceFile(
|
|
11
|
+
id,
|
|
12
|
+
code,
|
|
13
|
+
ts__default.ScriptTarget.Latest,
|
|
14
|
+
true,
|
|
15
|
+
ts__default.ScriptKind.TSX
|
|
16
|
+
);
|
|
17
|
+
const transformer = (context) => {
|
|
18
|
+
return (sourceFile2) => {
|
|
19
|
+
const visit = (node) => {
|
|
20
|
+
if (ts__default.isCallExpression(node) && ts__default.isPropertyAccessExpression(node.expression) && node.expression.name.text === "map") ;
|
|
21
|
+
if (ts__default.isJsxAttribute(node) && node.initializer && ts__default.isJsxExpression(node.initializer)) {
|
|
22
|
+
const attributeName = node.name.getText(sourceFile2);
|
|
23
|
+
const jsxExpression = node.initializer;
|
|
24
|
+
if (isEventHandler(attributeName)) {
|
|
25
|
+
return ts__default.visitEachChild(node, visit, context);
|
|
26
|
+
}
|
|
27
|
+
if (jsxExpression.expression && containsThis(jsxExpression.expression)) {
|
|
28
|
+
if (ts__default.isArrowFunction(jsxExpression.expression) || ts__default.isFunctionExpression(jsxExpression.expression)) {
|
|
29
|
+
return ts__default.visitEachChild(node, visit, context);
|
|
30
|
+
}
|
|
31
|
+
const arrowFunction = ts__default.factory.createArrowFunction(
|
|
32
|
+
void 0,
|
|
33
|
+
void 0,
|
|
34
|
+
[],
|
|
35
|
+
void 0,
|
|
36
|
+
ts__default.factory.createToken(ts__default.SyntaxKind.EqualsGreaterThanToken),
|
|
37
|
+
jsxExpression.expression
|
|
38
|
+
);
|
|
39
|
+
const newJsxExpression = ts__default.factory.updateJsxExpression(
|
|
40
|
+
jsxExpression,
|
|
41
|
+
arrowFunction
|
|
42
|
+
);
|
|
43
|
+
return ts__default.factory.updateJsxAttribute(
|
|
44
|
+
node,
|
|
45
|
+
node.name,
|
|
46
|
+
newJsxExpression
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (ts__default.isJsxExpression(node) && node.expression && !ts__default.isJsxAttribute(node.parent)) {
|
|
51
|
+
const expr = node.expression;
|
|
52
|
+
if (ts__default.isArrowFunction(expr) || ts__default.isFunctionExpression(expr)) {
|
|
53
|
+
return ts__default.visitEachChild(node, visit, context);
|
|
54
|
+
}
|
|
55
|
+
if (ts__default.isCallExpression(expr)) {
|
|
56
|
+
const visitedNode = ts__default.visitEachChild(node, visit, context);
|
|
57
|
+
const visitedExpr = visitedNode.expression;
|
|
58
|
+
if (containsThis(visitedExpr)) {
|
|
59
|
+
const arrowFunction = ts__default.factory.createArrowFunction(
|
|
60
|
+
void 0,
|
|
61
|
+
void 0,
|
|
62
|
+
[],
|
|
63
|
+
void 0,
|
|
64
|
+
ts__default.factory.createToken(ts__default.SyntaxKind.EqualsGreaterThanToken),
|
|
65
|
+
visitedExpr
|
|
66
|
+
);
|
|
67
|
+
return ts__default.factory.updateJsxExpression(visitedNode, arrowFunction);
|
|
68
|
+
}
|
|
69
|
+
return visitedNode;
|
|
70
|
+
}
|
|
71
|
+
if (containsThis(expr)) {
|
|
72
|
+
const visitedNode = ts__default.visitEachChild(node, visit, context);
|
|
73
|
+
const visitedExpr = visitedNode.expression;
|
|
74
|
+
const arrowFunction = ts__default.factory.createArrowFunction(
|
|
75
|
+
void 0,
|
|
76
|
+
void 0,
|
|
77
|
+
[],
|
|
78
|
+
void 0,
|
|
79
|
+
ts__default.factory.createToken(ts__default.SyntaxKind.EqualsGreaterThanToken),
|
|
80
|
+
visitedExpr
|
|
81
|
+
);
|
|
82
|
+
return ts__default.factory.updateJsxExpression(visitedNode, arrowFunction);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return ts__default.visitEachChild(node, visit, context);
|
|
86
|
+
};
|
|
87
|
+
return ts__default.visitEachChild(sourceFile2, visit, context);
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
function isEventHandler(attributeName) {
|
|
91
|
+
return attributeName.startsWith("on") && attributeName.length > 2;
|
|
92
|
+
}
|
|
93
|
+
function containsThis(expr) {
|
|
94
|
+
let hasThis = false;
|
|
95
|
+
const visitor = (node) => {
|
|
96
|
+
if (hasThis) return;
|
|
97
|
+
if (ts__default.isPropertyAccessExpression(node) && node.expression.kind === ts__default.SyntaxKind.ThisKeyword || ts__default.isElementAccessExpression(node) && node.expression.kind === ts__default.SyntaxKind.ThisKeyword || ts__default.isCallExpression(node) && ts__default.isPropertyAccessExpression(node.expression) && node.expression.expression.kind === ts__default.SyntaxKind.ThisKeyword || node.kind === ts__default.SyntaxKind.ThisKeyword) {
|
|
98
|
+
hasThis = true;
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
ts__default.forEachChild(node, visitor);
|
|
102
|
+
};
|
|
103
|
+
visitor(expr);
|
|
104
|
+
return hasThis;
|
|
105
|
+
}
|
|
106
|
+
const result = ts__default.transform(sourceFile, [transformer]);
|
|
107
|
+
const transformedFile = result.transformed[0];
|
|
108
|
+
const printer = ts__default.createPrinter({
|
|
109
|
+
newLine: ts__default.NewLineKind.LineFeed,
|
|
110
|
+
removeComments: false,
|
|
111
|
+
omitTrailingSemicolon: false
|
|
112
|
+
});
|
|
113
|
+
const newCode = printer.printFile(transformedFile);
|
|
114
|
+
result.dispose();
|
|
115
|
+
return {
|
|
116
|
+
code: newCode,
|
|
117
|
+
map: null
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export {
|
|
123
|
+
jsxSignalsPlugin
|
|
124
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Opciones de configuración para el plugin de generación de rutas
|
|
4
|
+
*
|
|
5
|
+
* IMPORTANTE: Todas las rutas son relativas al directorio raíz del proyecto del usuario,
|
|
6
|
+
* no al directorio del framework. El plugin se ejecuta en el contexto del proyecto
|
|
7
|
+
* donde está instalado el framework como dependencia.
|
|
8
|
+
*/
|
|
9
|
+
export interface RouteGeneratorPluginOptions {
|
|
10
|
+
/**
|
|
11
|
+
* Directorio raíz donde buscar archivos con decoradores @Route
|
|
12
|
+
* Relativo al root del proyecto del usuario
|
|
13
|
+
* @default 'app'
|
|
14
|
+
*/
|
|
15
|
+
srcDir?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Ruta donde se generará el archivo de rutas
|
|
18
|
+
* Relativo al root del proyecto del usuario
|
|
19
|
+
* @default 'app/router/generated-routes.ts'
|
|
20
|
+
*/
|
|
21
|
+
outputPath?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Extensiones de archivo a escanear
|
|
24
|
+
* @default ['.ts', '.tsx']
|
|
25
|
+
*/
|
|
26
|
+
extensions?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* Directorios a excluir del escaneo
|
|
29
|
+
* @default ['node_modules', 'dist', 'build', '.git']
|
|
30
|
+
*/
|
|
31
|
+
exclude?: string[];
|
|
32
|
+
/**
|
|
33
|
+
* Activar logs detallados
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
verbose?: boolean;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Plugin de Vite para generación automática de rutas
|
|
40
|
+
*
|
|
41
|
+
* Escanea el proyecto del usuario buscando decoradores @Route y genera un archivo
|
|
42
|
+
* TypeScript con todas las rutas encontradas para registro automático en el Trie.
|
|
43
|
+
*
|
|
44
|
+
* El plugin trabaja en el contexto del proyecto donde el framework está instalado,
|
|
45
|
+
* por lo que todas las rutas son relativas al proyecto del usuario, no al framework.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // vite.config.ts (en el proyecto del usuario)
|
|
50
|
+
* import { routeGeneratorPlugin } from '@v-ibe/core/vite-plugins';
|
|
51
|
+
*
|
|
52
|
+
* export default defineConfig({
|
|
53
|
+
* plugins: [
|
|
54
|
+
* routeGeneratorPlugin({
|
|
55
|
+
* srcDir: 'app', // carpeta del usuario
|
|
56
|
+
* outputPath: 'app/router/generated-routes.ts', // genera aquí
|
|
57
|
+
* verbose: true
|
|
58
|
+
* })
|
|
59
|
+
* ]
|
|
60
|
+
* });
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export declare function routeGeneratorPlugin(options?: RouteGeneratorPluginOptions): Plugin;
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { scanDirectory } from "../../router/static-analysis/scanner.js";
|
|
6
|
+
const DEFAULT_OPTIONS = {
|
|
7
|
+
srcDir: "app",
|
|
8
|
+
outputPath: "app/router/generated-routes.ts",
|
|
9
|
+
extensions: [".ts", ".tsx"],
|
|
10
|
+
exclude: ["node_modules", "dist", "build", ".git", "framework"],
|
|
11
|
+
verbose: false
|
|
12
|
+
};
|
|
13
|
+
function routeGeneratorPlugin(options = {}) {
|
|
14
|
+
const config = { ...DEFAULT_OPTIONS, ...options };
|
|
15
|
+
let server;
|
|
16
|
+
let projectRoot;
|
|
17
|
+
return {
|
|
18
|
+
name: "vite-plugin-route-generator",
|
|
19
|
+
configResolved(resolvedConfig) {
|
|
20
|
+
projectRoot = resolvedConfig.root;
|
|
21
|
+
log(config, `
|
|
22
|
+
🚀 Route Generator Plugin initialized`);
|
|
23
|
+
log(config, ` Project root: ${projectRoot}`);
|
|
24
|
+
log(config, ` Scanning: ${config.srcDir}`);
|
|
25
|
+
log(config, ` Output: ${config.outputPath}
|
|
26
|
+
`);
|
|
27
|
+
},
|
|
28
|
+
async buildStart() {
|
|
29
|
+
log(config, "\n🔍 Scanning for routes...\n");
|
|
30
|
+
await generateRoutesFile(projectRoot, config);
|
|
31
|
+
},
|
|
32
|
+
configureServer(devServer) {
|
|
33
|
+
server = devServer;
|
|
34
|
+
devServer.watcher.on("change", async (filePath) => {
|
|
35
|
+
if (shouldProcessFile(filePath, config)) {
|
|
36
|
+
log(config, `
|
|
37
|
+
📝 File changed: ${path.basename(filePath)}`);
|
|
38
|
+
await regenerateRoutes(projectRoot, config, server);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
devServer.watcher.on("add", async (filePath) => {
|
|
42
|
+
if (shouldProcessFile(filePath, config)) {
|
|
43
|
+
log(config, `
|
|
44
|
+
➕ File added: ${path.basename(filePath)}`);
|
|
45
|
+
await regenerateRoutes(projectRoot, config, server);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
devServer.watcher.on("unlink", async (filePath) => {
|
|
49
|
+
if (shouldProcessFile(filePath, config)) {
|
|
50
|
+
log(config, `
|
|
51
|
+
➖ File removed: ${path.basename(filePath)}`);
|
|
52
|
+
await regenerateRoutes(projectRoot, config, server);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function generateRoutesFile(projectRoot, config) {
|
|
59
|
+
const srcPath = path.resolve(projectRoot, config.srcDir);
|
|
60
|
+
try {
|
|
61
|
+
const result = await scanDirectory(srcPath, {
|
|
62
|
+
extensions: config.extensions,
|
|
63
|
+
exclude: config.exclude,
|
|
64
|
+
verbose: false
|
|
65
|
+
// Silencioso para no contaminar logs
|
|
66
|
+
});
|
|
67
|
+
if (result.totalRoutes === 0) {
|
|
68
|
+
log(config, `⚠️ No routes found in ${config.srcDir}`);
|
|
69
|
+
log(config, ` Make sure you have classes decorated with @Route`);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
log(config, `✅ Found ${result.totalRoutes} routes in ${result.filesWithRoutes} files`);
|
|
73
|
+
const generatedCode = generateTypeScriptCode(result.routes, projectRoot, config);
|
|
74
|
+
const outputPath = path.resolve(projectRoot, config.outputPath);
|
|
75
|
+
await ensureDirectoryExists(path.dirname(outputPath));
|
|
76
|
+
await fs.writeFile(outputPath, generatedCode, "utf-8");
|
|
77
|
+
log(config, `✅ Routes file generated: ${config.outputPath}
|
|
78
|
+
`);
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error("❌ Error generating routes:", error);
|
|
81
|
+
console.error(" Check that the srcDir exists and contains valid TypeScript files");
|
|
82
|
+
throw error;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function regenerateRoutes(projectRoot, config, server) {
|
|
86
|
+
await generateRoutesFile(projectRoot, config);
|
|
87
|
+
if (server) {
|
|
88
|
+
const outputPath = path.resolve(projectRoot, config.outputPath);
|
|
89
|
+
const module = server.moduleGraph.getModuleById(outputPath);
|
|
90
|
+
if (module) {
|
|
91
|
+
server.moduleGraph.invalidateModule(module);
|
|
92
|
+
server.ws.send({
|
|
93
|
+
type: "full-reload",
|
|
94
|
+
path: "*"
|
|
95
|
+
});
|
|
96
|
+
log(config, "🔄 Hot reload triggered\n");
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
function generateTypeScriptCode(routes, projectRoot, config) {
|
|
101
|
+
const imports = generateImports(routes, projectRoot, config);
|
|
102
|
+
const routesArray = generateRoutesArray(routes, projectRoot, config);
|
|
103
|
+
const typeDefinitions = generateTypeDefinitions();
|
|
104
|
+
const routeTypes = generateRouteTypes(routes);
|
|
105
|
+
return `/**
|
|
106
|
+
* 🚀 Auto-generated routes file
|
|
107
|
+
*
|
|
108
|
+
* This file is automatically generated by vite-plugin-route-generator.
|
|
109
|
+
* Do not edit manually - your changes will be overwritten!
|
|
110
|
+
*
|
|
111
|
+
* Generated at: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
112
|
+
* Total routes: ${routes.length}
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
${imports}
|
|
116
|
+
|
|
117
|
+
${typeDefinitions}
|
|
118
|
+
|
|
119
|
+
${routeTypes}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Array de todas las rutas encontradas en el proyecto
|
|
123
|
+
*
|
|
124
|
+
* Este array es importado automáticamente por el Router durante el bootstrap.
|
|
125
|
+
* No necesitas importarlo manualmente.
|
|
126
|
+
*/
|
|
127
|
+
const generatedRoutes: GeneratedRoute[] = ${routesArray};
|
|
128
|
+
|
|
129
|
+
export default generatedRoutes;
|
|
130
|
+
`;
|
|
131
|
+
}
|
|
132
|
+
function generateImports(routes, projectRoot, config) {
|
|
133
|
+
const policyImports = generatePolicyImports(routes, projectRoot, config);
|
|
134
|
+
if (policyImports.length === 0) {
|
|
135
|
+
return "// All components are lazy loaded with dynamic imports";
|
|
136
|
+
}
|
|
137
|
+
return `// Policy imports
|
|
138
|
+
${policyImports}
|
|
139
|
+
|
|
140
|
+
// All components are lazy loaded with dynamic imports`;
|
|
141
|
+
}
|
|
142
|
+
function generatePolicyImports(routes, projectRoot, config) {
|
|
143
|
+
const policySet = /* @__PURE__ */ new Map();
|
|
144
|
+
routes.forEach((route) => {
|
|
145
|
+
if (route.policies && route.policies.length > 0) {
|
|
146
|
+
route.policies.forEach((policyName) => {
|
|
147
|
+
if (!policySet.has(policyName)) {
|
|
148
|
+
const policyPath = findPolicyFile(policyName, projectRoot, config);
|
|
149
|
+
if (policyPath) {
|
|
150
|
+
policySet.set(policyName, policyPath);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
const imports = [];
|
|
157
|
+
policySet.forEach((filePath, policyName) => {
|
|
158
|
+
const relativePath = getRelativeImportPath(filePath, projectRoot, config);
|
|
159
|
+
imports.push(`import { ${policyName} } from '${relativePath}';`);
|
|
160
|
+
});
|
|
161
|
+
return imports.join("\n");
|
|
162
|
+
}
|
|
163
|
+
function findPolicyFile(policyName, projectRoot, config) {
|
|
164
|
+
const srcDir = path.resolve(projectRoot, config.srcDir);
|
|
165
|
+
const possiblePaths = [
|
|
166
|
+
path.join(srcDir, "policies", `${kebabCase(policyName)}.ts`),
|
|
167
|
+
path.join(srcDir, "policies", `${kebabCase(policyName)}.tsx`),
|
|
168
|
+
path.join(srcDir, "policy", `${kebabCase(policyName)}.ts`),
|
|
169
|
+
path.join(srcDir, "policy", `${kebabCase(policyName)}.tsx`),
|
|
170
|
+
path.join(srcDir, "policies", `${camelToKebab(policyName)}.policy.ts`),
|
|
171
|
+
path.join(srcDir, "policies", `${camelToKebab(policyName)}.policy.tsx`)
|
|
172
|
+
];
|
|
173
|
+
for (const possiblePath of possiblePaths) {
|
|
174
|
+
try {
|
|
175
|
+
if (existsSync(possiblePath)) {
|
|
176
|
+
return possiblePath;
|
|
177
|
+
}
|
|
178
|
+
} catch {
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
return path.join(srcDir, "policies", `${camelToKebab(policyName)}.policy.ts`);
|
|
183
|
+
}
|
|
184
|
+
function camelToKebab(str) {
|
|
185
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").replace(/([A-Z])([A-Z][a-z])/g, "$1-$2").toLowerCase().replace(/-?policy$/, "");
|
|
186
|
+
}
|
|
187
|
+
function kebabCase(str) {
|
|
188
|
+
return str.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
|
|
189
|
+
}
|
|
190
|
+
function generateRoutesArray(routes, projectRoot, config) {
|
|
191
|
+
const routeObjects = routes.map((route) => {
|
|
192
|
+
const relativePath = getRelativeImportPath(route.filePath, projectRoot, config);
|
|
193
|
+
const metadata = route.metadata ? JSON.stringify(route.metadata) : "undefined";
|
|
194
|
+
const policies = route.policies ? `[${route.policies.join(", ")}]` : "undefined";
|
|
195
|
+
const slot = route.slot ? `'${route.slot}'` : "undefined";
|
|
196
|
+
const routeId = randomUUID();
|
|
197
|
+
return ` {
|
|
198
|
+
id: '${routeId}',
|
|
199
|
+
path: '${route.path}',
|
|
200
|
+
className: '${route.className}',
|
|
201
|
+
loader: async (signal?: AbortSignal) => {
|
|
202
|
+
const module = await import('${relativePath}');
|
|
203
|
+
return { default: module.${route.className} };
|
|
204
|
+
},
|
|
205
|
+
metadata: ${metadata},
|
|
206
|
+
policies: ${policies},
|
|
207
|
+
slot: ${slot},
|
|
208
|
+
}`;
|
|
209
|
+
});
|
|
210
|
+
return `[
|
|
211
|
+
${routeObjects.join(",\n")}
|
|
212
|
+
]`;
|
|
213
|
+
}
|
|
214
|
+
function generateTypeDefinitions(routes) {
|
|
215
|
+
return `// Types will be defined after Routes type is generated
|
|
216
|
+
`;
|
|
217
|
+
}
|
|
218
|
+
function extractRouteParams(path2) {
|
|
219
|
+
const matches = path2.match(/:([a-zA-Z0-9_]+)/g);
|
|
220
|
+
if (!matches) return [];
|
|
221
|
+
return matches.map((match) => match.slice(1));
|
|
222
|
+
}
|
|
223
|
+
function generateRouteTypes(routes) {
|
|
224
|
+
const pathParamsMap = /* @__PURE__ */ new Map();
|
|
225
|
+
routes.forEach((route) => {
|
|
226
|
+
if (!pathParamsMap.has(route.path)) {
|
|
227
|
+
pathParamsMap.set(route.path, extractRouteParams(route.path));
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const paramTypes = Array.from(pathParamsMap.entries()).map(([path2, params]) => {
|
|
231
|
+
if (params.length === 0) {
|
|
232
|
+
return ` '${path2}': Record<string, never>;`;
|
|
233
|
+
}
|
|
234
|
+
const paramObject = params.map((p) => `${p}: string`).join("; ");
|
|
235
|
+
return ` '${path2}': { ${paramObject} };`;
|
|
236
|
+
}).join("\n");
|
|
237
|
+
return `/**
|
|
238
|
+
* 🎯 Tipos de rutas generados automáticamente
|
|
239
|
+
*
|
|
240
|
+
* Estos tipos proporcionan autocompletado y validación de tipos para router.navigate()
|
|
241
|
+
*/
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Mapeo de todas las rutas a sus parámetros requeridos
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* // Ruta sin parámetros
|
|
248
|
+
* Routes['/'] -> Record<string, never>
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* // Ruta con parámetros
|
|
252
|
+
* Routes['/store/:storeId'] -> { storeId: string }
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* // Obtener todas las rutas disponibles
|
|
256
|
+
* type AllPaths = keyof Routes; // '/' | '/callback' | '/store/:storeId' | ...
|
|
257
|
+
*/
|
|
258
|
+
export type Routes = {
|
|
259
|
+
${paramTypes}
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Tipo para una ruta generada
|
|
264
|
+
* El path está tipado con las rutas disponibles (keyof Routes)
|
|
265
|
+
*/
|
|
266
|
+
export interface GeneratedRoute {
|
|
267
|
+
id: string;
|
|
268
|
+
path: keyof Routes;
|
|
269
|
+
className: string;
|
|
270
|
+
loader: (signal?: AbortSignal) => Promise<{ default: any }>;
|
|
271
|
+
metadata?: Record<string, any>;
|
|
272
|
+
policies?: (new (...args: any[]) => any)[];
|
|
273
|
+
slot?: string;
|
|
274
|
+
}
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
function getRelativeImportPath(absolutePath, projectRoot, config) {
|
|
278
|
+
const outputDir = path.dirname(path.join(projectRoot, config.outputPath));
|
|
279
|
+
const relativePath = path.relative(outputDir, absolutePath);
|
|
280
|
+
const withoutExt = relativePath.replace(/\.(ts|tsx)$/, "");
|
|
281
|
+
const normalized = withoutExt.startsWith(".") ? withoutExt : `./${withoutExt}`;
|
|
282
|
+
return normalized.replace(/\\/g, "/");
|
|
283
|
+
}
|
|
284
|
+
function shouldProcessFile(filePath, config) {
|
|
285
|
+
if (!config.extensions.some((ext) => filePath.endsWith(ext))) {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
if (config.exclude.some((excluded) => filePath.includes(excluded))) {
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
if (filePath.includes("generated-routes")) {
|
|
292
|
+
return false;
|
|
293
|
+
}
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
async function ensureDirectoryExists(dirPath) {
|
|
297
|
+
try {
|
|
298
|
+
await fs.access(dirPath);
|
|
299
|
+
} catch {
|
|
300
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function log(config, message) {
|
|
304
|
+
if (config.verbose) {
|
|
305
|
+
console.log(message);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
export {
|
|
309
|
+
routeGeneratorPlugin
|
|
310
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@v-ibe/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A reactive framework for SPAs using signals, class-based web components, and JSX with direct DOM updates",
|
|
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
|
+
"default": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./jsx-runtime": {
|
|
15
|
+
"types": "./dist/jsx-runtime.d.ts",
|
|
16
|
+
"import": "./dist/jsx-runtime.js",
|
|
17
|
+
"default": "./dist/jsx-runtime.js"
|
|
18
|
+
},
|
|
19
|
+
"./jsx-dev-runtime": {
|
|
20
|
+
"types": "./dist/jsx-dev-runtime.d.ts",
|
|
21
|
+
"import": "./dist/jsx-dev-runtime.js",
|
|
22
|
+
"default": "./dist/jsx-dev-runtime.js"
|
|
23
|
+
},
|
|
24
|
+
"./vite-plugins": {
|
|
25
|
+
"types": "./dist/vite-plugins/index.d.ts",
|
|
26
|
+
"import": "./dist/vite-plugins/index.js",
|
|
27
|
+
"default": "./dist/vite-plugins/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./app-entry": {
|
|
30
|
+
"types": "./dist/app-entry.d.ts",
|
|
31
|
+
"import": "./dist/app-entry.js",
|
|
32
|
+
"default": "./dist/app-entry.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
"dist",
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"build": "vite build",
|
|
42
|
+
"dev": "vite --config vite.config.dev.ts",
|
|
43
|
+
"prepublishOnly": "npm run build",
|
|
44
|
+
"clean": "rm -rf dist",
|
|
45
|
+
"test:parser": "tsx src/router/static-analysis/test.ts",
|
|
46
|
+
"test:scanner": "tsx src/router/static-analysis/test-scanner.ts",
|
|
47
|
+
"test:class-decorator": "tsx src/router/static-analysis/test-class-decorator.ts",
|
|
48
|
+
"test:vite-plugin": "tsx src/vite-plugins/router/test-plugin.ts",
|
|
49
|
+
"test": "vitest",
|
|
50
|
+
"test:ui": "vitest --ui",
|
|
51
|
+
"test:run": "vitest run",
|
|
52
|
+
"test:coverage": "vitest run --coverage"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"framework",
|
|
56
|
+
"signals",
|
|
57
|
+
"reactive",
|
|
58
|
+
"web-components",
|
|
59
|
+
"jsx",
|
|
60
|
+
"typescript"
|
|
61
|
+
],
|
|
62
|
+
"author": "Julian Vargas <arboledavargas@outlook.com> (https://github.com/arboledavargas)",
|
|
63
|
+
"homepage": "https://v-ibe.com",
|
|
64
|
+
"license": "MIT",
|
|
65
|
+
"repository": {
|
|
66
|
+
"type": "git",
|
|
67
|
+
"url": "git+https://github.com/arboledavargas/v-ibe.git"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"typescript": ">=5.0.0",
|
|
71
|
+
"vite": "^7.1.3"
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"@types/node": "^24.3.0",
|
|
75
|
+
"@vitest/ui": "^4.0.17",
|
|
76
|
+
"happy-dom": "^20.3.1",
|
|
77
|
+
"jsdom": "^27.4.0",
|
|
78
|
+
"postcss": "^8.5.6",
|
|
79
|
+
"tsx": "^4.19.2",
|
|
80
|
+
"typescript": "^5.9.2",
|
|
81
|
+
"vite": "^7.1.3",
|
|
82
|
+
"vite-plugin-dts": "^4.3.0",
|
|
83
|
+
"vitest": "^4.0.17"
|
|
84
|
+
}
|
|
85
|
+
}
|