@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Julian Vargas
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # v-ibe
2
+
3
+ Modern framework for single page applications.
4
+
5
+ > **Alpha** — Core is stable but the API may change before 1.0. Not recommended for production yet.
6
+
7
+ ---
8
+
9
+ **v-ibe** is an opinionated front-end framework for building SPAs using persistent class-based components, signals, and direct DOM updates. No virtual DOM, no hooks, no re-renders.
10
+
11
+ ## Hello World
12
+
13
+ ```typescript
14
+ @Component()
15
+ export class HelloWorld extends BaseComponent {
16
+ @State name = 'World';
17
+
18
+ view() {
19
+ return (
20
+ <h1 onClick={() => this.name = 'Signals'}>
21
+ Hello {this.name}
22
+ </h1>
23
+ );
24
+ }
25
+ }
26
+ ```
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install @v-ibe/core
32
+ ```
33
+
34
+ ## Documentation
35
+
36
+ [https://v-ibe.com](https://v-ibe.com)
37
+
38
+ ## License
39
+
40
+ MIT
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Bootstrap function to register all services marked with @Service decorator
3
+ * and initialize them in topological order.
4
+ *
5
+ * This should be called once at application startup, before rendering components.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { bootstrap } from './framework';
10
+ *
11
+ * // Register all services and bootstrap
12
+ * await bootstrap();
13
+ *
14
+ * // Now render your app
15
+ * document.getElementById('root')!.innerHTML = '<my-app></my-app>';
16
+ * ```
17
+ */
18
+ export declare function bootstrap(): Promise<void>;
@@ -0,0 +1,37 @@
1
+ import { Constructor } from '../types';
2
+ /**
3
+ * Decorator to inject a service dependency from the global DI container
4
+ *
5
+ * Works by creating a lazy getter that retrieves the service from the container
6
+ * associated with the instance. The value is cached after first access.
7
+ *
8
+ * @param ctor - Constructor of the service to inject
9
+ *
10
+ * @example In a service
11
+ * ```typescript
12
+ * @Service
13
+ * class AuthService {
14
+ * @Inject(HttpClient) http!: HttpClient;
15
+ * @Inject(ConfigService) config!: ConfigService;
16
+ *
17
+ * async login(credentials: Credentials) {
18
+ * const url = this.config.getApiUrl();
19
+ * return this.http.post(url, credentials);
20
+ * }
21
+ * }
22
+ * ```
23
+ *
24
+ * @example In a component
25
+ * ```typescript
26
+ * @Component
27
+ * class MyComponent extends BaseComponent {
28
+ * @Inject(Router) router!: Router;
29
+ * @Inject(AuthService) auth!: AuthService;
30
+ *
31
+ * view() {
32
+ * return <div>Usuario: {this.auth.currentUser}</div>;
33
+ * }
34
+ * }
35
+ * ```
36
+ */
37
+ export declare function Inject(ctor: Constructor): (_: undefined, ctx: ClassFieldDecoratorContext) => void;
@@ -0,0 +1,45 @@
1
+ import { DEPENDENCIES_KEY } from "./service.js";
2
+ function Inject(ctor) {
3
+ return function(_, ctx) {
4
+ if (ctx.kind !== "field") {
5
+ throw new Error("@Inject solo puede usarse en fields");
6
+ }
7
+ if (!ctx.metadata[DEPENDENCIES_KEY]) {
8
+ ctx.metadata[DEPENDENCIES_KEY] = /* @__PURE__ */ new Set();
9
+ }
10
+ ctx.metadata[DEPENDENCIES_KEY].add(ctor);
11
+ ctx.addInitializer(function() {
12
+ const privateKey = Symbol(`__injected_${String(ctx.name)}`);
13
+ Object.defineProperty(this, ctx.name, {
14
+ enumerable: true,
15
+ configurable: true,
16
+ get() {
17
+ if (this[privateKey]) {
18
+ return this[privateKey];
19
+ }
20
+ const container = this.__container;
21
+ if (!container) {
22
+ throw new Error(
23
+ `@Inject(${ctor.name}): No container found on ${this.constructor?.name || "unknown"}. Ensure this instance is within a component tree that provides ${ctor.name}.`
24
+ );
25
+ }
26
+ const inst = container.get(ctor);
27
+ Object.defineProperty(this, ctx.name, {
28
+ value: inst,
29
+ writable: true,
30
+ // ← Permitir override en tests
31
+ configurable: true
32
+ // ← Permitir redefinir en tests
33
+ });
34
+ return inst;
35
+ },
36
+ set(value) {
37
+ this[privateKey] = value;
38
+ }
39
+ });
40
+ });
41
+ };
42
+ }
43
+ export {
44
+ Inject
45
+ };
@@ -0,0 +1,24 @@
1
+ import { Constructor } from '../types';
2
+ declare const DEPENDENCIES_KEY: unique symbol;
3
+ /**
4
+ * Decorator to mark a class as a Service
5
+ * Only stores metadata - actual registration happens when container is created
6
+ * All services are bootstrapped eagerly during container bootstrap
7
+ *
8
+ * @example
9
+ * ```typescript
10
+ * @Service
11
+ * class AuthService {
12
+ * @Inject(HttpClient) http!: HttpClient;
13
+ *
14
+ * async login(credentials: Credentials) {
15
+ * return this.http.post('/auth/login', credentials);
16
+ * }
17
+ * }
18
+ * ```
19
+ */
20
+ export declare function Service<T extends Constructor>(ctor: T, ctx: ClassDecoratorContext): T;
21
+ /**
22
+ * Export the dependencies key for use by @Inject decorator
23
+ */
24
+ export { DEPENDENCIES_KEY };
@@ -0,0 +1,13 @@
1
+ import { registerServiceMetadata } from "../service-metadata.js";
2
+ const DEPENDENCIES_KEY = Symbol("dependencies");
3
+ function Service(ctor, ctx) {
4
+ const dependencies = ctx.metadata[DEPENDENCIES_KEY];
5
+ registerServiceMetadata(ctor, {
6
+ dependencies: dependencies || /* @__PURE__ */ new Set()
7
+ });
8
+ return ctor;
9
+ }
10
+ export {
11
+ DEPENDENCIES_KEY,
12
+ Service
13
+ };
@@ -0,0 +1,53 @@
1
+ import { Constructor } from './types';
2
+ /**
3
+ * Singleton global dependency injection container
4
+ *
5
+ * Uses topological sort (Kahn's algorithm) to bootstrap services in correct dependency order.
6
+ * All services are eagerly initialized during bootstrap.
7
+ */
8
+ export declare class DIContainer {
9
+ #private;
10
+ /**
11
+ * Register a service constructor
12
+ */
13
+ register(token: Constructor): void;
14
+ /**
15
+ * Register a dependency relationship between services
16
+ * @param parent - The service that depends on another
17
+ * @param dependency - The service that parent depends on
18
+ */
19
+ registerDependency(parent: Constructor, dependency: Constructor): void;
20
+ /**
21
+ * Bootstrap all services in dependency order
22
+ * All services are eagerly initialized during bootstrap
23
+ * Each instance is associated with this container for property injection
24
+ */
25
+ bootstrap(): Promise<void>;
26
+ /**
27
+ * Get the container associated with an instance
28
+ * Useful for property injection (fallback for @Inject)
29
+ */
30
+ static getContainerForInstance(instance: any): DIContainer | undefined;
31
+ /**
32
+ * Get a service instance
33
+ * All services must be bootstrapped before calling get()
34
+ */
35
+ get<T>(ctor: Constructor<T>): T;
36
+ /**
37
+ * Get all service instances
38
+ * Useful for collecting metadata from all services after bootstrap
39
+ */
40
+ getAllInstances(): any[];
41
+ /**
42
+ * Check if bootstrap has been called
43
+ */
44
+ get isReady(): boolean;
45
+ /**
46
+ * Dispose all services and reset container
47
+ */
48
+ dispose(): void;
49
+ }
50
+ /**
51
+ * Global singleton container instance
52
+ */
53
+ export declare const services: DIContainer;
@@ -0,0 +1,158 @@
1
+ import { hasLifecycle } from "./lifecycle.js";
2
+ class DIContainer {
3
+ #singletons = /* @__PURE__ */ new Map();
4
+ #registered = /* @__PURE__ */ new Set();
5
+ // Dependency graph for topological sort
6
+ #dependencies = /* @__PURE__ */ new Map();
7
+ // What each service depends on
8
+ #dependents = /* @__PURE__ */ new Map();
9
+ // What depends on each service
10
+ #ready = false;
11
+ /**
12
+ * Register a service constructor
13
+ */
14
+ register(token) {
15
+ this.#registered.add(token);
16
+ if (!this.#dependencies.has(token)) {
17
+ this.#dependencies.set(token, /* @__PURE__ */ new Set());
18
+ }
19
+ if (!this.#dependents.has(token)) {
20
+ this.#dependents.set(token, /* @__PURE__ */ new Set());
21
+ }
22
+ }
23
+ /**
24
+ * Register a dependency relationship between services
25
+ * @param parent - The service that depends on another
26
+ * @param dependency - The service that parent depends on
27
+ */
28
+ registerDependency(parent, dependency) {
29
+ if (!this.#registered.has(parent)) {
30
+ throw new Error(
31
+ `Cannot register dependency: ${parent.name} is not registered. Use @Service decorator first.`
32
+ );
33
+ }
34
+ if (!this.#registered.has(dependency)) {
35
+ throw new Error(
36
+ `Cannot register dependency: ${dependency.name} is not registered. Use @Service decorator first.`
37
+ );
38
+ }
39
+ if (!this.#dependencies.has(parent)) {
40
+ this.#dependencies.set(parent, /* @__PURE__ */ new Set());
41
+ }
42
+ this.#dependencies.get(parent).add(dependency);
43
+ if (!this.#dependents.has(dependency)) {
44
+ this.#dependents.set(dependency, /* @__PURE__ */ new Set());
45
+ }
46
+ this.#dependents.get(dependency).add(parent);
47
+ }
48
+ /**
49
+ * Get bootstrap order using topological sort (Kahn's algorithm)
50
+ * This ensures dependencies are initialized before dependents
51
+ */
52
+ async *#getBootstrapOrder() {
53
+ const inDegree = /* @__PURE__ */ new Map();
54
+ const queue = [];
55
+ for (const service of this.#registered) {
56
+ const deps = this.#dependencies.get(service) || /* @__PURE__ */ new Set();
57
+ inDegree.set(service, deps.size);
58
+ if (deps.size === 0) {
59
+ queue.push(service);
60
+ }
61
+ }
62
+ while (queue.length > 0) {
63
+ const service = queue.shift();
64
+ yield service;
65
+ const dependents = this.#dependents.get(service) || /* @__PURE__ */ new Set();
66
+ for (const dependent of dependents) {
67
+ const newInDegree = inDegree.get(dependent) - 1;
68
+ inDegree.set(dependent, newInDegree);
69
+ if (newInDegree === 0) {
70
+ queue.push(dependent);
71
+ }
72
+ }
73
+ }
74
+ const remaining = Array.from(inDegree.entries()).filter(
75
+ ([_, degree]) => degree > 0
76
+ );
77
+ if (remaining.length > 0) {
78
+ const cycleServices = remaining.map(([service]) => service.name).join(", ");
79
+ throw new Error(
80
+ `Circular dependency detected. Services with unresolved dependencies: ${cycleServices}`
81
+ );
82
+ }
83
+ }
84
+ /**
85
+ * Bootstrap all services in dependency order
86
+ * All services are eagerly initialized during bootstrap
87
+ * Each instance is associated with this container for property injection
88
+ */
89
+ async bootstrap() {
90
+ if (this.#ready) return;
91
+ for await (const ctor of this.#getBootstrapOrder()) {
92
+ const inst = new ctor();
93
+ inst.__container = this;
94
+ this.#singletons.set(ctor, inst);
95
+ if (hasLifecycle(inst)) {
96
+ await inst.onBootstrap();
97
+ }
98
+ }
99
+ this.#ready = true;
100
+ }
101
+ /**
102
+ * Get the container associated with an instance
103
+ * Useful for property injection (fallback for @Inject)
104
+ */
105
+ static getContainerForInstance(instance) {
106
+ return instance.__container;
107
+ }
108
+ /**
109
+ * Get a service instance
110
+ * All services must be bootstrapped before calling get()
111
+ */
112
+ get(ctor) {
113
+ if (!this.#registered.has(ctor)) {
114
+ throw new Error(`Service not registered: ${ctor.name}`);
115
+ }
116
+ if (!this.#singletons.has(ctor)) {
117
+ throw new Error(
118
+ `Service ${ctor.name} not found in singletons. Make sure bootstrap() has been called.`
119
+ );
120
+ }
121
+ return this.#singletons.get(ctor);
122
+ }
123
+ /**
124
+ * Get all service instances
125
+ * Useful for collecting metadata from all services after bootstrap
126
+ */
127
+ getAllInstances() {
128
+ return Array.from(this.#singletons.values());
129
+ }
130
+ /**
131
+ * Check if bootstrap has been called
132
+ */
133
+ get isReady() {
134
+ return this.#ready;
135
+ }
136
+ /**
137
+ * Dispose all services and reset container
138
+ */
139
+ dispose() {
140
+ for (const instance of this.#singletons.values()) {
141
+ if (typeof instance.onDestroy === "function") {
142
+ try {
143
+ instance.onDestroy();
144
+ } catch (error) {
145
+ console.error("[DIContainer] Error en onDestroy:", error);
146
+ }
147
+ }
148
+ }
149
+ this.#singletons.clear();
150
+ this.#registered.clear();
151
+ this.#dependencies.clear();
152
+ this.#dependents.clear();
153
+ this.#ready = false;
154
+ }
155
+ }
156
+ export {
157
+ DIContainer
158
+ };
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Interfaz para servicios que requieren inicialización asíncrona
3
+ *
4
+ * Los servicios que implementan esta interfaz tendrán su método onBootstrap
5
+ * llamado automáticamente cuando el componente que los provee se monte.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * class Router implements LifeCycle {
10
+ * async onBootstrap() {
11
+ * await this.loadRoutes();
12
+ * console.log('Router initialized');
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export interface LifeCycle {
18
+ /**
19
+ * Método llamado automáticamente durante el bootstrap del componente
20
+ * Permite inicialización asíncrona como cargar configuración, conectar a APIs, etc.
21
+ */
22
+ onBootstrap(): Promise<void>;
23
+ }
24
+ /**
25
+ * Type guard para verificar si un objeto implementa la interfaz LifeCycle
26
+ *
27
+ * @param obj - Objeto a verificar
28
+ * @returns true si el objeto tiene un método onBootstrap que es una función
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * if (hasLifecycle(service)) {
33
+ * await service.onBootstrap();
34
+ * }
35
+ * ```
36
+ */
37
+ export declare function hasLifecycle(obj: any): obj is LifeCycle;
@@ -0,0 +1,6 @@
1
+ function hasLifecycle(obj) {
2
+ return obj != null && typeof obj.onBootstrap === "function";
3
+ }
4
+ export {
5
+ hasLifecycle
6
+ };
@@ -0,0 +1,68 @@
1
+ import { Constructor } from './types';
2
+ /**
3
+ * Hierarchical DI container that supports parent-chain resolution.
4
+ *
5
+ * Each component with `services: [...]` in its @Component config
6
+ * gets a ScopedContainer. Services not found locally are resolved
7
+ * by walking up the parent chain.
8
+ *
9
+ * Uses topological sort (Kahn's algorithm) to bootstrap services
10
+ * in correct dependency order — same algorithm as DIContainer.
11
+ */
12
+ export declare class ScopedContainer {
13
+ #private;
14
+ constructor(parent?: ScopedContainer);
15
+ /**
16
+ * Register a service constructor in this scope
17
+ */
18
+ register(token: Constructor): void;
19
+ /**
20
+ * Register a dependency relationship between services in this scope.
21
+ * Only for dependencies that are BOTH registered locally.
22
+ * Cross-scope dependencies are resolved via parent chain at get() time.
23
+ */
24
+ registerDependency(parent: Constructor, dependency: Constructor): void;
25
+ /**
26
+ * Bootstrap all locally registered services in dependency order.
27
+ * Each instance is associated with this container via __container.
28
+ *
29
+ * Services with async onBootstrap() are launched as fire-and-forget.
30
+ * Use the reactive pattern (@Store with isLoading) to handle async state.
31
+ */
32
+ bootstrapSync(): void;
33
+ /**
34
+ * Bootstrap all locally registered services, awaiting async onBootstrap hooks.
35
+ * Use this in the DOM init() path where async is available.
36
+ */
37
+ bootstrap(): Promise<void>;
38
+ /**
39
+ * Resolve a service by walking up the parent chain.
40
+ * Checks local scope first, then parent, then grandparent, etc.
41
+ */
42
+ get<T>(ctor: Constructor<T>): T;
43
+ /**
44
+ * Check if a service exists in this scope or any parent scope.
45
+ */
46
+ has(ctor: Constructor): boolean;
47
+ /**
48
+ * Check if a service is registered locally (not including parents).
49
+ */
50
+ hasLocal(ctor: Constructor): boolean;
51
+ /**
52
+ * Check if bootstrap has been called.
53
+ */
54
+ get isReady(): boolean;
55
+ /**
56
+ * Get the parent container.
57
+ */
58
+ get parent(): ScopedContainer | undefined;
59
+ /**
60
+ * Get all locally instantiated service instances.
61
+ */
62
+ getAllInstances(): any[];
63
+ /**
64
+ * Dispose all local services and reset container.
65
+ * Calls onDestroy() on services that implement it.
66
+ */
67
+ dispose(): void;
68
+ }