@ai11y/core 0.0.1

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 (107) hide show
  1. package/.turbo/turbo-build.log +87 -0
  2. package/CHANGELOG.md +29 -0
  3. package/README.md +37 -0
  4. package/dist/agent/agent-adapter.d.mts +17 -0
  5. package/dist/agent/agent-adapter.d.mts.map +1 -0
  6. package/dist/agent/agent-adapter.mjs +45 -0
  7. package/dist/agent/agent-adapter.mjs.map +1 -0
  8. package/dist/agent/llm-agent.d.mts +13 -0
  9. package/dist/agent/llm-agent.d.mts.map +1 -0
  10. package/dist/agent/llm-agent.mjs +41 -0
  11. package/dist/agent/llm-agent.mjs.map +1 -0
  12. package/dist/agent/plan.d.mts +27 -0
  13. package/dist/agent/plan.d.mts.map +1 -0
  14. package/dist/agent/plan.mjs +28 -0
  15. package/dist/agent/plan.mjs.map +1 -0
  16. package/dist/agent/rule-based-agent.d.mts +13 -0
  17. package/dist/agent/rule-based-agent.d.mts.map +1 -0
  18. package/dist/agent/rule-based-agent.mjs +152 -0
  19. package/dist/agent/rule-based-agent.mjs.map +1 -0
  20. package/dist/agent/tool-contract.d.mts +19 -0
  21. package/dist/agent/tool-contract.d.mts.map +1 -0
  22. package/dist/agent/types.d.mts +77 -0
  23. package/dist/agent/types.d.mts.map +1 -0
  24. package/dist/client-api.d.mts +49 -0
  25. package/dist/client-api.d.mts.map +1 -0
  26. package/dist/client-api.mjs +68 -0
  27. package/dist/client-api.mjs.map +1 -0
  28. package/dist/context.d.mts +29 -0
  29. package/dist/context.d.mts.map +1 -0
  30. package/dist/dom-actions/click.d.mts +15 -0
  31. package/dist/dom-actions/click.d.mts.map +1 -0
  32. package/dist/dom-actions/click.mjs +36 -0
  33. package/dist/dom-actions/click.mjs.map +1 -0
  34. package/dist/dom-actions/fill-input.d.mts +17 -0
  35. package/dist/dom-actions/fill-input.d.mts.map +1 -0
  36. package/dist/dom-actions/fill-input.mjs +69 -0
  37. package/dist/dom-actions/fill-input.mjs.map +1 -0
  38. package/dist/dom-actions/find-element.mjs +17 -0
  39. package/dist/dom-actions/find-element.mjs.map +1 -0
  40. package/dist/dom-actions/highlight.d.mts +34 -0
  41. package/dist/dom-actions/highlight.d.mts.map +1 -0
  42. package/dist/dom-actions/highlight.mjs +60 -0
  43. package/dist/dom-actions/highlight.mjs.map +1 -0
  44. package/dist/dom-actions/navigate.d.mts +16 -0
  45. package/dist/dom-actions/navigate.d.mts.map +1 -0
  46. package/dist/dom-actions/navigate.mjs +22 -0
  47. package/dist/dom-actions/navigate.mjs.map +1 -0
  48. package/dist/dom-actions/scroll.d.mts +16 -0
  49. package/dist/dom-actions/scroll.d.mts.map +1 -0
  50. package/dist/dom-actions/scroll.mjs +32 -0
  51. package/dist/dom-actions/scroll.mjs.map +1 -0
  52. package/dist/dom.d.mts +23 -0
  53. package/dist/dom.d.mts.map +1 -0
  54. package/dist/dom.mjs +60 -0
  55. package/dist/dom.mjs.map +1 -0
  56. package/dist/events.d.mts +35 -0
  57. package/dist/events.d.mts.map +1 -0
  58. package/dist/events.mjs +49 -0
  59. package/dist/events.mjs.map +1 -0
  60. package/dist/index.d.mts +21 -0
  61. package/dist/index.mjs +18 -0
  62. package/dist/instruction.d.mts +21 -0
  63. package/dist/instruction.d.mts.map +1 -0
  64. package/dist/marker.d.mts +35 -0
  65. package/dist/marker.d.mts.map +1 -0
  66. package/dist/marker.mjs +137 -0
  67. package/dist/marker.mjs.map +1 -0
  68. package/dist/store.d.mts +56 -0
  69. package/dist/store.d.mts.map +1 -0
  70. package/dist/store.mjs +114 -0
  71. package/dist/store.mjs.map +1 -0
  72. package/dist/util/attributes.d.mts +57 -0
  73. package/dist/util/attributes.d.mts.map +1 -0
  74. package/dist/util/attributes.mjs +68 -0
  75. package/dist/util/attributes.mjs.map +1 -0
  76. package/dist/util/format.d.mts +18 -0
  77. package/dist/util/format.d.mts.map +1 -0
  78. package/dist/util/format.mjs +21 -0
  79. package/dist/util/format.mjs.map +1 -0
  80. package/package.json +26 -0
  81. package/src/agent/agent-adapter.ts +75 -0
  82. package/src/agent/index.ts +21 -0
  83. package/src/agent/llm-agent.ts +64 -0
  84. package/src/agent/plan.ts +41 -0
  85. package/src/agent/rule-based-agent.ts +269 -0
  86. package/src/agent/tool-contract.ts +22 -0
  87. package/src/agent/types.ts +83 -0
  88. package/src/client-api.ts +107 -0
  89. package/src/context.ts +28 -0
  90. package/src/dom-actions/click.ts +39 -0
  91. package/src/dom-actions/fill-input.ts +113 -0
  92. package/src/dom-actions/find-element.ts +14 -0
  93. package/src/dom-actions/highlight.ts +93 -0
  94. package/src/dom-actions/index.ts +5 -0
  95. package/src/dom-actions/navigate.ts +17 -0
  96. package/src/dom-actions/scroll.ts +29 -0
  97. package/src/dom.ts +89 -0
  98. package/src/events.ts +55 -0
  99. package/src/index.ts +55 -0
  100. package/src/instruction.ts +6 -0
  101. package/src/marker.ts +237 -0
  102. package/src/store.ts +138 -0
  103. package/src/util/attributes.ts +68 -0
  104. package/src/util/format.ts +16 -0
  105. package/src/util/index.ts +2 -0
  106. package/tsconfig.json +18 -0
  107. package/tsdown.config.ts +10 -0
package/src/index.ts ADDED
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @ai11y/core
3
+ *
4
+ * Core types and utilities shared across all ai11y packages.
5
+ */
6
+
7
+ export {
8
+ type AgentAdapterConfig,
9
+ type AgentConfig,
10
+ type AgentMode,
11
+ type AgentRequest,
12
+ type AgentResponse,
13
+ type ConversationMessage,
14
+ type LLMAgentConfig,
15
+ runAgentAdapter,
16
+ runLLMAgent,
17
+ runRuleBasedAgent,
18
+ } from "./agent/index.js";
19
+ export { plan } from "./agent/plan.js";
20
+ export type { ToolDefinition, ToolExecutor } from "./agent/tool-contract.js";
21
+ export { type Ai11yClient, createClient } from "./client-api.js";
22
+ export type {
23
+ Ai11yContext,
24
+ Ai11yError,
25
+ Ai11yEvent,
26
+ Ai11yState,
27
+ } from "./context.js";
28
+ export { getContext } from "./dom.js";
29
+ export {
30
+ clickMarker,
31
+ fillInputMarker,
32
+ type HighlightOptions,
33
+ highlightMarker,
34
+ navigateToRoute,
35
+ scrollToMarker,
36
+ } from "./dom-actions/index.js";
37
+ export { getSubscriberCount, notify, subscribe } from "./events.js";
38
+ export type { Instruction } from "./instruction.js";
39
+ export type { Marker } from "./marker.js";
40
+ export { getMarkers } from "./marker.js";
41
+ export {
42
+ clearContext,
43
+ clearEvents,
44
+ clearState,
45
+ getError,
46
+ getEvents,
47
+ getRoute,
48
+ getState,
49
+ setError,
50
+ setRoute,
51
+ setState,
52
+ subscribeToStore,
53
+ track,
54
+ } from "./store.js";
55
+ export * from "./util/index.js";
@@ -0,0 +1,6 @@
1
+ export type Instruction =
2
+ | { action: "click"; id: string }
3
+ | { action: "navigate"; route: string }
4
+ | { action: "highlight"; id: string }
5
+ | { action: "scroll"; id: string }
6
+ | { action: "fillInput"; id: string; value: string };
package/src/marker.ts ADDED
@@ -0,0 +1,237 @@
1
+ import {
2
+ ATTRIBUTE_SENSITIVE,
3
+ getAllMarkersSelector,
4
+ getMarkerId,
5
+ getMarkerIntent,
6
+ getMarkerLabel,
7
+ } from "./util/attributes.js";
8
+ import { formatMarkerId } from "./util/format.js";
9
+
10
+ /**
11
+ * Marker information for UI elements
12
+ */
13
+ export interface Marker {
14
+ id: string;
15
+ label: string;
16
+ intent: string;
17
+ elementType: string;
18
+ /** Current value for input/textarea elements */
19
+ value?: string;
20
+ /** Selected value(s) for select elements */
21
+ selectedOptions?: string[];
22
+ /** All available options for select elements */
23
+ options?: Array<{ value: string; label: string }>;
24
+ }
25
+
26
+ /**
27
+ * Gets the document body in a type-safe way
28
+ * Returns null if not in a browser environment
29
+ */
30
+ function getDocumentBody(): Element | null {
31
+ if (typeof document === "undefined") {
32
+ return null;
33
+ }
34
+ return document.body;
35
+ }
36
+
37
+ /**
38
+ * Finds an input or textarea element within a marked element
39
+ * Handles both direct input elements and nested inputs (when Mark wraps the input)
40
+ */
41
+ function findInputElement(
42
+ element: Element,
43
+ ): HTMLInputElement | HTMLTextAreaElement | null {
44
+ if (
45
+ element instanceof HTMLInputElement ||
46
+ element instanceof HTMLTextAreaElement
47
+ ) {
48
+ return element;
49
+ }
50
+ if (element instanceof HTMLElement) {
51
+ const nestedInput = element.querySelector("input, textarea");
52
+ if (
53
+ nestedInput instanceof HTMLInputElement ||
54
+ nestedInput instanceof HTMLTextAreaElement
55
+ ) {
56
+ return nestedInput;
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+
62
+ /**
63
+ * Finds a select element within a marked element
64
+ * Handles both direct select elements and nested selects (when Mark wraps the select)
65
+ */
66
+ function findSelectElement(element: Element): HTMLSelectElement | null {
67
+ if (element instanceof HTMLSelectElement) {
68
+ return element;
69
+ }
70
+ if (element instanceof HTMLElement) {
71
+ const nestedSelect = element.querySelector("select");
72
+ if (nestedSelect instanceof HTMLSelectElement) {
73
+ return nestedSelect;
74
+ }
75
+ }
76
+ return null;
77
+ }
78
+
79
+ /**
80
+ * Checks if an input element contains sensitive data that should be redacted
81
+ * from the UI context (passwords, credit cards, hidden fields, etc.)
82
+ *
83
+ * @param inputElement - The input or textarea element to check
84
+ * @returns True if the input contains sensitive data
85
+ */
86
+ function isSensitiveInput(
87
+ inputElement: HTMLInputElement | HTMLTextAreaElement,
88
+ ): boolean {
89
+ // Check input type
90
+ if (inputElement instanceof HTMLInputElement) {
91
+ const type = inputElement.type.toLowerCase();
92
+ if (type === "password" || type === "hidden") {
93
+ return true;
94
+ }
95
+ }
96
+
97
+ // Check autocomplete attribute for sensitive patterns
98
+ const autocomplete = inputElement.getAttribute("autocomplete")?.toLowerCase();
99
+ if (autocomplete) {
100
+ const sensitiveAutocompletePaths = [
101
+ "current-password",
102
+ "new-password",
103
+ "cc-number",
104
+ "cc-csc",
105
+ "cc-exp",
106
+ "cc-exp-month",
107
+ "cc-exp-year",
108
+ ];
109
+ if (
110
+ sensitiveAutocompletePaths.some((path) => autocomplete.includes(path))
111
+ ) {
112
+ return true;
113
+ }
114
+ }
115
+
116
+ // Check for custom sensitive marker attribute
117
+ if (inputElement.getAttribute(ATTRIBUTE_SENSITIVE) === "true") {
118
+ return true;
119
+ }
120
+
121
+ // Check parent element for sensitive marker attribute
122
+ const parent = inputElement.parentElement;
123
+ if (parent && parent.getAttribute(ATTRIBUTE_SENSITIVE) === "true") {
124
+ return true;
125
+ }
126
+
127
+ return false;
128
+ }
129
+
130
+ /**
131
+ * Extracts the value from an input or textarea element
132
+ * Redacts sensitive values (passwords, credit cards, etc.) for privacy
133
+ */
134
+ function extractInputValue(element: Element): string | undefined {
135
+ const inputElement = findInputElement(element);
136
+ if (!inputElement) {
137
+ return undefined;
138
+ }
139
+ if (isSensitiveInput(inputElement)) {
140
+ return "[REDACTED]";
141
+ }
142
+ return inputElement.value;
143
+ }
144
+
145
+ /**
146
+ * Extracts options and selected values from a select element
147
+ */
148
+ function extractSelectData(element: Element): {
149
+ options?: Array<{ value: string; label: string }>;
150
+ selectedOptions?: string[];
151
+ } {
152
+ const selectElement = findSelectElement(element);
153
+ if (!selectElement) {
154
+ return {};
155
+ }
156
+
157
+ const options: Array<{ value: string; label: string }> = [];
158
+ for (let i = 0; i < selectElement.options.length; i++) {
159
+ const option = selectElement.options[i];
160
+ options.push({
161
+ value: option.value,
162
+ label: option.text,
163
+ });
164
+ }
165
+
166
+ const selectedOptions: string[] = [];
167
+ if (selectElement.multiple) {
168
+ for (let i = 0; i < selectElement.selectedOptions.length; i++) {
169
+ selectedOptions.push(selectElement.selectedOptions[i].value);
170
+ }
171
+ } else {
172
+ if (selectElement.value) {
173
+ selectedOptions.push(selectElement.value);
174
+ }
175
+ }
176
+
177
+ return {
178
+ options: options.length > 0 ? options : undefined,
179
+ selectedOptions: selectedOptions.length > 0 ? selectedOptions : undefined,
180
+ };
181
+ }
182
+
183
+ /**
184
+ * Scans the DOM for elements with data-ai-* attributes and returns markers
185
+ *
186
+ * @param root - Optional DOM root element to scan (defaults to document.body)
187
+ * @returns Array of Marker objects found in the DOM
188
+ *
189
+ * @example
190
+ * ```ts
191
+ * const markers = getMarkers();
192
+ * // Scans document.body for data-ai-* attributes
193
+ * ```
194
+ */
195
+ export function getMarkers(root?: Element): Marker[] {
196
+ const scanRoot = root ?? getDocumentBody();
197
+
198
+ if (!scanRoot) {
199
+ return [];
200
+ }
201
+
202
+ const elements = scanRoot.querySelectorAll(getAllMarkersSelector());
203
+ const markers: Marker[] = [];
204
+ for (let i = 0; i < elements.length; i++) {
205
+ const element = elements[i];
206
+ const id = getMarkerId(element);
207
+ if (!id) continue;
208
+
209
+ const label = getMarkerLabel(element) || formatMarkerId(id);
210
+ const intent = getMarkerIntent(element) || "";
211
+ const elementType = element.tagName.toLowerCase();
212
+
213
+ const marker: Marker = {
214
+ id,
215
+ label,
216
+ intent,
217
+ elementType,
218
+ };
219
+
220
+ const inputValue = extractInputValue(element);
221
+ if (inputValue !== undefined) {
222
+ marker.value = inputValue;
223
+ }
224
+
225
+ const selectData = extractSelectData(element);
226
+ if (selectData.options !== undefined) {
227
+ marker.options = selectData.options;
228
+ }
229
+ if (selectData.selectedOptions !== undefined) {
230
+ marker.selectedOptions = selectData.selectedOptions;
231
+ }
232
+
233
+ markers.push(marker);
234
+ }
235
+
236
+ return markers;
237
+ }
package/src/store.ts ADDED
@@ -0,0 +1,138 @@
1
+ import type { Ai11yError, Ai11yEvent, Ai11yState } from "./context.js";
2
+ import { notify } from "./events.js";
3
+
4
+ let route: string | undefined;
5
+ let state: Ai11yState | undefined;
6
+ let error: Ai11yError | null | undefined;
7
+ let events: Ai11yEvent[] = [];
8
+
9
+ type StoreChangeListener = (
10
+ type: "route" | "state" | "error",
11
+ value: unknown,
12
+ ) => void;
13
+
14
+ const storeListeners = new Set<StoreChangeListener>();
15
+
16
+ function notifyStoreChange(
17
+ type: "route" | "state" | "error",
18
+ value: unknown,
19
+ ): void {
20
+ for (const listener of storeListeners) {
21
+ try {
22
+ listener(type, value);
23
+ } catch (err) {
24
+ // Don't let one listener's error break others
25
+ console.error("Error in store change listener:", err);
26
+ }
27
+ }
28
+ }
29
+
30
+ export function setRoute(newRoute: string | undefined): void {
31
+ route = newRoute;
32
+ notifyStoreChange("route", newRoute);
33
+ }
34
+
35
+ export function getRoute(): string | undefined {
36
+ return route;
37
+ }
38
+
39
+ /**
40
+ * Merges new state with existing state (similar to React's setState)
41
+ * Pass undefined to clear all state
42
+ *
43
+ * @param newState - Partial state to merge, or undefined to clear
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * setState({ userId: '123' }); // Merges with existing state
48
+ * setState({ theme: 'dark' }); // Adds to state, keeps userId
49
+ * setState(undefined); // Clears all state
50
+ * ```
51
+ */
52
+ export function setState(newState: Ai11yState | undefined): void {
53
+ if (newState === undefined) {
54
+ state = undefined;
55
+ } else {
56
+ state = { ...(state || {}), ...newState };
57
+ }
58
+ notifyStoreChange("state", state);
59
+ }
60
+
61
+ /**
62
+ * Clears all application state
63
+ *
64
+ * @example
65
+ * ```ts
66
+ * clearState(); // Resets state to empty
67
+ * ```
68
+ */
69
+ export function clearState(): void {
70
+ state = undefined;
71
+ notifyStoreChange("state", undefined);
72
+ }
73
+
74
+ export function getState(): Ai11yState | undefined {
75
+ return state;
76
+ }
77
+
78
+ export function setError(newError: Ai11yError | null | undefined): void {
79
+ error = newError;
80
+ notifyStoreChange("error", newError);
81
+ }
82
+
83
+ export function getError(): Ai11yError | null | undefined {
84
+ return error;
85
+ }
86
+
87
+ export function track(event: string, payload?: unknown): void {
88
+ events = [
89
+ ...events.slice(-49), // Keep last 50 events
90
+ {
91
+ type: event,
92
+ payload,
93
+ timestamp: Date.now(),
94
+ },
95
+ ];
96
+ notify();
97
+ }
98
+
99
+ export function getEvents(): Ai11yEvent[] {
100
+ return events;
101
+ }
102
+
103
+ export function clearEvents(): void {
104
+ events = [];
105
+ }
106
+
107
+ /**
108
+ * Subscribe to store changes (route, state, error)
109
+ * Returns an unsubscribe function
110
+ *
111
+ * @param listener - Function called when route, state, or error changes
112
+ * @returns Unsubscribe function
113
+ *
114
+ * @example
115
+ * ```ts
116
+ * const unsubscribe = subscribeToStore((type, value) => {
117
+ * if (type === 'route') console.log('Route changed:', value);
118
+ * });
119
+ * // Later...
120
+ * unsubscribe();
121
+ * ```
122
+ */
123
+ export function subscribeToStore(listener: StoreChangeListener): () => void {
124
+ storeListeners.add(listener);
125
+ return () => {
126
+ storeListeners.delete(listener);
127
+ };
128
+ }
129
+
130
+ export function clearContext(): void {
131
+ route = undefined;
132
+ state = undefined;
133
+ error = undefined;
134
+ events = [];
135
+ notifyStoreChange("route", undefined);
136
+ notifyStoreChange("state", undefined);
137
+ notifyStoreChange("error", undefined);
138
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Attribute name constants for data-ai-* attributes
3
+ */
4
+ export const ATTRIBUTE_ID = "data-ai-id";
5
+ export const ATTRIBUTE_LABEL = "data-ai-label";
6
+ export const ATTRIBUTE_INTENT = "data-ai-intent";
7
+ export const ATTRIBUTE_SENSITIVE = "data-ai-sensitive";
8
+
9
+ /**
10
+ * Gets the value of the data-ai-id attribute from an element
11
+ *
12
+ * @param element - The element to get the attribute from
13
+ * @returns The marker ID or null if not found
14
+ */
15
+ export function getMarkerId(element: Element): string | null {
16
+ return element.getAttribute(ATTRIBUTE_ID);
17
+ }
18
+
19
+ /**
20
+ * Gets the value of the data-ai-label attribute from an element
21
+ *
22
+ * @param element - The element to get the attribute from
23
+ * @returns The marker label or null if not found
24
+ */
25
+ export function getMarkerLabel(element: Element): string | null {
26
+ return element.getAttribute(ATTRIBUTE_LABEL);
27
+ }
28
+
29
+ /**
30
+ * Gets the value of the data-ai-intent attribute from an element
31
+ *
32
+ * @param element - The element to get the attribute from
33
+ * @returns The marker intent or null if not found
34
+ */
35
+ export function getMarkerIntent(element: Element): string | null {
36
+ return element.getAttribute(ATTRIBUTE_INTENT);
37
+ }
38
+
39
+ /**
40
+ * Creates a query selector for finding an element by marker ID
41
+ *
42
+ * @param markerId - The marker ID to search for
43
+ * @returns A query selector string
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * const selector = getMarkerSelector('connect_stripe');
48
+ * // Returns: '[data-ai-id="connect_stripe"]'
49
+ * ```
50
+ */
51
+ export function getMarkerSelector(markerId: string): string {
52
+ return `[${ATTRIBUTE_ID}="${markerId}"]`;
53
+ }
54
+
55
+ /**
56
+ * Creates a query selector for finding all elements with marker IDs
57
+ *
58
+ * @returns A query selector string
59
+ *
60
+ * @example
61
+ * ```ts
62
+ * const selector = getAllMarkersSelector();
63
+ * // Returns: '[data-ai-id]'
64
+ * ```
65
+ */
66
+ export function getAllMarkersSelector(): string {
67
+ return `[${ATTRIBUTE_ID}]`;
68
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Formats a marker ID into a readable label
3
+ * Converts snake_case to Title Case
4
+ *
5
+ * @param id - The marker ID to format
6
+ * @returns A formatted label
7
+ *
8
+ * @example
9
+ * ```ts
10
+ * formatMarkerId('connect_stripe');
11
+ * // Returns: 'Connect Stripe'
12
+ * ```
13
+ */
14
+ export function formatMarkerId(id: string): string {
15
+ return id.replace(/_/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
16
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./attributes.js";
2
+ export * from "./format.js";
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "lib": ["ES2022", "DOM"],
6
+ "moduleResolution": "nodenext",
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "rootDir": "src",
14
+ "outDir": "dist"
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from "tsdown";
2
+
3
+ export default defineConfig({
4
+ entry: ["src/index.ts"],
5
+ unbundle: true,
6
+ format: ["esm"],
7
+ dts: true,
8
+ clean: true,
9
+ outDir: "dist",
10
+ });