@relax.js/core 1.0.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 (194) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +188 -0
  3. package/dist/DataLoader.d.ts +51 -0
  4. package/dist/DependencyInjection.d.ts +271 -0
  5. package/dist/DependencyInjectionOld.d.ts +35 -0
  6. package/dist/Metadata.d.ts +8 -0
  7. package/dist/SequentialId.d.ts +47 -0
  8. package/dist/_alt/src/MustardEngine.d.ts +30 -0
  9. package/dist/_alt/src/MustardParser.d.ts +63 -0
  10. package/dist/_alt/src/MustardParser2.d.ts +35 -0
  11. package/dist/_alt/src/pipes.d.ts +93 -0
  12. package/dist/_alt/src/template.d.ts +166 -0
  13. package/dist/_alt/src/tools.d.ts +4 -0
  14. package/dist/_alt/tests/pipes.tests.d.ts +1 -0
  15. package/dist/_alt/tests/template.tests.d.ts +1 -0
  16. package/dist/_alt/vitest.config.d.ts +2 -0
  17. package/dist/collections/Index.d.ts +1 -0
  18. package/dist/collections/LinkedList.d.ts +75 -0
  19. package/dist/collections/Pager.d.ts +15 -0
  20. package/dist/collections/index.js +2 -0
  21. package/dist/collections/index.js.map +7 -0
  22. package/dist/collections/index.mjs +2 -0
  23. package/dist/collections/index.mjs.map +7 -0
  24. package/dist/components/Table.d.ts +13 -0
  25. package/dist/components/index.d.ts +4 -0
  26. package/dist/components/index.js +128 -0
  27. package/dist/components/index.js.map +7 -0
  28. package/dist/components/index.mjs +128 -0
  29. package/dist/components/index.mjs.map +7 -0
  30. package/dist/components/lists/Table.d.ts +59 -0
  31. package/dist/components/lists/TreeView.d.ts +67 -0
  32. package/dist/components/lists/index.d.ts +2 -0
  33. package/dist/components/loader.d.ts +60 -0
  34. package/dist/components/menus/MenuItem.d.ts +30 -0
  35. package/dist/components/menus/TopMenu.d.ts +16 -0
  36. package/dist/components/menus/index.d.ts +2 -0
  37. package/dist/components/panels/tabs.d.ts +15 -0
  38. package/dist/di/index.d.ts +1 -0
  39. package/dist/di/index.js +2 -0
  40. package/dist/di/index.js.map +7 -0
  41. package/dist/di/index.mjs +2 -0
  42. package/dist/di/index.mjs.map +7 -0
  43. package/dist/elements/CopyAttributes.d.ts +2 -0
  44. package/dist/elements/dom.d.ts +18 -0
  45. package/dist/elements/index.d.ts +2 -0
  46. package/dist/elements/index.js +2 -0
  47. package/dist/elements/index.js.map +7 -0
  48. package/dist/elements/index.mjs +2 -0
  49. package/dist/elements/index.mjs.map +7 -0
  50. package/dist/errors.d.ts +71 -0
  51. package/dist/forms/FormReader.d.ts +182 -0
  52. package/dist/forms/FormValidator.d.ts +114 -0
  53. package/dist/forms/ValidationRules.d.ts +103 -0
  54. package/dist/forms/index.d.ts +4 -0
  55. package/dist/forms/index.js +2 -0
  56. package/dist/forms/index.js.map +7 -0
  57. package/dist/forms/index.mjs +2 -0
  58. package/dist/forms/index.mjs.map +7 -0
  59. package/dist/forms/setFormData.d.ts +49 -0
  60. package/dist/getParentComponent.d.ts +43 -0
  61. package/dist/html/TableRenderer.d.ts +44 -0
  62. package/dist/html/TreeBinder.d.ts +9 -0
  63. package/dist/html/html.d.ts +55 -0
  64. package/dist/html/index.d.ts +5 -0
  65. package/dist/html/index.js +2 -0
  66. package/dist/html/index.js.map +7 -0
  67. package/dist/html/index.mjs +2 -0
  68. package/dist/html/index.mjs.map +7 -0
  69. package/dist/html/template.d.ts +167 -0
  70. package/dist/http/ServerSentEvents.d.ts +116 -0
  71. package/dist/http/SimpleWebSocket.d.ts +153 -0
  72. package/dist/http/http.d.ts +177 -0
  73. package/dist/http/index.d.ts +3 -0
  74. package/dist/http/index.js +2 -0
  75. package/dist/http/index.js.map +7 -0
  76. package/dist/http/index.mjs +2 -0
  77. package/dist/http/index.mjs.map +7 -0
  78. package/dist/i18n/i18n.d.ts +105 -0
  79. package/dist/i18n/icu.d.ts +64 -0
  80. package/dist/i18n/index.d.ts +2 -0
  81. package/dist/i18n/index.js +2 -0
  82. package/dist/i18n/index.js.map +7 -0
  83. package/dist/i18n/index.mjs +2 -0
  84. package/dist/i18n/index.mjs.map +7 -0
  85. package/dist/index.d.ts +16 -0
  86. package/dist/index.js +5 -0
  87. package/dist/index.js.map +7 -0
  88. package/dist/index.mjs +5 -0
  89. package/dist/index.mjs.map +7 -0
  90. package/dist/lib/DataLoader.d.ts +51 -0
  91. package/dist/lib/DependencyInjection.d.ts +271 -0
  92. package/dist/lib/InvokeParent.d.ts +10 -0
  93. package/dist/lib/Pipes.d.ts +236 -0
  94. package/dist/lib/SequentialId.d.ts +47 -0
  95. package/dist/lib/collections/Index.d.ts +1 -0
  96. package/dist/lib/collections/LinkedList.d.ts +75 -0
  97. package/dist/lib/collections/Pager.d.ts +15 -0
  98. package/dist/lib/collections/TableRenderer.d.ts +44 -0
  99. package/dist/lib/di/index.d.ts +1 -0
  100. package/dist/lib/elements/CopyAttributes.d.ts +2 -0
  101. package/dist/lib/elements/dom.d.ts +18 -0
  102. package/dist/lib/elements/index.d.ts +2 -0
  103. package/dist/lib/errors.d.ts +71 -0
  104. package/dist/lib/forms/FormReader.d.ts +182 -0
  105. package/dist/lib/forms/FormValidator.d.ts +114 -0
  106. package/dist/lib/forms/ValidationRules.d.ts +103 -0
  107. package/dist/lib/forms/index.d.ts +4 -0
  108. package/dist/lib/forms/setFormData.d.ts +49 -0
  109. package/dist/lib/getParentComponent.d.ts +43 -0
  110. package/dist/lib/html/TableRenderer.d.ts +44 -0
  111. package/dist/lib/html/TreeBinder.d.ts +9 -0
  112. package/dist/lib/html/html.d.ts +55 -0
  113. package/dist/lib/html/html2.d.ts +55 -0
  114. package/dist/lib/html/index.d.ts +5 -0
  115. package/dist/lib/html/m.d.ts +167 -0
  116. package/dist/lib/html/m2.d.ts +8 -0
  117. package/dist/lib/html/m3.d.ts +0 -0
  118. package/dist/lib/html/template.d.ts +167 -0
  119. package/dist/lib/http/HttpClient.d.ts +153 -0
  120. package/dist/lib/http/ServerSentEvents.d.ts +116 -0
  121. package/dist/lib/http/SimpleWebSocket.d.ts +153 -0
  122. package/dist/lib/http/http.d.ts +177 -0
  123. package/dist/lib/http/index.d.ts +3 -0
  124. package/dist/lib/i18n/i18n.d.ts +105 -0
  125. package/dist/lib/i18n/icu.d.ts +64 -0
  126. package/dist/lib/i18n/index.d.ts +2 -0
  127. package/dist/lib/index.d.ts +16 -0
  128. package/dist/lib/routing/NavigateRouteEvent.d.ts +52 -0
  129. package/dist/lib/routing/RouteLink.d.ts +7 -0
  130. package/dist/lib/routing/Routing.d.ts +270 -0
  131. package/dist/lib/routing/RoutingTarget.d.ts +22 -0
  132. package/dist/lib/routing/index.d.ts +7 -0
  133. package/dist/lib/routing/navigation.d.ts +70 -0
  134. package/dist/lib/routing/routeMatching.d.ts +21 -0
  135. package/dist/lib/routing/routeTargetRegistry.d.ts +23 -0
  136. package/dist/lib/routing/types.d.ts +130 -0
  137. package/dist/lib/templates/NodeTemplate.d.ts +38 -0
  138. package/dist/lib/templates/accessorParser.d.ts +87 -0
  139. package/dist/lib/templates/parseTemplate.d.ts +6 -0
  140. package/dist/lib/templates/tokenizer.d.ts +76 -0
  141. package/dist/lib/tools.d.ts +30 -0
  142. package/dist/lib/utils/index.d.ts +4 -0
  143. package/dist/pipes.d.ts +236 -0
  144. package/dist/routing/NavigateRouteEvent.d.ts +52 -0
  145. package/dist/routing/RouteLink.d.ts +7 -0
  146. package/dist/routing/RoutingTarget.d.ts +22 -0
  147. package/dist/routing/index.d.ts +7 -0
  148. package/dist/routing/index.js +5 -0
  149. package/dist/routing/index.js.map +7 -0
  150. package/dist/routing/index.mjs +5 -0
  151. package/dist/routing/index.mjs.map +7 -0
  152. package/dist/routing/navigation.d.ts +70 -0
  153. package/dist/routing/routeMatching.d.ts +21 -0
  154. package/dist/routing/routeTargetRegistry.d.ts +23 -0
  155. package/dist/routing/types.d.ts +130 -0
  156. package/dist/templates/NodeTemplate.d.ts +38 -0
  157. package/dist/templates/accessorParser.d.ts +87 -0
  158. package/dist/templates/parseTemplate.d.ts +6 -0
  159. package/dist/templates/tokenizer.d.ts +76 -0
  160. package/dist/tools.d.ts +30 -0
  161. package/dist/utils/index.d.ts +4 -0
  162. package/dist/utils/index.js +2 -0
  163. package/dist/utils/index.js.map +7 -0
  164. package/dist/utils/index.mjs +2 -0
  165. package/dist/utils/index.mjs.map +7 -0
  166. package/docs/Architecture.md +333 -0
  167. package/docs/DependencyInjection.md +237 -0
  168. package/docs/Errors.md +87 -0
  169. package/docs/GettingStarted.md +231 -0
  170. package/docs/Pipes.md +211 -0
  171. package/docs/Translations.md +312 -0
  172. package/docs/WhyRelaxjs.md +336 -0
  173. package/docs/elements/dom.md +102 -0
  174. package/docs/forms/creating-form-components.md +924 -0
  175. package/docs/forms/form-api.md +94 -0
  176. package/docs/forms/forms.md +99 -0
  177. package/docs/forms/patterns.md +311 -0
  178. package/docs/forms/reading-writing.md +365 -0
  179. package/docs/forms/validation.md +351 -0
  180. package/docs/html/TableRenderer.md +292 -0
  181. package/docs/html/html.md +175 -0
  182. package/docs/html/index.md +54 -0
  183. package/docs/html/template.md +422 -0
  184. package/docs/http/HttpClient.md +459 -0
  185. package/docs/http/ServerSentEvents.md +184 -0
  186. package/docs/http/index.md +109 -0
  187. package/docs/i18n/i18n.md +309 -0
  188. package/docs/i18n/intl-standard.md +178 -0
  189. package/docs/routing/RouteLink.md +98 -0
  190. package/docs/routing/Routing.md +332 -0
  191. package/docs/routing/RoutingTarget.md +136 -0
  192. package/docs/routing/layouts.md +207 -0
  193. package/docs/utilities.md +143 -0
  194. package/package.json +93 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 relax.js
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,188 @@
1
+ # Relaxjs
2
+
3
+ **Ship faster with less code.**
4
+
5
+ Web Component library with routing, forms, DI, templating, and i18n. No virtual DOM, no build magic, no surprise re-renders.
6
+
7
+ ## Why Relaxjs?
8
+
9
+ Modern frameworks solve problems you might not have. Relaxjs takes the opposite approach:
10
+
11
+ | Framework Approach | Relaxjs Approach |
12
+ |-------------------|------------------|
13
+ | Virtual DOM diffing | Direct DOM manipulation |
14
+ | Reactive state management | Explicit updates |
15
+ | Custom template syntax | Standard HTML |
16
+ | Framework-specific lifecycle | Native Web Component lifecycle |
17
+ | Magic re-renders | You control what updates |
18
+ | Custom rendering pipeline | Native async/await everywhere |
19
+
20
+ > [Read the detailed comparison](docs/WhyRelaxjs.md)
21
+
22
+ **The result:** You always know *when* something ran, *why* it ran, and *what* triggered it.
23
+
24
+ ## What Relaxjs Adds
25
+
26
+ Web Components give you encapsulation and lifecycle hooks. Relaxjs fills the gaps:
27
+
28
+ | Vanilla Web Components | With Relaxjs |
29
+ |------------------------|--------------|
30
+ | Manual form serialization | `readData(form)` returns typed objects (send it directly to backend) |
31
+ | Query string parsing | Named routes with typed parameters |
32
+ | DIY validation logic | `FormValidator` with HTML5 integration |
33
+ | No component library | Table, Tabs, TreeView, Menu ready to use |
34
+ | Manual service wiring | Decorator-based dependency injection |
35
+ | Raw fetch boilerplate | Simple HTTP client for backend calls |
36
+
37
+ You write less boilerplate while keeping full control.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ npm install relaxjs
43
+ ```
44
+
45
+ ## Quick Examples
46
+
47
+ ### Form Handling
48
+
49
+ Read and write form data with automatic type conversion:
50
+
51
+ ```typescript
52
+ import { setFormData, readData } from 'relaxjs';
53
+
54
+ // Populate a form from an object
55
+ const user = { name: 'John', email: 'john@example.com', age: 30 };
56
+ setFormData(form, user);
57
+
58
+ // Read form data back (with types!)
59
+ const data = readData(form);
60
+ // { name: 'John', email: 'john@example.com', age: 30 }
61
+ ```
62
+
63
+ Supports nested objects (`user.address.city`), arrays (`tags[]`), and automatic type conversion for numbers, booleans, and dates.
64
+
65
+ > [Form utilities docs](docs/forms/forms.md)
66
+
67
+ ### Client-Side Routing
68
+
69
+ Define routes and let the router handle navigation:
70
+
71
+ ```typescript
72
+ import { defineRoutes, navigate, startRouting } from 'relaxjs';
73
+
74
+ defineRoutes([
75
+ { name: 'home', path: '/', componentTagName: 'app-home' },
76
+ { name: 'user', path: '/users/:id', componentTagName: 'app-user' },
77
+ { name: 'settings', path: '/settings', componentTagName: 'app-settings' }
78
+ ]);
79
+
80
+ startRouting();
81
+
82
+ // Navigate programmatically
83
+ navigate('user', { params: { id: '123' } });
84
+ ```
85
+
86
+ ```html
87
+ <r-route-target></r-route-target>
88
+ ```
89
+
90
+ > [Routing docs](docs/routing/Routing.md)
91
+
92
+ ### Form Validation
93
+
94
+ HTML5-style validation with custom rules and error summaries:
95
+
96
+ ```typescript
97
+ import { FormValidator } from 'relaxjs';
98
+
99
+ const validator = new FormValidator(form, {
100
+ useSummary: true,
101
+ submitCallback: () => saveData()
102
+ });
103
+ ```
104
+
105
+ > [Validation docs](docs/forms/validation.md)
106
+
107
+ ## What's Included
108
+
109
+ | Feature | Description |
110
+ |---------|-------------|
111
+ | **Form Utilities** | Read/write forms, type conversion, validation |
112
+ | **Routing** | Named routes, typed parameters, guards, layouts, multiple targets |
113
+ | **HTML Templates** | `html` tagged templates with data binding and in-place updates |
114
+ | **HTTP Client** | Type-safe `get`/`post`/`put`/`del` with automatic JWT |
115
+ | **WebSocket** | Auto-reconnect, message queuing, typed messages |
116
+ | **SSE** | Server-Sent Events dispatched as DOM events |
117
+ | **Dependency Injection** | Decorator-based DI with constructor and property injection |
118
+ | **i18n** | ICU message format, pluralization, locale-aware formatting |
119
+ | **Pipes** | 15 built-in data transformations for templates |
120
+
121
+ ## Where Relaxjs Fits
122
+
123
+ Relaxjs is a good choice when:
124
+
125
+ - You're building a **small-to-medium SPA** where you want direct control over the DOM
126
+ - Your team prefers **vanilla Web Components** over framework abstractions
127
+ - You want **gradual adoption** - use only the parts you need, no all-or-nothing buy-in
128
+ - **Bundle size and simplicity** matter more than ecosystem breadth
129
+ - You want to **understand what your code does** - no hidden re-renders, no magic proxies, no compiler transforms
130
+
131
+ ## Where Relaxjs Doesn't Fit
132
+
133
+ Be honest with yourself - Relaxjs is not the right tool for everything:
134
+
135
+ - **Large-scale apps with complex state** - Relaxjs has no reactive state management, no global store, no computed properties. If your UI has dozens of interdependent data flows, you'll be writing a lot of manual update logic.
136
+ - **Server-side rendering / static site generation** - Relaxjs is client-only. If you need SEO, fast first-paint from the server, or pre-rendered pages, look at Next.js, Nuxt, or SvelteKit.
137
+ - **Big teams that need a large talent pool** - React and Angular developers are everywhere. Finding developers who know Relaxjs (or are willing to learn a small library) is harder.
138
+ - **Rich ecosystem needs** - There's no component marketplace, no DevTools extension, no community middleware. You build what you need or use vanilla JS libraries.
139
+ - **Mobile / native targets** - No React Native equivalent, no Ionic integration. Relaxjs is for the browser.
140
+
141
+ ## How It Compares
142
+
143
+ | | Relaxjs | React | Angular | Vue | Svelte |
144
+ |---|---|---|---|---|---|
145
+ | **Approach** | Web Components | Virtual DOM | Full framework | Virtual DOM | Compiler |
146
+ | **Bundle size** | ~20KB gzipped | ~45KB | ~150KB+ | ~33KB | ~2KB runtime |
147
+ | **Learning curve** | Low (vanilla TS) | Medium | High | Medium | Low-Medium |
148
+ | **State management** | Explicit DOM updates | Hooks / Redux / Zustand | RxJS / Signals | Reactive refs | Stores / runes |
149
+ | **Routing** | Built-in (simple) | react-router (separate) | Built-in (full) | vue-router (separate) | SvelteKit |
150
+ | **Forms** | Built-in (HTML5 native) | Controlled / uncontrolled | Reactive forms | v-model | bind: |
151
+ | **SSR** | No | Yes | Yes | Yes | Yes |
152
+ | **Ecosystem** | Small | Massive | Large | Large | Growing |
153
+ | **DI** | Built-in | None (Context API) | Built-in | Provide / Inject | None |
154
+ | **i18n** | Built-in (ICU) | i18next etc. | Built-in | vue-i18n | i18next etc. |
155
+ | **DevTools** | Browser DevTools | React DevTools | Angular DevTools | Vue DevTools | Svelte DevTools |
156
+ | **Community size** | Small | Very large | Large | Large | Medium |
157
+
158
+ ## Philosophy
159
+
160
+ This isn't a framework - it's a library. Use what you need:
161
+
162
+ - Need just form handling? Import `setFormData` and `readData`.
163
+ - Need routing? Add `defineRoutes` and `r-route-target`.
164
+ - Need everything? It's all there.
165
+
166
+ No buy-in required. No migration path to worry about. Just Web Components and TypeScript.
167
+
168
+ ## Documentation
169
+
170
+ - [Why Relaxjs?](docs/WhyRelaxjs.md) - Detailed comparison with frameworks
171
+ - [Getting Started](docs/GettingStarted.md) - Progressive adoption guide (7 levels)
172
+ - [Architecture](docs/Architecture.md)
173
+ - [Form Utilities](docs/forms/forms.md) - Validation, reading/writing, custom form components
174
+ - [Routing](docs/routing/Routing.md) - Routes, guards, layouts, navigation
175
+ - [HTML Templates](docs/html/html.md) - Tagged templates with data binding
176
+ - [HTTP & WebSocket](docs/http/HttpClient.md) - REST calls, WebSocket, SSE
177
+ - [Dependency Injection](docs/DependencyInjection.md)
178
+ - [i18n](docs/i18n/i18n.md) - Translations, ICU format, locale switching
179
+ - [Pipes](docs/Pipes.md) - Data transformations for templates
180
+ - [Utilities](docs/utilities.md) - Sequential IDs, LinkedList, helpers
181
+
182
+ ## Browser Support
183
+
184
+ Works in all browsers that support Web Components (Chrome, Firefox, Safari, Edge).
185
+
186
+ ## License
187
+
188
+ ISC
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Interface for loading paginated data from a data source.
3
+ * Implement this interface to provide data to table or list components
4
+ * that support pagination and sorting.
5
+ *
6
+ * Used by components like `r-table` to fetch data on demand as users
7
+ * navigate through pages or change sort order.
8
+ *
9
+ * @example
10
+ * // Implement for an API-backed data source
11
+ * class UserDataLoader implements DataLoader {
12
+ * async load(options) {
13
+ * const params = new URLSearchParams({
14
+ * page: options.page.toString(),
15
+ * pageSize: options.pageSize.toString(),
16
+ * sort: JSON.stringify(options.sort)
17
+ * });
18
+ *
19
+ * const response = await fetch(`/api/users?${params}`);
20
+ * return response.json();
21
+ * }
22
+ * }
23
+ *
24
+ * @example
25
+ * // Use with a table component
26
+ * const loader: DataLoader = new UserDataLoader();
27
+ * const result = await loader.load({ page: 1, pageSize: 25, sort: [] });
28
+ * table.render(result.rows);
29
+ */
30
+ export interface DataLoader {
31
+ /**
32
+ * Loads a page of data with optional sorting.
33
+ *
34
+ * @param options - The loading options
35
+ * @param options.page - The 1-based page number to load
36
+ * @param options.pageSize - Number of rows per page
37
+ * @param options.sort - Array of sort specifications
38
+ * @returns Promise resolving to rows and total count for pagination
39
+ */
40
+ load(options: {
41
+ page: number;
42
+ pageSize: number;
43
+ sort: {
44
+ column: string;
45
+ direction: 'asc' | 'desc';
46
+ }[];
47
+ }): Promise<{
48
+ rows: Record<string, any>[];
49
+ totalCount: number;
50
+ }>;
51
+ }
@@ -0,0 +1,271 @@
1
+ /**
2
+ * Generic constructor type used for dependency registration and injection.
3
+ * Represents any class constructor that can be used with the DI container.
4
+ *
5
+ * @template T - The type of object the constructor creates
6
+ *
7
+ * @example
8
+ * // Use with service registration
9
+ * class UserService {}
10
+ * const ctor: Constructor<UserService> = UserService;
11
+ * serviceCollection.registerByType(ctor, { inject: [] });
12
+ */
13
+ export type Constructor<T extends object = object> = new (...args: any[]) => T;
14
+ /**
15
+ * Controls how service instances are shared across the container hierarchy.
16
+ * Used when registering services to define their lifetime behavior.
17
+ *
18
+ * - `global`: Single instance shared everywhere (singleton pattern)
19
+ * - `closest`: New instance per container scope (scoped lifetime)
20
+ *
21
+ * @example
22
+ * // Singleton service - same instance everywhere
23
+ * serviceCollection.register(LoggerService, { scope: 'global', inject: [] });
24
+ *
25
+ * // Scoped service - new instance per scope
26
+ * serviceCollection.register(RequestContext, { scope: 'closest', inject: [] });
27
+ */
28
+ export type ServiceScope = 'global' | 'closest';
29
+ /**
30
+ * Configuration options for registering a service in the DI container.
31
+ * Controls identification, lifetime, and dependency resolution.
32
+ *
33
+ * @example
34
+ * // Register with constructor injection
35
+ * const options: RegistrationOptions = {
36
+ * scope: 'global',
37
+ * inject: [DatabaseConnection, ConfigService]
38
+ * };
39
+ * serviceCollection.register(UserRepository, options);
40
+ *
41
+ * @example
42
+ * // Register with property injection
43
+ * const options: RegistrationOptions = {
44
+ * inject: [],
45
+ * properties: { logger: Logger, config: 'appConfig' }
46
+ * };
47
+ *
48
+ * @example
49
+ * // Register with a pre-created instance
50
+ * const options: RegistrationOptions = {
51
+ * inject: [],
52
+ * instance: existingService
53
+ * };
54
+ */
55
+ export interface RegistrationOptions {
56
+ /** Service lifetime - 'global' for singleton, 'closest' for scoped */
57
+ scope?: ServiceScope;
58
+ /** Optional string key for resolving by name instead of type */
59
+ key?: string;
60
+ /** Pre-existing instance to use instead of creating new one */
61
+ instance?: unknown;
62
+ /** Types or keys for constructor parameters, in order */
63
+ inject: (string | Constructor)[];
64
+ /** Map of property names to their injection types/keys */
65
+ properties?: Record<string, string | Constructor>;
66
+ }
67
+ /**
68
+ * Field decorator that collects property injection configuration.
69
+ * Updates or creates the properties mapping in registration options.
70
+ *
71
+ * @example
72
+ * @ContainerService({
73
+ * inject: [Database],
74
+ * properties: {
75
+ * logger: Logger, // Inject by type
76
+ * audit: 'auditLogger' // Inject by key
77
+ * }
78
+ * })
79
+ * class UserService {
80
+ * @Inject(Logger)
81
+ * private logger!: Logger;
82
+ *
83
+ * @Inject('auditLogger')
84
+ * private audit!: Logger;
85
+ *
86
+ * constructor(db: Database) {}
87
+ * }
88
+ */
89
+ export declare function Inject<T extends object>(typeOrKey: Constructor<T> | string): (_: undefined, context: ClassFieldDecoratorContext) => (this: any) => T;
90
+ /**
91
+ * Class decorator that automatically registers a service in the global DI container.
92
+ * Use this to declaratively register services without manual registration calls.
93
+ *
94
+ * Services are registered at module load time, so ensure this file is imported
95
+ * before attempting to resolve the decorated service.
96
+ *
97
+ * @param options - Registration configuration including scope and dependencies
98
+ *
99
+ * @example
100
+ * // Simple service with constructor injection
101
+ * @ContainerService({ inject: [DatabaseConnection] })
102
+ * class UserRepository {
103
+ * constructor(private db: DatabaseConnection) {}
104
+ * }
105
+ *
106
+ * @example
107
+ * // Service with custom key for named resolution
108
+ * @ContainerService({ key: 'primaryCache', scope: 'global', inject: [] })
109
+ * class CacheService {}
110
+ *
111
+ * // Later resolve by key
112
+ * const cache = container.resolve('primaryCache');
113
+ */
114
+ export declare function ContainerService<T extends object>(options?: RegistrationOptions): (target: Constructor<T>) => void;
115
+ /**
116
+ * Internal class representing a registered service's metadata.
117
+ * Holds all information needed to create and configure service instances.
118
+ *
119
+ * @internal This is an implementation detail and should not be used directly.
120
+ */
121
+ declare class Registration {
122
+ classConstructor: Constructor;
123
+ scope: ServiceScope;
124
+ inject: (string | Constructor)[];
125
+ properties: Record<string, string | Constructor>;
126
+ key?: string;
127
+ instance?: unknown;
128
+ /**
129
+ * Creates a new registration record.
130
+ *
131
+ * @param classConstructor - The class constructor function
132
+ * @param scope - Instance sharing behavior
133
+ * @param inject - Constructor parameter dependencies
134
+ * @param properties - Property injection mappings
135
+ * @param key - Optional string identifier
136
+ * @param instance - Optional pre-created instance
137
+ */
138
+ constructor(classConstructor: Constructor, scope: ServiceScope, inject: (string | Constructor)[], properties?: Record<string, string | Constructor>, key?: string, instance?: unknown);
139
+ }
140
+ /**
141
+ * Registry that stores service registration metadata.
142
+ * Use this to register services before they can be resolved by a ServiceContainer.
143
+ *
144
+ * Typically you'll use the global `serviceCollection` instance rather than creating your own.
145
+ *
146
+ * @example
147
+ * // Register a service by type
148
+ * serviceCollection.registerByType(LoggerService, { inject: [] });
149
+ *
150
+ * // Register with a string key
151
+ * serviceCollection.register(CacheService, { key: 'cache', inject: [] });
152
+ *
153
+ * // Check if service is registered
154
+ * const reg = serviceCollection.tryGet(LoggerService);
155
+ * if (reg) {
156
+ * console.log('Logger is registered');
157
+ * }
158
+ */
159
+ export declare class ServiceCollection {
160
+ private servicesByKey;
161
+ private servicesByClassName;
162
+ /**
163
+ * Registers a service with full configuration options.
164
+ * The service will be resolvable by both its class name and optional key.
165
+ *
166
+ * @param constructor - The service class constructor
167
+ * @param options - Registration configuration
168
+ */
169
+ register<T extends object>(constructor: Constructor<T>, options: RegistrationOptions): void;
170
+ /**
171
+ * Registers a service by its class type.
172
+ * The service will be resolvable by its class constructor.
173
+ *
174
+ * @param constructor - The service class constructor
175
+ * @param options - Optional registration configuration
176
+ */
177
+ registerByType<T extends object>(constructor: Constructor<T>, options?: RegistrationOptions): void;
178
+ private checkNameCollision;
179
+ private validateRegistration;
180
+ /**
181
+ * Attempts to retrieve a service registration.
182
+ * Returns undefined if the service is not registered.
183
+ *
184
+ * @param key - Either a string key or class constructor
185
+ * @returns The registration or undefined
186
+ */
187
+ tryGet<T extends object>(key: string | Constructor<T>): Registration | undefined;
188
+ /**
189
+ * Retrieves a service registration or throws if not found.
190
+ *
191
+ * @param key - Either a string key or class constructor
192
+ * @returns The registration
193
+ * @throws Error if the service is not registered
194
+ */
195
+ get<T extends object>(key: string | Constructor<T>): Registration;
196
+ }
197
+ /**
198
+ * IoC container that resolves and manages service instances.
199
+ * Creates instances based on registrations in a ServiceCollection,
200
+ * handling constructor injection, property injection, and lifetime management.
201
+ *
202
+ * Typically you'll use the global `container` instance rather than creating your own.
203
+ *
204
+ * @example
205
+ * // Resolve a service by class
206
+ * const logger = container.resolve(LoggerService);
207
+ *
208
+ * // Resolve by string key
209
+ * const cache = container.resolve<CacheService>('primaryCache');
210
+ *
211
+ * @example
212
+ * // Full setup workflow
213
+ * serviceCollection.register(UserService, {
214
+ * inject: [DatabaseConnection],
215
+ * scope: 'global'
216
+ * });
217
+ *
218
+ * const userService = container.resolve(UserService);
219
+ */
220
+ export declare class ServiceContainer {
221
+ private serviceCollection;
222
+ private instances;
223
+ /**
224
+ * Creates a new container backed by the given service collection.
225
+ *
226
+ * @param serviceCollection - The registry containing service registrations
227
+ */
228
+ constructor(serviceCollection: ServiceCollection);
229
+ /**
230
+ * Resolves a service instance by class type or string key.
231
+ * Creates the instance if not already cached (for global scope).
232
+ * Handles constructor and property injection automatically.
233
+ *
234
+ * @param keyOrType - Either a string key or class constructor
235
+ * @returns The resolved service instance
236
+ * @throws Error if the service is not registered
237
+ *
238
+ * @example
239
+ * const service = container.resolve(MyService);
240
+ */
241
+ resolve<T extends object>(keyOrType: string | Constructor<T>): T;
242
+ /**
243
+ * Creates a new instance of a service, resolving all constructor dependencies.
244
+ */
245
+ private createInstance;
246
+ /**
247
+ * Injects dependencies into instance properties based on registration config.
248
+ */
249
+ private injectFields;
250
+ }
251
+ /**
252
+ * Global service collection instance for registering services.
253
+ * Use this to register services that can later be resolved by the container.
254
+ *
255
+ * @example
256
+ * import { serviceCollection } from 'relaxjs';
257
+ *
258
+ * serviceCollection.register(MyService, { inject: [Dependency] });
259
+ */
260
+ export declare const serviceCollection: ServiceCollection;
261
+ /**
262
+ * Global service container instance for resolving dependencies.
263
+ * Use this to obtain service instances with all dependencies injected.
264
+ *
265
+ * @example
266
+ * import { container } from 'relaxjs';
267
+ *
268
+ * const service = container.resolve(MyService);
269
+ */
270
+ export declare const container: ServiceContainer;
271
+ export {};
@@ -0,0 +1,35 @@
1
+ export type Constructor<T = object> = new (...args: any[]) => T;
2
+ export declare function Inject<T>(keyOrType?: string | Constructor<T>): PropertyDecorator & ParameterDecorator;
3
+ export interface RegistrationOptions {
4
+ scope?: ServiceScope;
5
+ key?: string;
6
+ instance?: unknown;
7
+ }
8
+ export declare function setDebugFunc(func: (...msg: any[]) => {}): void;
9
+ export declare class ServiceCollection {
10
+ private servicesByKey;
11
+ private servicesByClassName;
12
+ register<T>(constructor: Constructor<T>, options: RegistrationOptions): void;
13
+ registerByType<T>(constructor: Constructor<T>, scope?: ServiceScope): void;
14
+ tryGet<T>(key: string | Constructor<T>): Registration | undefined;
15
+ get<T>(key: string | Constructor<T>): Registration;
16
+ }
17
+ export type ServiceScope = 'global' | 'closest';
18
+ export declare function ContainerService<T>(key?: string, scope?: ServiceScope): (target: Constructor<T>) => void;
19
+ export declare class ServiceContainer {
20
+ private instances;
21
+ private serviceCollection;
22
+ constructor(serviceCollection: ServiceCollection);
23
+ resolve<T>(keyOrType: string | Constructor<T>): T;
24
+ enrich<T>(instance: T): void;
25
+ }
26
+ export declare let serviceCollection: ServiceCollection;
27
+ export declare let container: ServiceContainer;
28
+ declare class Registration {
29
+ classConstructor: Constructor;
30
+ scope: ServiceScope;
31
+ key?: string;
32
+ instance?: unknown;
33
+ constructor(classConstructor: Constructor, scope: ServiceScope, key?: string, instance?: unknown);
34
+ }
35
+ export {};
@@ -0,0 +1,8 @@
1
+ import "reflect-metadata";
2
+ interface MetadataHandler {
3
+ defineMetadata(metadataKey: string | symbol, value: any, target: object, propertyKey?: string | symbol): void;
4
+ getMetadata(metadataKey: string | symbol, target: object, propertyKey?: string | symbol): any;
5
+ hasMetadata(metadataKey: string | symbol, target: object, propertyKey?: string | symbol): boolean;
6
+ }
7
+ export declare const reflect: MetadataHandler;
8
+ export {};
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @module SequentialId
3
+ * Generates compact, time-ordered unique identifiers suitable for distributed systems.
4
+ *
5
+ * IDs are structured to be:
6
+ * - Unique across multiple clients (via baseId)
7
+ * - Time-sortable (timestamp is the most significant bits)
8
+ * - Compact (Base36 encoding produces short strings)
9
+ *
10
+ * Bit allocation (58 bits total):
11
+ * - 30 bits for timestamp (seconds since January 1, 2025)
12
+ * - 8 bits for per-second counter (supports 256 IDs/second)
13
+ * - 20 bits for client/endpoint identifier (supports ~1M unique sources)
14
+ */
15
+ /**
16
+ * Generates a unique, time-ordered sequential ID.
17
+ *
18
+ * The ID combines a timestamp, per-second counter, and client identifier
19
+ * into a compact Base36 string. IDs generated later will sort after earlier IDs,
20
+ * making them suitable for ordered collections.
21
+ *
22
+ * @param baseId - Unique identifier for the client/endpoint (0 to 1,048,575).
23
+ * Use different baseIds for different servers or processes to
24
+ * avoid collisions.
25
+ * @returns Base36 encoded string representing the unique ID
26
+ * @throws Error if baseId is out of valid range
27
+ * @throws Error if more than 256 IDs are generated in a single second
28
+ * @throws Error if timestamp exceeds range (after year 2045)
29
+ *
30
+ * @example
31
+ * // Generate ID for server instance 1
32
+ * const id1 = generateSequentialId(1);
33
+ * // Returns something like: 'k2j8m3n5p'
34
+ *
35
+ * @example
36
+ * // Different servers use different baseIds
37
+ * const SERVER_ID = parseInt(process.env.SERVER_ID || '0');
38
+ * const orderId = generateSequentialId(SERVER_ID);
39
+ *
40
+ * @example
41
+ * // IDs are time-sortable
42
+ * const id1 = generateSequentialId(0);
43
+ * await delay(1000);
44
+ * const id2 = generateSequentialId(0);
45
+ * console.log(id1 < id2); // true (lexicographic comparison works)
46
+ */
47
+ export declare function generateSequentialId(baseId: number): string;
@@ -0,0 +1,30 @@
1
+ import { CompiledTemplate } from './MustardParser';
2
+ import { PipeRegistry } from './pipes';
3
+ /**
4
+ * Main template engine that brings together parsing, rendering and pipe functions
5
+ * Use this as the main entry point for template operations
6
+ */
7
+ export declare class Mustard {
8
+ private parser;
9
+ private pipeRegistry;
10
+ private templateCache;
11
+ constructor(customPipeRegistry?: PipeRegistry);
12
+ /**
13
+ * Render a template with the given context
14
+ */
15
+ render(template: string, context: Record<string, any>): string;
16
+ /**
17
+ * Get a compiled template function
18
+ */
19
+ getTemplate(template: string): CompiledTemplate;
20
+ /**
21
+ * Register a custom pipe function
22
+ */
23
+ registerPipe(name: string, fn: (value: any, ...args: any[]) => any): void;
24
+ /**
25
+ * Clear the template cache
26
+ */
27
+ clearCache(): void;
28
+ }
29
+ export declare function bindFunctions(context: Record<string, any>, functions: Record<string, Function>): Record<string, any>;
30
+ export declare function createEngine(customPipes?: Record<string, (value: any, ...args: any[]) => any>): Mustard;