@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.
Files changed (250) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +40 -0
  3. package/dist/DI/__tests__/scoped-container-dependencies.test.d.ts +1 -0
  4. package/dist/DI/bootstrap.d.ts +18 -0
  5. package/dist/DI/decorators/inject.d.ts +37 -0
  6. package/dist/DI/decorators/inject.js +45 -0
  7. package/dist/DI/decorators/service.d.ts +24 -0
  8. package/dist/DI/decorators/service.js +13 -0
  9. package/dist/DI/di-container.d.ts +53 -0
  10. package/dist/DI/di-container.js +158 -0
  11. package/dist/DI/lifecycle.d.ts +37 -0
  12. package/dist/DI/lifecycle.js +6 -0
  13. package/dist/DI/scoped-container.d.ts +68 -0
  14. package/dist/DI/scoped-container.js +193 -0
  15. package/dist/DI/service-metadata.d.ts +32 -0
  16. package/dist/DI/service-metadata.js +31 -0
  17. package/dist/DI/types.d.ts +4 -0
  18. package/dist/behaviors/__tests__/behavior-system.test.d.ts +1 -0
  19. package/dist/behaviors/behavior-manager.d.ts +60 -0
  20. package/dist/behaviors/behavior-manager.js +131 -0
  21. package/dist/behaviors/behavior-registry.d.ts +68 -0
  22. package/dist/behaviors/behavior-registry.js +105 -0
  23. package/dist/behaviors/constants.d.ts +16 -0
  24. package/dist/behaviors/constants.js +8 -0
  25. package/dist/behaviors/decorators.d.ts +87 -0
  26. package/dist/behaviors/decorators.js +46 -0
  27. package/dist/behaviors/index.d.ts +4 -0
  28. package/dist/components/__tests__/host.test.d.ts +1 -0
  29. package/dist/components/app-tree.d.ts +49 -0
  30. package/dist/components/app-tree.js +122 -0
  31. package/dist/components/base-component.d.ts +85 -0
  32. package/dist/components/base-component.js +438 -0
  33. package/dist/components/decorators/component.d.ts +27 -0
  34. package/dist/components/decorators/component.js +47 -0
  35. package/dist/components/decorators/prop.d.ts +14 -0
  36. package/dist/components/decorators/prop.js +37 -0
  37. package/dist/components/types.d.ts +26 -0
  38. package/dist/core.d.ts +23 -0
  39. package/dist/core.js +8 -0
  40. package/dist/custom-components/__tests__/for.test.d.ts +1 -0
  41. package/dist/custom-components/__tests__/show.test.d.ts +1 -0
  42. package/dist/custom-components/for.d.ts +58 -0
  43. package/dist/custom-components/for.js +313 -0
  44. package/dist/custom-components/index.d.ts +2 -0
  45. package/dist/custom-components/show.d.ts +78 -0
  46. package/dist/custom-components/show.js +88 -0
  47. package/dist/data-management/cache/cache-invalidate.decorator.d.ts +35 -0
  48. package/dist/data-management/cache/cache-invalidate.decorator.js +21 -0
  49. package/dist/data-management/cache/cache-metadata.d.ts +15 -0
  50. package/dist/data-management/cache/cache-provider.interface.d.ts +67 -0
  51. package/dist/data-management/cache/cache-tags.decorator.d.ts +52 -0
  52. package/dist/data-management/cache/cache-tags.decorator.js +13 -0
  53. package/dist/data-management/cache/cache-update.decorator.d.ts +28 -0
  54. package/dist/data-management/cache/cache-update.decorator.js +21 -0
  55. package/dist/data-management/cache/cache.decorator.d.ts +28 -0
  56. package/dist/data-management/cache/cache.decorator.js +13 -0
  57. package/dist/data-management/cache/index.d.ts +11 -0
  58. package/dist/data-management/cache/local-storage-cache.d.ts +40 -0
  59. package/dist/data-management/cache/local-storage-cache.js +268 -0
  60. package/dist/data-management/cache/memory-cache.d.ts +37 -0
  61. package/dist/data-management/cache/memory-cache.js +149 -0
  62. package/dist/data-management/cache/session-storage-cache.d.ts +35 -0
  63. package/dist/data-management/cache/session-storage-cache.js +242 -0
  64. package/dist/data-management/cache/ttl.decorator.d.ts +31 -0
  65. package/dist/data-management/cache/ttl.decorator.js +34 -0
  66. package/dist/data-management/decorators/consume.d.ts +29 -0
  67. package/dist/data-management/decorators/consume.js +28 -0
  68. package/dist/data-management/decorators/id.d.ts +28 -0
  69. package/dist/data-management/decorators/id.js +19 -0
  70. package/dist/data-management/decorators/model.d.ts +48 -0
  71. package/dist/data-management/decorators/model.js +24 -0
  72. package/dist/data-management/decorators/prop.d.ts +43 -0
  73. package/dist/data-management/decorators/prop.js +32 -0
  74. package/dist/data-management/index.d.ts +13 -0
  75. package/dist/data-management/store/json-to-model.d.ts +45 -0
  76. package/dist/data-management/store/json-to-model.js +36 -0
  77. package/dist/data-management/store/store.d.ts +108 -0
  78. package/dist/data-management/store/store.js +207 -0
  79. package/dist/data-management/store/types.d.ts +53 -0
  80. package/dist/events-handler/decorators/emit.d.ts +29 -0
  81. package/dist/events-handler/decorators/emit.js +51 -0
  82. package/dist/events-handler/event-decorators.d.ts +1 -0
  83. package/dist/events-handler/event-emitter.service.d.ts +21 -0
  84. package/dist/events-handler/event-emitter.service.js +85 -0
  85. package/dist/events-handler/event-types.d.ts +12 -0
  86. package/dist/index.d.ts +55 -0
  87. package/dist/index.js +121 -0
  88. package/dist/jsx/dynamic/__tests__/granular-array-renderer.test.d.ts +1 -0
  89. package/dist/jsx/dynamic/__tests__/jsx-array-rendering.test.d.ts +1 -0
  90. package/dist/jsx/dynamic/array-renderer.d.ts +2 -0
  91. package/dist/jsx/dynamic/array-renderer.js +133 -0
  92. package/dist/jsx/dynamic/child-renderer.d.ts +1 -0
  93. package/dist/jsx/dynamic/child-renderer.js +180 -0
  94. package/dist/jsx/dynamic/dom-utils.d.ts +5 -0
  95. package/dist/jsx/dynamic/dom-utils.js +22 -0
  96. package/dist/jsx/dynamic/granular-array-renderer.d.ts +16 -0
  97. package/dist/jsx/dynamic/granular-array-renderer.js +153 -0
  98. package/dist/jsx/dynamic/node-renderer.d.ts +2 -0
  99. package/dist/jsx/dynamic/props-handler.d.ts +3 -0
  100. package/dist/jsx/dynamic/props-handler.js +281 -0
  101. package/dist/jsx/dynamic/text-renderer.d.ts +2 -0
  102. package/dist/jsx/jsx-dev-runtime.d.ts +2 -0
  103. package/dist/jsx/jsx-runtime.d.ts +3 -0
  104. package/dist/jsx/types.d.ts +35 -0
  105. package/dist/jsx/types.js +4 -0
  106. package/dist/jsx-dev-runtime.d.ts +2 -0
  107. package/dist/jsx-dev-runtime.js +8 -0
  108. package/dist/jsx-runtime.d.ts +2 -0
  109. package/dist/jsx-runtime.js +11 -0
  110. package/dist/reactivity/__tests__/context-stack.test.d.ts +1 -0
  111. package/dist/reactivity/__tests__/nested-effects-untrack.test.d.ts +22 -0
  112. package/dist/reactivity/context-scope.d.ts +57 -0
  113. package/dist/reactivity/context-scope.js +35 -0
  114. package/dist/reactivity/decorators/__tests__/ctx-integration.test.d.ts +5 -0
  115. package/dist/reactivity/decorators/__tests__/ctx-loop.test.d.ts +10 -0
  116. package/dist/reactivity/decorators/__tests__/state-intelligent.test.d.ts +1 -0
  117. package/dist/reactivity/decorators/computed.d.ts +6 -0
  118. package/dist/reactivity/decorators/computed.js +17 -0
  119. package/dist/reactivity/decorators/create-event-decorator.d.ts +5 -0
  120. package/dist/reactivity/decorators/create-event-decorator.js +28 -0
  121. package/dist/reactivity/decorators/ctx.d.ts +9 -0
  122. package/dist/reactivity/decorators/ctx.js +91 -0
  123. package/dist/reactivity/decorators/effect.d.ts +9 -0
  124. package/dist/reactivity/decorators/effect.js +24 -0
  125. package/dist/reactivity/decorators/resource.d.ts +48 -0
  126. package/dist/reactivity/decorators/resource.js +20 -0
  127. package/dist/reactivity/decorators/state.d.ts +8 -0
  128. package/dist/reactivity/decorators/state.js +68 -0
  129. package/dist/reactivity/decorators/store.d.ts +6 -0
  130. package/dist/reactivity/decorators/store.js +25 -0
  131. package/dist/reactivity/phase-scheduler.d.ts +81 -0
  132. package/dist/reactivity/phase-scheduler.js +88 -0
  133. package/dist/reactivity/phase-scheduler.test.d.ts +1 -0
  134. package/dist/reactivity/reactive-cache.d.ts +21 -0
  135. package/dist/reactivity/reactive-cache.js +31 -0
  136. package/dist/reactivity/reactive-cache.test.d.ts +1 -0
  137. package/dist/reactivity/reactive-context.d.ts +152 -0
  138. package/dist/reactivity/reactive-context.js +184 -0
  139. package/dist/reactivity/signals/__tests__/composicion-automatica.test.d.ts +1 -0
  140. package/dist/reactivity/signals/__tests__/composite/nivel-1-estructura-basica.test.d.ts +1 -0
  141. package/dist/reactivity/signals/__tests__/composite/nivel-2-registro-subscribers.test.d.ts +1 -0
  142. package/dist/reactivity/signals/__tests__/composite/nivel-3-notificaciones-basicas.test.d.ts +1 -0
  143. package/dist/reactivity/signals/__tests__/composite/nivel-4-comparacion-valores.test.d.ts +1 -0
  144. package/dist/reactivity/signals/__tests__/composite/nivel-5-tracking-automatico.test.d.ts +1 -0
  145. package/dist/reactivity/signals/__tests__/composite/nivel-6-anti-glitch.test.d.ts +1 -0
  146. package/dist/reactivity/signals/__tests__/composite/nivel-7-objetos-anidados.test.d.ts +1 -0
  147. package/dist/reactivity/signals/__tests__/composite/nivel-8-observable-array-support.test.d.ts +1 -0
  148. package/dist/reactivity/signals/__tests__/composite-shallow-tracking.test.d.ts +1 -0
  149. package/dist/reactivity/signals/__tests__/effect.test.d.ts +1 -0
  150. package/dist/reactivity/signals/__tests__/reactive-array/nivel-1-estructura-basica.test.d.ts +1 -0
  151. package/dist/reactivity/signals/__tests__/reactive-array/nivel-2-metodos-mutadores.test.d.ts +1 -0
  152. package/dist/reactivity/signals/__tests__/reactive-array/nivel-3-tracking-por-indice.test.d.ts +1 -0
  153. package/dist/reactivity/signals/__tests__/reactive-array/nivel-4-tracking-length.test.d.ts +1 -0
  154. package/dist/reactivity/signals/__tests__/reactive-array/nivel-5-tracking-mutation.test.d.ts +1 -0
  155. package/dist/reactivity/signals/__tests__/reactive-array/nivel-6-metodos-no-mutadores.test.d.ts +1 -0
  156. package/dist/reactivity/signals/__tests__/reactive-array/nivel-7-composicion-bidireccional.test.d.ts +1 -0
  157. package/dist/reactivity/signals/__tests__/reactive-array/nivel-8-proxies.test.d.ts +1 -0
  158. package/dist/reactivity/signals/__tests__/reactive-array/nivel-9-derived-cache-optimization.test.d.ts +1 -0
  159. package/dist/reactivity/signals/__tests__/resource.test.d.ts +1 -0
  160. package/dist/reactivity/signals/__tests__/signal.test.d.ts +1 -0
  161. package/dist/reactivity/signals/array-strategies.d.ts +120 -0
  162. package/dist/reactivity/signals/array-strategies.js +261 -0
  163. package/dist/reactivity/signals/composite.d.ts +89 -0
  164. package/dist/reactivity/signals/composite.js +145 -0
  165. package/dist/reactivity/signals/computed.d.ts +61 -0
  166. package/dist/reactivity/signals/computed.js +107 -0
  167. package/dist/reactivity/signals/computed.test.d.ts +1 -0
  168. package/dist/reactivity/signals/derived.d.ts +10 -0
  169. package/dist/reactivity/signals/derived.js +24 -0
  170. package/dist/reactivity/signals/effect.d.ts +27 -0
  171. package/dist/reactivity/signals/effect.js +46 -0
  172. package/dist/reactivity/signals/event.d.ts +9 -0
  173. package/dist/reactivity/signals/event.js +15 -0
  174. package/dist/reactivity/signals/reactive-array.d.ts +133 -0
  175. package/dist/reactivity/signals/reactive-array.js +490 -0
  176. package/dist/reactivity/signals/reactive-proxy.d.ts +54 -0
  177. package/dist/reactivity/signals/reactive-proxy.js +299 -0
  178. package/dist/reactivity/signals/reactive-tracking.test.d.ts +1 -0
  179. package/dist/reactivity/signals/resource.d.ts +9 -0
  180. package/dist/reactivity/signals/resource.js +58 -0
  181. package/dist/reactivity/signals/signal.d.ts +39 -0
  182. package/dist/reactivity/signals/signal.js +56 -0
  183. package/dist/reactivity/signals/subscription-management.test.d.ts +1 -0
  184. package/dist/reactivity/types.d.ts +12 -0
  185. package/dist/router/__tests__/link-behavior-active-class.test.d.ts +1 -0
  186. package/dist/router/__tests__/loop-detector.test.d.ts +1 -0
  187. package/dist/router/__tests__/params-container-resolution.test.d.ts +1 -0
  188. package/dist/router/__tests__/router-generated-routes.test.d.ts +1 -0
  189. package/dist/router/__tests__/router-params-granular.test.d.ts +1 -0
  190. package/dist/router/__tests__/router-params-simple.test.d.ts +1 -0
  191. package/dist/router/__tests__/router-query-params.test.d.ts +1 -0
  192. package/dist/router/__tests__/router-route-candidates.test.d.ts +1 -0
  193. package/dist/router/__tests__/routeview-app-articles.test.d.ts +1 -0
  194. package/dist/router/__tests__/routeview-debug.test.d.ts +1 -0
  195. package/dist/router/__tests__/routeview-integration.test.d.ts +1 -0
  196. package/dist/router/__tests__/routeview-this.test.d.ts +1 -0
  197. package/dist/router/decorators/base-policy.d.ts +141 -0
  198. package/dist/router/decorators/base-policy.js +63 -0
  199. package/dist/router/decorators/index.d.ts +6 -0
  200. package/dist/router/decorators/params.d.ts +31 -0
  201. package/dist/router/decorators/params.js +97 -0
  202. package/dist/router/decorators/route-metadata.d.ts +11 -0
  203. package/dist/router/decorators/route-metadata.js +23 -0
  204. package/dist/router/decorators/route.d.ts +39 -0
  205. package/dist/router/decorators/route.js +7 -0
  206. package/dist/router/link.behavior.d.ts +87 -0
  207. package/dist/router/link.behavior.js +227 -0
  208. package/dist/router/policy-evaluator.d.ts +81 -0
  209. package/dist/router/policy-evaluator.js +209 -0
  210. package/dist/router/route-view.d.ts +56 -0
  211. package/dist/router/route-view.js +156 -0
  212. package/dist/router/router.d.ts +67 -0
  213. package/dist/router/router.js +308 -0
  214. package/dist/router/static-analysis/index.d.ts +37 -0
  215. package/dist/router/static-analysis/parser.d.ts +14 -0
  216. package/dist/router/static-analysis/parser.js +147 -0
  217. package/dist/router/static-analysis/scanner.d.ts +27 -0
  218. package/dist/router/static-analysis/scanner.js +91 -0
  219. package/dist/router/trie.d.ts +14 -0
  220. package/dist/router/trie.js +126 -0
  221. package/dist/router/trie.types.d.ts +36 -0
  222. package/dist/styles/base-style-sheet.d.ts +96 -0
  223. package/dist/styles/base-style-sheet.js +149 -0
  224. package/dist/styles/decorators/factories.d.ts +76 -0
  225. package/dist/styles/decorators/factories.js +11 -0
  226. package/dist/styles/decorators/keyframes.d.ts +238 -0
  227. package/dist/styles/decorators/keyframes.js +79 -0
  228. package/dist/styles/decorators/rule.d.ts +177 -0
  229. package/dist/styles/decorators/rule.js +72 -0
  230. package/dist/styles/decorators/scope.d.ts +66 -0
  231. package/dist/styles/decorators/scope.js +17 -0
  232. package/dist/styles/decorators/style.d.ts +1 -0
  233. package/dist/styles/decorators/style.js +20 -0
  234. package/dist/styles/decorators/useStyles.d.ts +5 -0
  235. package/dist/styles/decorators/useStyles.js +29 -0
  236. package/dist/styles/global-styles-registry.d.ts +72 -0
  237. package/dist/styles/global-styles-registry.js +155 -0
  238. package/dist/types.d.ts +1 -0
  239. package/dist/vite-plugins/__tests__/jsx-control-flow-transform.test.d.ts +1 -0
  240. package/dist/vite-plugins/index.d.ts +4 -0
  241. package/dist/vite-plugins/index.js +10 -0
  242. package/dist/vite-plugins/jsx-contextual.d.ts +7 -0
  243. package/dist/vite-plugins/jsx-contextual.js +53 -0
  244. package/dist/vite-plugins/jsx-control-flow-transform.d.ts +60 -0
  245. package/dist/vite-plugins/jsx-control-flow-transform.js +180 -0
  246. package/dist/vite-plugins/jsx-signals.d.ts +2 -0
  247. package/dist/vite-plugins/jsx-signals.js +124 -0
  248. package/dist/vite-plugins/router/route-generator-plugin.d.ts +63 -0
  249. package/dist/vite-plugins/router/route-generator-plugin.js +310 -0
  250. 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
+ }