dalila 1.4.2 → 1.4.3

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 (59) hide show
  1. package/dist/context/auto-scope.d.ts +167 -0
  2. package/dist/context/auto-scope.js +381 -0
  3. package/dist/context/context.d.ts +111 -0
  4. package/dist/context/context.js +283 -0
  5. package/dist/context/index.d.ts +2 -0
  6. package/dist/context/index.js +2 -0
  7. package/dist/context/raw.d.ts +2 -0
  8. package/dist/context/raw.js +2 -0
  9. package/dist/core/dev.d.ts +7 -0
  10. package/dist/core/dev.js +14 -0
  11. package/dist/core/for.d.ts +42 -0
  12. package/dist/core/for.js +311 -0
  13. package/dist/core/index.d.ts +14 -0
  14. package/dist/core/index.js +14 -0
  15. package/dist/core/key.d.ts +33 -0
  16. package/dist/core/key.js +83 -0
  17. package/dist/core/match.d.ts +22 -0
  18. package/dist/core/match.js +175 -0
  19. package/dist/core/mutation.d.ts +55 -0
  20. package/dist/core/mutation.js +128 -0
  21. package/dist/core/persist.d.ts +63 -0
  22. package/dist/core/persist.js +371 -0
  23. package/dist/core/query.d.ts +72 -0
  24. package/dist/core/query.js +184 -0
  25. package/dist/core/resource.d.ts +299 -0
  26. package/dist/core/resource.js +924 -0
  27. package/dist/core/scheduler.d.ts +111 -0
  28. package/dist/core/scheduler.js +243 -0
  29. package/dist/core/scope.d.ts +74 -0
  30. package/dist/core/scope.js +171 -0
  31. package/dist/core/signal.d.ts +88 -0
  32. package/dist/core/signal.js +451 -0
  33. package/dist/core/store.d.ts +130 -0
  34. package/dist/core/store.js +234 -0
  35. package/dist/core/virtual.d.ts +26 -0
  36. package/dist/core/virtual.js +277 -0
  37. package/dist/core/watch-testing.d.ts +13 -0
  38. package/dist/core/watch-testing.js +16 -0
  39. package/dist/core/watch.d.ts +81 -0
  40. package/dist/core/watch.js +353 -0
  41. package/dist/core/when.d.ts +23 -0
  42. package/dist/core/when.js +124 -0
  43. package/dist/index.d.ts +4 -0
  44. package/dist/index.js +4 -0
  45. package/dist/internal/watch-testing.d.ts +1 -0
  46. package/dist/internal/watch-testing.js +8 -0
  47. package/dist/router/index.d.ts +1 -0
  48. package/dist/router/index.js +1 -0
  49. package/dist/router/route.d.ts +23 -0
  50. package/dist/router/route.js +48 -0
  51. package/dist/router/router.d.ts +23 -0
  52. package/dist/router/router.js +169 -0
  53. package/dist/runtime/bind.d.ts +59 -0
  54. package/dist/runtime/bind.js +340 -0
  55. package/dist/runtime/index.d.ts +10 -0
  56. package/dist/runtime/index.js +9 -0
  57. package/dist/simple.d.ts +11 -0
  58. package/dist/simple.js +11 -0
  59. package/package.json +1 -1
@@ -0,0 +1,169 @@
1
+ import { signal } from '../core/signal.js';
2
+ import { createScope, withScope } from '../core/scope.js';
3
+ import { findRoute } from './route.js';
4
+ let currentRouter = null;
5
+ export function getCurrentRouter() {
6
+ return currentRouter;
7
+ }
8
+ export function createRouter(config) {
9
+ const routes = config.routes;
10
+ const routeSignal = signal({
11
+ path: '/',
12
+ params: {},
13
+ query: new URLSearchParams(),
14
+ hash: ''
15
+ });
16
+ let outletElement = null;
17
+ let currentScope = null;
18
+ let currentRouteState = null;
19
+ let scrollPositions = {};
20
+ let currentLoaderController = null;
21
+ async function updateRoute(path, replace = false) {
22
+ const match = findRoute(path, routes);
23
+ if (!match) {
24
+ console.warn(`No route found for path: ${path}`);
25
+ return;
26
+ }
27
+ const fromState = currentRouteState;
28
+ const toState = {
29
+ path: match.route.path,
30
+ params: match.params,
31
+ query: match.query,
32
+ hash: match.hash
33
+ };
34
+ // Save scroll position before leaving current route
35
+ if (fromState && outletElement) {
36
+ scrollPositions[fromState.path] = window.scrollY;
37
+ }
38
+ // Call beforeEnter guard
39
+ if (match.route.beforeEnter) {
40
+ const canEnter = await match.route.beforeEnter(toState, fromState || toState);
41
+ if (!canEnter) {
42
+ console.log('Navigation cancelled by beforeEnter guard');
43
+ return;
44
+ }
45
+ }
46
+ // Abort any ongoing loader
47
+ if (currentLoaderController) {
48
+ currentLoaderController.abort();
49
+ }
50
+ // Dispose of previous scope
51
+ if (currentScope) {
52
+ // Call afterLeave hook
53
+ if (match.route.afterLeave) {
54
+ await match.route.afterLeave(fromState || toState, toState);
55
+ }
56
+ currentScope.dispose();
57
+ }
58
+ // Create new scope for this route
59
+ currentScope = createScope();
60
+ // Load data if route has a loader
61
+ let routeData = undefined;
62
+ if (match.route.loader) {
63
+ currentLoaderController = new AbortController();
64
+ try {
65
+ routeData = await match.route.loader({
66
+ ...toState,
67
+ signal: currentLoaderController.signal
68
+ });
69
+ }
70
+ catch (error) {
71
+ if (error.name !== 'AbortError') {
72
+ console.error('Loader failed:', error);
73
+ }
74
+ return;
75
+ }
76
+ }
77
+ // Update route signal
78
+ routeSignal.set(toState);
79
+ currentRouteState = toState;
80
+ // Update browser history
81
+ const url = path + (match.query.toString() ? `?${match.query}` : '') + (match.hash ? `#${match.hash}` : '');
82
+ if (replace) {
83
+ history.replaceState(null, '', url);
84
+ }
85
+ else {
86
+ history.pushState(null, '', url);
87
+ }
88
+ // Mount the view if outlet exists
89
+ if (outletElement) {
90
+ await mountView(match, routeData);
91
+ }
92
+ // Restore scroll position
93
+ if (toState.hash) {
94
+ const element = document.getElementById(toState.hash.slice(1));
95
+ if (element) {
96
+ element.scrollIntoView();
97
+ }
98
+ }
99
+ else if (scrollPositions[toState.path] !== undefined) {
100
+ window.scrollTo(0, scrollPositions[toState.path]);
101
+ }
102
+ else {
103
+ window.scrollTo(0, 0);
104
+ }
105
+ }
106
+ async function mountView(match, routeData) {
107
+ if (!outletElement || !currentScope)
108
+ return;
109
+ // Clear outlet
110
+ outletElement.innerHTML = '';
111
+ // Mount view within scope
112
+ withScope(currentScope, () => {
113
+ const viewResult = match.route.view();
114
+ const nodes = Array.isArray(viewResult) ? viewResult : [viewResult];
115
+ outletElement.append(...nodes);
116
+ });
117
+ }
118
+ function handlePopState() {
119
+ updateRoute(window.location.pathname + window.location.search + window.location.hash, true);
120
+ }
121
+ function handleLink(event) {
122
+ const target = event.target;
123
+ const anchor = target.closest('a');
124
+ if (!anchor)
125
+ return;
126
+ const href = anchor.getAttribute('href');
127
+ if (!href || href.startsWith('http') || href.startsWith('//') || anchor.target === '_blank') {
128
+ return;
129
+ }
130
+ event.preventDefault();
131
+ push(href);
132
+ }
133
+ function push(path) {
134
+ updateRoute(path, false);
135
+ }
136
+ function replace(path) {
137
+ updateRoute(path, true);
138
+ }
139
+ function back() {
140
+ window.history.back();
141
+ }
142
+ function mount(outlet) {
143
+ outletElement = outlet;
144
+ // Set up history API listener
145
+ window.addEventListener('popstate', handlePopState);
146
+ // Initialize with current location
147
+ const initialPath = window.location.pathname + window.location.search + window.location.hash;
148
+ updateRoute(initialPath, true);
149
+ }
150
+ function outlet() {
151
+ if (!outletElement) {
152
+ outletElement = document.createElement('div');
153
+ }
154
+ return outletElement;
155
+ }
156
+ // Create router instance
157
+ const router = {
158
+ mount,
159
+ push,
160
+ replace,
161
+ back,
162
+ link: handleLink,
163
+ outlet,
164
+ route: routeSignal
165
+ };
166
+ // Set as current router
167
+ currentRouter = router;
168
+ return router;
169
+ }
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Dalila Template Runtime - bind()
3
+ *
4
+ * Binds a DOM tree to a reactive context using declarative attributes.
5
+ * No eval, no inline JS execution - only identifier resolution from ctx.
6
+ *
7
+ * @module dalila/runtime
8
+ */
9
+ export interface BindOptions {
10
+ /**
11
+ * Event types to bind (default: click, input, change, submit, keydown, keyup)
12
+ */
13
+ events?: string[];
14
+ /**
15
+ * Selectors for elements where text interpolation should be skipped
16
+ */
17
+ rawTextSelectors?: string;
18
+ }
19
+ export interface BindContext {
20
+ [key: string]: unknown;
21
+ }
22
+ export type DisposeFunction = () => void;
23
+ /**
24
+ * Bind a DOM tree to a reactive context.
25
+ *
26
+ * @param root - The root element to bind
27
+ * @param ctx - The context object containing handlers and reactive values
28
+ * @param options - Binding options
29
+ * @returns A dispose function that removes all bindings
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * import { bind } from 'dalila/runtime';
34
+ *
35
+ * const ctx = {
36
+ * count: signal(0),
37
+ * increment: () => count.update(n => n + 1),
38
+ * };
39
+ *
40
+ * const dispose = bind(document.getElementById('app')!, ctx);
41
+ *
42
+ * // Later, to cleanup:
43
+ * dispose();
44
+ * ```
45
+ */
46
+ export declare function bind(root: Element, ctx: BindContext, options?: BindOptions): DisposeFunction;
47
+ /**
48
+ * Automatically bind when DOM is ready.
49
+ * Useful for simple pages without a build step.
50
+ *
51
+ * @example
52
+ * ```html
53
+ * <script type="module">
54
+ * import { autoBind } from 'dalila/runtime';
55
+ * autoBind('#app', { count: signal(0) });
56
+ * </script>
57
+ * ```
58
+ */
59
+ export declare function autoBind(selector: string, ctx: BindContext, options?: BindOptions): Promise<DisposeFunction>;
@@ -0,0 +1,340 @@
1
+ /**
2
+ * Dalila Template Runtime - bind()
3
+ *
4
+ * Binds a DOM tree to a reactive context using declarative attributes.
5
+ * No eval, no inline JS execution - only identifier resolution from ctx.
6
+ *
7
+ * @module dalila/runtime
8
+ */
9
+ import { effect, createScope, withScope, isInDevMode } from '../core/index.js';
10
+ // ============================================================================
11
+ // Utilities
12
+ // ============================================================================
13
+ /**
14
+ * Check if a value is a Dalila signal
15
+ */
16
+ function isSignal(value) {
17
+ return typeof value === 'function' && 'set' in value && 'update' in value;
18
+ }
19
+ /**
20
+ * Resolve a value from ctx - handles signals, functions, and plain values
21
+ */
22
+ function resolve(value) {
23
+ if (isSignal(value))
24
+ return value();
25
+ if (typeof value === 'function')
26
+ return value();
27
+ return value;
28
+ }
29
+ /**
30
+ * Normalize binding attribute value
31
+ * Handles both "name" and "{name}" formats
32
+ */
33
+ function normalizeBinding(raw) {
34
+ if (!raw)
35
+ return null;
36
+ const trimmed = raw.trim();
37
+ // Match {name} format and extract name
38
+ const match = trimmed.match(/^\{\s*([a-zA-Z_$][\w$]*)\s*\}$/);
39
+ return match ? match[1] : trimmed;
40
+ }
41
+ /**
42
+ * Dev mode warning helper
43
+ */
44
+ function warn(message) {
45
+ if (isInDevMode()) {
46
+ console.warn(`[Dalila] ${message}`);
47
+ }
48
+ }
49
+ // ============================================================================
50
+ // Default Options
51
+ // ============================================================================
52
+ const DEFAULT_EVENTS = ['click', 'input', 'change', 'submit', 'keydown', 'keyup'];
53
+ const DEFAULT_RAW_TEXT_SELECTORS = 'pre, code';
54
+ // ============================================================================
55
+ // Text Interpolation
56
+ // ============================================================================
57
+ /**
58
+ * Process a text node and replace {tokens} with reactive bindings
59
+ */
60
+ function bindTextNode(node, ctx, cleanups) {
61
+ const text = node.data;
62
+ const regex = /\{\s*([a-zA-Z_$][\w$]*)\s*\}/g;
63
+ // Check if there are any tokens
64
+ if (!regex.test(text))
65
+ return;
66
+ // Reset regex
67
+ regex.lastIndex = 0;
68
+ const frag = document.createDocumentFragment();
69
+ let cursor = 0;
70
+ let match;
71
+ while ((match = regex.exec(text)) !== null) {
72
+ // Add text before the token
73
+ const before = text.slice(cursor, match.index);
74
+ if (before) {
75
+ frag.appendChild(document.createTextNode(before));
76
+ }
77
+ const key = match[1];
78
+ const value = ctx[key];
79
+ if (value === undefined) {
80
+ warn(`Text interpolation: "${key}" not found in context`);
81
+ frag.appendChild(document.createTextNode(match[0]));
82
+ }
83
+ else if (isSignal(value)) {
84
+ // Reactive text node
85
+ const textNode = document.createTextNode('');
86
+ const stop = effect(() => {
87
+ textNode.data = String(value());
88
+ });
89
+ if (typeof stop === 'function') {
90
+ cleanups.push(stop);
91
+ }
92
+ frag.appendChild(textNode);
93
+ }
94
+ else {
95
+ // Static value - render once
96
+ frag.appendChild(document.createTextNode(String(value)));
97
+ }
98
+ cursor = match.index + match[0].length;
99
+ }
100
+ // Add remaining text
101
+ const after = text.slice(cursor);
102
+ if (after) {
103
+ frag.appendChild(document.createTextNode(after));
104
+ }
105
+ // Replace original node
106
+ if (node.parentNode) {
107
+ node.parentNode.replaceChild(frag, node);
108
+ }
109
+ }
110
+ // ============================================================================
111
+ // Event Binding
112
+ // ============================================================================
113
+ /**
114
+ * Bind all d-on-* events within root
115
+ */
116
+ function bindEvents(root, ctx, events, cleanups) {
117
+ for (const eventName of events) {
118
+ const attr = `d-on-${eventName}`;
119
+ const elements = root.querySelectorAll(`[${attr}]`);
120
+ elements.forEach((el) => {
121
+ const handlerName = normalizeBinding(el.getAttribute(attr));
122
+ if (!handlerName)
123
+ return;
124
+ const handler = ctx[handlerName];
125
+ if (handler === undefined) {
126
+ warn(`Event handler "${handlerName}" not found in context`);
127
+ return;
128
+ }
129
+ if (typeof handler !== 'function') {
130
+ warn(`Event handler "${handlerName}" is not a function`);
131
+ return;
132
+ }
133
+ el.addEventListener(eventName, handler);
134
+ cleanups.push(() => el.removeEventListener(eventName, handler));
135
+ });
136
+ }
137
+ }
138
+ // ============================================================================
139
+ // when Directive
140
+ // ============================================================================
141
+ /**
142
+ * Bind all [when] directives within root
143
+ */
144
+ function bindWhen(root, ctx, cleanups) {
145
+ const elements = root.querySelectorAll('[when]');
146
+ elements.forEach((el) => {
147
+ const bindingName = normalizeBinding(el.getAttribute('when'));
148
+ if (!bindingName)
149
+ return;
150
+ const binding = ctx[bindingName];
151
+ if (binding === undefined) {
152
+ warn(`when: "${bindingName}" not found in context`);
153
+ return;
154
+ }
155
+ const htmlEl = el;
156
+ const stop = effect(() => {
157
+ const value = !!resolve(binding);
158
+ htmlEl.style.display = value ? '' : 'none';
159
+ });
160
+ if (typeof stop === 'function') {
161
+ cleanups.push(stop);
162
+ }
163
+ });
164
+ }
165
+ // ============================================================================
166
+ // match Directive
167
+ // ============================================================================
168
+ /**
169
+ * Bind all [match] directives within root
170
+ */
171
+ function bindMatch(root, ctx, cleanups) {
172
+ const elements = root.querySelectorAll('[match]');
173
+ elements.forEach((el) => {
174
+ const bindingName = normalizeBinding(el.getAttribute('match'));
175
+ if (!bindingName)
176
+ return;
177
+ const binding = ctx[bindingName];
178
+ if (binding === undefined) {
179
+ warn(`match: "${bindingName}" not found in context`);
180
+ return;
181
+ }
182
+ const cases = Array.from(el.querySelectorAll('[case]'));
183
+ const stop = effect(() => {
184
+ const value = String(resolve(binding));
185
+ let matchedEl = null;
186
+ let defaultEl = null;
187
+ // First pass: hide all and find match/default
188
+ for (const caseEl of cases) {
189
+ caseEl.style.display = 'none';
190
+ const caseValue = caseEl.getAttribute('case');
191
+ if (caseValue === 'default') {
192
+ defaultEl = caseEl;
193
+ }
194
+ else if (caseValue === value && !matchedEl) {
195
+ matchedEl = caseEl;
196
+ }
197
+ }
198
+ // Second pass: show match OR default (not both)
199
+ if (matchedEl) {
200
+ matchedEl.style.display = '';
201
+ }
202
+ else if (defaultEl) {
203
+ defaultEl.style.display = '';
204
+ }
205
+ });
206
+ if (typeof stop === 'function') {
207
+ cleanups.push(stop);
208
+ }
209
+ });
210
+ }
211
+ // ============================================================================
212
+ // Main bind() Function
213
+ // ============================================================================
214
+ /**
215
+ * Bind a DOM tree to a reactive context.
216
+ *
217
+ * @param root - The root element to bind
218
+ * @param ctx - The context object containing handlers and reactive values
219
+ * @param options - Binding options
220
+ * @returns A dispose function that removes all bindings
221
+ *
222
+ * @example
223
+ * ```ts
224
+ * import { bind } from 'dalila/runtime';
225
+ *
226
+ * const ctx = {
227
+ * count: signal(0),
228
+ * increment: () => count.update(n => n + 1),
229
+ * };
230
+ *
231
+ * const dispose = bind(document.getElementById('app')!, ctx);
232
+ *
233
+ * // Later, to cleanup:
234
+ * dispose();
235
+ * ```
236
+ */
237
+ export function bind(root, ctx, options = {}) {
238
+ const events = options.events ?? DEFAULT_EVENTS;
239
+ const rawTextSelectors = options.rawTextSelectors ?? DEFAULT_RAW_TEXT_SELECTORS;
240
+ const htmlRoot = root;
241
+ // HMR support: Register binding context globally in dev mode
242
+ if (isInDevMode()) {
243
+ globalThis.__dalila_hmr_context = { root, ctx, options };
244
+ }
245
+ // Create a scope for this template binding
246
+ const templateScope = createScope();
247
+ const cleanups = [];
248
+ // Run all bindings within the template scope
249
+ withScope(templateScope, () => {
250
+ // 1. Text interpolation
251
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
252
+ const textNodes = [];
253
+ while (walker.nextNode()) {
254
+ const node = walker.currentNode;
255
+ // Skip nodes inside raw text containers
256
+ const parent = node.parentElement;
257
+ if (parent && parent.closest(rawTextSelectors)) {
258
+ continue;
259
+ }
260
+ if (node.data.includes('{')) {
261
+ textNodes.push(node);
262
+ }
263
+ }
264
+ // Process text nodes (collect first, then process to avoid walker issues)
265
+ for (const node of textNodes) {
266
+ bindTextNode(node, ctx, cleanups);
267
+ }
268
+ // 2. Event bindings
269
+ bindEvents(root, ctx, events, cleanups);
270
+ // 3. when directive
271
+ bindWhen(root, ctx, cleanups);
272
+ // 4. match directive
273
+ bindMatch(root, ctx, cleanups);
274
+ });
275
+ // Bindings complete: remove loading state and mark as ready
276
+ // Use microtask to ensure all effects have run at least once
277
+ queueMicrotask(() => {
278
+ htmlRoot.removeAttribute('d-loading');
279
+ htmlRoot.setAttribute('d-ready', '');
280
+ });
281
+ // Return dispose function
282
+ return () => {
283
+ // Run manual cleanups (event listeners)
284
+ for (const cleanup of cleanups) {
285
+ if (typeof cleanup === 'function') {
286
+ try {
287
+ cleanup();
288
+ }
289
+ catch (e) {
290
+ if (isInDevMode()) {
291
+ console.warn('[Dalila] Cleanup error:', e);
292
+ }
293
+ }
294
+ }
295
+ }
296
+ cleanups.length = 0;
297
+ // Dispose template scope (stops all effects)
298
+ try {
299
+ templateScope.dispose();
300
+ }
301
+ catch (e) {
302
+ if (isInDevMode()) {
303
+ console.warn('[Dalila] Scope dispose error:', e);
304
+ }
305
+ }
306
+ };
307
+ }
308
+ // ============================================================================
309
+ // Convenience: Auto-bind on DOMContentLoaded
310
+ // ============================================================================
311
+ /**
312
+ * Automatically bind when DOM is ready.
313
+ * Useful for simple pages without a build step.
314
+ *
315
+ * @example
316
+ * ```html
317
+ * <script type="module">
318
+ * import { autoBind } from 'dalila/runtime';
319
+ * autoBind('#app', { count: signal(0) });
320
+ * </script>
321
+ * ```
322
+ */
323
+ export function autoBind(selector, ctx, options) {
324
+ return new Promise((resolve, reject) => {
325
+ const doBind = () => {
326
+ const root = document.querySelector(selector);
327
+ if (!root) {
328
+ reject(new Error(`[Dalila] Element not found: ${selector}`));
329
+ return;
330
+ }
331
+ resolve(bind(root, ctx, options));
332
+ };
333
+ if (document.readyState === 'loading') {
334
+ document.addEventListener('DOMContentLoaded', doBind, { once: true });
335
+ }
336
+ else {
337
+ doBind();
338
+ }
339
+ });
340
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Dalila Runtime Module
3
+ *
4
+ * Provides declarative DOM binding with reactive updates.
5
+ * No eval, no inline JS - only identifier resolution.
6
+ *
7
+ * @module dalila/runtime
8
+ */
9
+ export { bind, autoBind } from './bind.js';
10
+ export type { BindOptions, BindContext, DisposeFunction } from './bind.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Dalila Runtime Module
3
+ *
4
+ * Provides declarative DOM binding with reactive updates.
5
+ * No eval, no inline JS - only identifier resolution.
6
+ *
7
+ * @module dalila/runtime
8
+ */
9
+ export { bind, autoBind } from './bind.js';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * dalila/simple - Simplified API
3
+ *
4
+ * Just the essentials:
5
+ * - Global store (no Zustand needed)
6
+ * - Auto-scope context (menos verboso)
7
+ * - Core reactivity primitives
8
+ *
9
+ * Philosophy: Use HTML templates (via dev-server), not hyperscript.
10
+ */
11
+ export * from './core/index.js';
package/dist/simple.js ADDED
@@ -0,0 +1,11 @@
1
+ /**
2
+ * dalila/simple - Simplified API
3
+ *
4
+ * Just the essentials:
5
+ * - Global store (no Zustand needed)
6
+ * - Auto-scope context (menos verboso)
7
+ * - Core reactivity primitives
8
+ *
9
+ * Philosophy: Use HTML templates (via dev-server), not hyperscript.
10
+ */
11
+ export * from './core/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dalila",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "description": "DOM-first reactive framework based on signals",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",