Repository: atomicdata-dev/atomic-server (language: rust)

Issue:
Better package linting
There are certain steps that need to be taken to make a JavaScript package easily usable in a wide range of environments. For instance, there are some subtle quirks that aren’t immediately apparent, such as ensuring that the type export rule in package.json precedes the others.

We should add publint and are my trypes wrong checks to the packages and to the CI to make sure our packages are up to standard.


Discussion / hints:

Fix patch:
diff --git a/browser/.gitignore b/browser/.gitignore
index 5b0e76b5e..75baf8392 100644
--- a/browser/.gitignore
+++ b/browser/.gitignore
@@ -6,6 +6,7 @@ publish
 .husky
 .nohup
 .swc
+.tsup
 */lib
 */dist
 */dev-dist
@@ -26,3 +27,9 @@ data-browser/coverage
 !.yarn/versions
 .DS_Store
 **/.trunk/*
+
+**/tomic-lib-**.tgz
+**/tomic-react-**.tgz
+**/tomic-svelte-**.tgz
+**/tomic-cli-**.tgz
+**/tomic-create-template-**.tgz
diff --git a/browser/CHANGELOG.md b/browser/CHANGELOG.md
index 8c8401539..eebf839de 100644
--- a/browser/CHANGELOG.md
+++ b/browser/CHANGELOG.md
@@ -24,6 +24,11 @@ This changelog covers all five packages, as they are (for now) updated as a whol
 - Added `store.preloadResourceTree()` method, see docs for more info.
 - Fix generated ontologies not working in a Next.js server context.
 - SEMI BREAKING CHANGE: When using generated types by cli, @tomic/lib now requires them to be generated by @tomic/cli v0.41.0 or above.
+- Fix types masquerading as esm module in cjs build.
+
+### @tomic/react
+
+- Add cjs build.
 
 ### @tomic/cli
 
diff --git a/browser/cli/package.json b/browser/cli/package.json
index 5d06ab362..d22ed034f 100644
--- a/browser/cli/package.json
+++ b/browser/cli/package.json
@@ -1,6 +1,14 @@
 {
   "version": "0.40.0",
   "author": "Polle Pas",
+  "homepage": "https://docs.atomicdata.dev/js-cli",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/atomicdata-dev/atomic-server.git"
+  },
+  "bugs": {
+    "url": "https://github.com/atomicdata-dev/atomic-server/issues"
+  },
   "dependencies": {
     "@tomic/lib": "workspace:*",
     "chalk": "^5.3.0",
@@ -9,7 +17,7 @@
   "devDependencies": {
     "typescript": "^5.6.3"
   },
-  "description": "",
+  "description": "Generate types from Atomic Data ontologies",
   "license": "MIT",
   "name": "@tomic/cli",
   "publishConfig": {
@@ -19,7 +27,8 @@
     "build": "tsc",
     "lint": "eslint ./src --ext .js,.ts",
     "lint-fix": "eslint ./src --ext .js,.ts --fix",
-    "prepublishOnly": "pnpm run build && pnpm run lint-fix",
+    "prepublishOnly": "pnpm run build && pnpm run lint && pnpm run lint-package",
+    "lint-package": "pnpm dlx publint",
     "watch": "tsc --build --watch",
     "start": "pnpm watch",
     "tsc": "pnpm exec tsc --build",
diff --git a/browser/create-template/package.json b/browser/create-template/package.json
index ffb1ff4fc..340a68dec 100644
--- a/browser/create-template/package.json
+++ b/browser/create-template/package.json
@@ -1,6 +1,14 @@
 {
   "version": "0.40.0",
   "author": "Polle Pas",
+  "homepage": "https://docs.atomicdata.dev/create-template/atomic-template",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/atomicdata-dev/atomic-server.git"
+  },
+  "bugs": {
+    "url": "https://github.com/atomicdata-dev/atomic-server/issues"
+  },
   "dependencies": {
     "@tomic/lib": "workspace:*",
     "chalk": "^5.3.0",
@@ -20,7 +28,8 @@
     "build": "tsc",
     "lint": "eslint ./src --ext .js,.ts",
     "lint-fix": "eslint ./src --ext .js,.ts --fix",
-    "prepublishOnly": "pnpm run build && pnpm run lint-fix",
+    "prepublishOnly": "pnpm run build && pnpm run lint && pnpm run lint-package",
+    "lint-package": "pnpm dlx publint",
     "watch": "tsc --build --watch",
     "start": "pnpm exec tsc --build --watch",
     "tsc": "pnpm exec tsc --build",
diff --git a/browser/data-browser/src/App.tsx b/browser/data-browser/src/App.tsx
index a9b21ccae..32755ec6c 100644
--- a/browser/data-browser/src/App.tsx
+++ b/browser/data-browser/src/App.tsx
@@ -1,7 +1,7 @@
 import { BrowserRouter } from 'react-router-dom';
 import { HelmetProvider } from 'react-helmet-async';
 import { StoreContext, Store } from '@tomic/react';
-import { StyleSheetManager } from 'styled-components';
+import { StyleSheetManager, type ShouldForwardProp } from 'styled-components';
 
 import { GlobalStyle, ThemeWrapper } from './styling';
 import { AppRoutes } from './routes/Routes';
@@ -75,7 +75,7 @@ if (isDev()) {
 }
 
 // This implements the default behavior from styled-components v5
-function shouldForwardProp(propName, target) {
+const shouldForwardProp: ShouldForwardProp<'web'> = (propName, target) => {
   if (typeof target === 'string') {
     // For HTML elements, forward the prop if it is a valid HTML attribute
     return isPropValid(propName);
@@ -83,7 +83,7 @@ function shouldForwardProp(propName, target) {
 
   // For other elements, forward all props
   return true;
-}
+};
 
 /** Entrypoint of the application. This is where providers go. */
 function App(): JSX.Element {
@@ -97,11 +97,10 @@ function App(): JSX.Element {
               <HotKeysWrapper>
                 <StyleSheetManager shouldForwardProp={shouldForwardProp}>
                   <ThemeWrapper>
-                    {/* @ts-ignore TODO: Check if types are fixed or upgrade styled-components to 6.0.0 */}
                     <GlobalStyle />
                     {/* @ts-ignore fallback component type too strict */}
                     <ErrBoundary FallbackComponent={CrashPage}>
-                      {/* Default form validation provider. Does not do anyting on its own but will make sure useValidation works without context*/}
+                      {/* Default form validation provider. Does not do anything on its own but will make sure useValidation works without context*/}
                       <FormValidationContextProvider
                         onValidationChange={() => undefined}
                       >
diff --git a/browser/data-browser/src/chunks/CurrencyPicker/processCurrencyFile.ts b/browser/data-browser/src/chunks/CurrencyPicker/processCurrencyFile.ts
index 39ac38fca..ab1553559 100644
--- a/browser/data-browser/src/chunks/CurrencyPicker/processCurrencyFile.ts
+++ b/browser/data-browser/src/chunks/CurrencyPicker/processCurrencyFile.ts
@@ -10,7 +10,7 @@ export const processCurrencyFile = (xmlStr: string): string => {
   const parser = new DOMParser();
   const xmlDoc = parser.parseFromString(xmlStr, 'text/xml');
   const currencyNodes = xmlDoc.getElementsByTagName('CcyNtry');
-  const currencyMap = {};
+  const currencyMap: Record<string, string> = {};
 
   for (let i = 0; i < currencyNodes.length; i++) {
     const currencyNode = currencyNodes[i];
@@ -22,7 +22,10 @@ export const processCurrencyFile = (xmlStr: string): string => {
 
     const currencyName =
       currencyNode.getElementsByTagName('CcyNm')[0]?.textContent;
-    currencyMap[code] = currencyName;
+
+    if (currencyName) {
+      currencyMap[code] = currencyName;
+    }
   }
 
   return JSON.stringify(currencyMap);
diff --git a/browser/data-browser/src/chunks/MarkdownEditor/SlashMenu/CommandsExtension.ts b/browser/data-browser/src/chunks/MarkdownEditor/SlashMenu/CommandsExtension.ts
index 038a018af..f400647be 100644
--- a/browser/data-browser/src/chunks/MarkdownEditor/SlashMenu/CommandsExtension.ts
+++ b/browser/data-browser/src/chunks/MarkdownEditor/SlashMenu/CommandsExtension.ts
@@ -22,6 +22,7 @@ export const SlashCommands = Extension.create({
     return {
       suggestion: {
         char: '/',
+        // @ts-expect-error Tiptap typing is not very good or clear so they're just any.
         command: ({ editor, range, props }) => {
           props.command({ editor, range });
         },
@@ -46,7 +47,7 @@ export const suggestion: Partial<SuggestionOptions> = {
         icon: FaListUl,
         command: ({ editor, range }) =>
           editor.chain().focus().deleteRange(range).toggleBulletList().run(),
-      },
+      } as CommandItem,
       {
         title: 'Codeblock',
         icon: FaCode,
diff --git a/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx b/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
index dde602dd8..408f319ec 100644
--- a/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
+++ b/browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx
@@ -1,6 +1,9 @@
 import { useId } from 'react';
 import { IconButton } from '../IconButton/IconButton';
-import { DropdownTriggerRenderFunction } from './DropdownTrigger';
+import {
+  DropdownTriggerRenderFunction,
+  type DropdownTriggerProps,
+} from './DropdownTrigger';
 
 /** Builds a default trigger for a dropdown menu using an IconButton.
  * Make sure the component stays mounted when the menu is open in order to have proper focus management.
@@ -11,7 +14,7 @@ export const buildDefaultTrigger = (
   ButtonComp: typeof IconButton = IconButton,
 ): DropdownTriggerRenderFunction => {
   const Comp = (
-    { onClick, menuId, isActive },
+    { onClick, menuId, isActive }: DropdownTriggerProps,
     ref: React.Ref<HTMLButtonElement>,
   ) => {
     const id = useId();
diff --git a/browser/data-browser/src/components/SearchFilter.tsx b/browser/data-browser/src/components/SearchFilter.tsx
deleted file mode 100644
index 6cc278ec1..000000000
--- a/browser/data-browser/src/components/SearchFilter.tsx
+++ /dev/null
@@ -1,64 +0,0 @@
-import { useEffect, useState } from 'react';
-import { urls, useArray, useProperty, useResource } from '@tomic/react';
-import { ResourceSelector } from '../components/forms/ResourceSelector';
-
-/**
- * Shows a Class selector to the user.
- * If a Class is selected, the filters for the required and recommended properties
- * of that Class are shown.
- */
-export function ClassFilter({ filters, setFilters }): JSX.Element {
-  const [klass, setClass] = useState<string | undefined>(undefined);
-  const resource = useResource(klass);
-  const [requiredProps] = useArray(resource, urls.properties.requires);
-  const [recommendedProps] = useArray(resource, urls.properties.recommends);
-  const allProps = [...requiredProps, ...recommendedProps];
-
-  useEffect(() => {
-    // Set the filters to the default values of the properties
-    setFilters({
-      ...filters,
-      [urls.properties.isA]: klass,
-    });
-  }, [klass, JSON.stringify(filters)]);
-
-  return (
-    <div>
-      <ResourceSelector
-        setSubject={setClass}
-        value={klass}
-        isA={urls.classes.class}
-      />
-      {allProps?.map(propertySubject => (
-        <PropertyFilter
-          key={propertySubject}
-          subject={propertySubject}
-          filters={filters}
-          setFilters={setFilters}
-        />
-      ))}
-    </div>
-  );
-}
-
-function PropertyFilter({ filters, setFilters, subject }): JSX.Element {
-  const prop = useProperty(subject);
-
-  function handleChange(e) {
-    setFilters({
-      ...filters,
-      [prop.shortname]: e.target.value,
-    });
-  }
-
-  return (
-    <div>
-      <label>{prop.shortname}</label>
-      <input
-        type='text'
-        value={filters[prop.shortname]}
-        onChange={handleChange}
-      />
-    </div>
-  );
-}
diff --git a/browser/data-browser/src/components/Searchbar.tsx b/browser/data-browser/src/components/Searchbar.tsx
index 61da85233..f303d8e18 100644
--- a/browser/data-browser/src/components/Searchbar.tsx
+++ b/browser/data-browser/src/components/Searchbar.tsx
@@ -42,7 +42,7 @@ export function Searchbar({
     }
   };
 
-  function handleChange(e) {
+  const handleChange: React.ChangeEventHandler<HTMLInputElement> = e => {
     setInput(e.target.value);
 
     try {
@@ -52,9 +52,9 @@ export function Searchbar({
     } catch (_err) {
       navigate(searchURL(e.target.value, scope), { replace: true });
     }
-  }
+  };
 
-  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
+  const handleSubmit: React.FormEventHandler<HTMLFormElement> = event => {
     if (!subject) {
       return;
     }
diff --git a/browser/data-browser/src/components/TableEditor/TableEditor.tsx b/browser/data-browser/src/components/TableEditor/TableEditor.tsx
index 04b279107..ca71b14bd 100644
--- a/browser/data-browser/src/components/TableEditor/TableEditor.tsx
+++ b/browser/data-browser/src/components/TableEditor/TableEditor.tsx
@@ -8,7 +8,7 @@ import {
 } from 'react';
 import { styled } from 'styled-components';
 import { FixedSizeList, ListOnScrollProps } from 'react-window';
-import Autosizer from 'react-virtualized-auto-sizer';
+import Autosizer, { type VerticalSize } from 'react-virtualized-auto-sizer';
 import { Cell, IndexCell } from './Cell';
 import { TableRow } from './TableRow';
 import { TableHeader, TableHeadingComponent } from './TableHeader';
@@ -157,7 +157,7 @@ function FancyTableInner<T>({
   );
 
   const List = useCallback(
-    ({ height }) => (
+    ({ height }: VerticalSize) => (
       <StyledFixedSizeList
         height={height}
         width='100%'
@@ -186,7 +186,6 @@ function FancyTableInner<T>({
       <VisuallyHidden id={ariaUsageId}>
         <p>{ARIA_TABLE_USAGE}</p>
       </VisuallyHidden>
-      {/* @ts-ignore */}
       <Table
         aria-labelledby={labelledBy}
         aria-rowcount={itemCount}
@@ -234,13 +233,12 @@ interface TableProps {
   totalContentHeight: number;
 }
 
-// @ts-ignore
 const Table = styled.div.attrs<TableProps>(p => ({
   style: {
     '--table-template-columns': p.gridTemplateColumns,
     '--table-content-width': p.contentRowWidth,
-  },
-}))<TableProps>`
+  } as Record<string, string>,
+}))`
   --table-height: 80vh;
   --table-row-height: ${p => p.rowHeight}px;
   --table-inner-padding: 0.5rem;
@@ -257,7 +255,6 @@ const Table = styled.div.attrs<TableProps>(p => ({
 
   &:focus-visible {
     outline: none;
-    /* border-color: ${p => p.theme.colors.main}; */
     box-shadow: 0 0 0 2px ${p => p.theme.colors.main};
   }
 `;
diff --git a/browser/data-browser/src/components/Template/ApplyTemplateDialog.tsx b/browser/data-browser/src/components/Template/ApplyTemplateDialog.tsx
index 92a16a7f3..28ffca7cc 100644
--- a/browser/data-browser/src/components/Template/ApplyTemplateDialog.tsx
+++ b/browser/data-browser/src/components/Template/ApplyTemplateDialog.tsx
@@ -26,7 +26,7 @@ interface ApplyTemplateDialogProps {
   bindOpen: (open: boolean) => void;
 }
 
-const stableArray = [];
+const stableArray: string[] = [];
 
 export function ApplyTemplateDialog({
   template,
diff --git a/browser/data-browser/src/components/Toaster.tsx b/browser/data-browser/src/components/Toaster.tsx
index f283d0144..1c147cbbf 100644
--- a/browser/data-browser/src/components/Toaster.tsx
+++ b/browser/data-browser/src/components/Toaster.tsx
@@ -1,4 +1,9 @@
-import toast, { ToastBar, Toaster as ReactHotToast } from 'react-hot-toast';
+import toast, {
+  type Toast,
+  ToastBar,
+  Toaster as ReactHotToast,
+  type Renderable,
+} from 'react-hot-toast';
 import { FaCopy, FaTimes } from 'react-icons/fa';
 import { useTheme } from 'styled-components';
 import { zIndex } from '../styling';
@@ -45,12 +50,27 @@ export function Toaster(): JSX.Element {
   );
 }
 
-function ToastMessage({ icon, message, t }) {
-  let text = message.props.children;
+interface ToastMessageProps {
+  icon: React.ReactNode;
+  message: Renderable;
+  t: Toast;
+}
+
+function ToastMessage({ icon, message, t }: ToastMessageProps) {
+  let text: string;
+
+  if (typeof message === 'string') {
+    text = message;
+  } else if (message && 'props' in message) {
+    // children can technically still be a react node but we never do that in our code so we'll just assume it to be a string.
+    text = message.props.children;
+  } else {
+    text = '';
+  }
 
   function handleCopy() {
     toast.success('Copied error to clipboard');
-    navigator.clipboard.writeText(message.props.children);
+    navigator.clipboard.writeText(text);
     toast.dismiss(t.id);
   }
 
diff --git a/browser/data-browser/src/routes/History/versionHelpers.ts b/browser/data-browser/src/routes/History/versionHelpers.ts
index aee9cc92d..511bb1b2e 100644
--- a/browser/data-browser/src/routes/History/versionHelpers.ts
+++ b/browser/data-browser/src/routes/History/versionHelpers.ts
@@ -38,16 +38,19 @@ export function dedupeVersions(versions: Version[]): Version[] {
 export function groupVersionsByMonth(
   versions: Version[],
 ): Record<string, Version[]> {
-  return versions.reduceRight((acc, version) => {
-    const createdDate = new Date(version.commit.createdAt);
-    const groupKey = groupFormatter.format(createdDate);
-    const group = acc[groupKey] ?? [];
-
-    return {
-      ...acc,
-      [groupKey]: [...group, version],
-    };
-  }, {});
+  return versions.reduceRight(
+    (acc, version) => {
+      const createdDate = new Date(version.commit.createdAt);
+      const groupKey = groupFormatter.format(createdDate);
+      const group = acc[groupKey] ?? [];
+
+      return {
+        ...acc,
+        [groupKey]: [...group, version],
+      };
+    },
+    {} as Record<string, Version[]>,
+  );
 }
 
 function compareMaps(map1: Map<string, unknown>, map2: Map<string, unknown>) {
diff --git a/browser/data-browser/src/routes/SearchRoute.tsx b/browser/data-browser/src/routes/SearchRoute.tsx
index b39175f96..f0ddc4ef0 100644
--- a/browser/data-browser/src/routes/SearchRoute.tsx
+++ b/browser/data-browser/src/routes/SearchRoute.tsx
@@ -7,11 +7,9 @@ import ResourceCard from '../views/Card/ResourceCard';
 import { useServerSearch } from '@tomic/react';
 import { ErrorLook } from '../components/ErrorLook';
 import { styled } from 'styled-components';
-import { FaFilter, FaSearch } from 'react-icons/fa';
+import { FaSearch } from 'react-icons/fa';
 import { useQueryScopeHandler } from '../hooks/useQueryScope';
 import { useSettings } from '../helpers/AppSettings';
-import { ClassFilter } from '../components/SearchFilter';
-import { Button } from '../components/Button';
 import { Column } from '../components/Row';
 import { Main } from '../components/Main';
 
@@ -20,7 +18,6 @@ export function Search(): JSX.Element {
   const [query] = useSearchQuery();
   const { drive } = useSettings();
   const { scope } = useQueryScopeHandler();
-  const [filters, setFilters] = useState({});
   const [enableFilter, setEnableFilter] = useState(false);
 
   useHotkeys(
@@ -32,13 +29,10 @@ export function Search(): JSX.Element {
     [enableFilter],
   );
 
-  const [showFilter, setShowFilter] = useState(false);
-
   const [selectedIndex, setSelected] = useState(0);
   const { results, loading, error } = useServerSearch(query, {
     debounce: 0,
     parents: scope || drive,
-    filters,
     include: true,
   });
   const navigate = useNavigate();
@@ -109,36 +103,19 @@ export function Search(): JSX.Element {
           <ErrorLook>{error.message}</ErrorLook>
         ) : (
           <>
-            <div
-              style={{
-                display: 'flex',
-                justifyContent: 'space-between',
-              }}
-            >
-              <Heading>
-                <FaSearch />
-                <span>
-                  {message ? (
-                    message
-                  ) : (
-                    <>
-                      {results.length}{' '}
-                      {results.length > 1 ? 'Results' : 'Result'} for{' '}
-                      <QueryText>{query}</QueryText>
-                    </>
-                  )}
-                </span>
-              </Heading>
-              {enableFilter && (
-                <Button onClick={() => setShowFilter(!showFilter)}>
-                  <FaFilter />
-                  Filter
-                </Button>
-              )}
-            </div>
-            {showFilter && (
-              <ClassFilter setFilters={setFilters} filters={filters} />
-            )}
+            <Heading>
+              <FaSearch />
+              <span>
+                {message ? (
+                  message
+                ) : (
+                  <>
+                    {results.length} {results.length > 1 ? 'Results' : 'Result'}{' '}
+                    for <QueryText>{query}</QueryText>
+                  </>
+                )}
+              </span>
+            </Heading>
             <Column ref={resultsDiv} gap='1rem'>
               {results.map((subject, index) => (
                 <ResourceCard
@@ -164,8 +141,9 @@ const Heading = styled.h1`
   white-space: nowrap;
   overflow: hidden;
   line-height: 1.5;
-  margin-bottom: ${p => p.theme.margin * 3}rem;
-  > span {
+  margin-bottom: ${p => p.theme.size(8)};
+
+  & > span {
     overflow: hidden;
     text-overflow: ellipsis;
   }
diff --git a/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx b/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
index c4b6998e1..ca4d0a412 100644
--- a/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
+++ b/browser/data-browser/src/views/BookmarkPage/BookmarkPreview.tsx
@@ -33,7 +33,7 @@ export function BookmarkPreview({
   );
 }
 
-const ErrorPage = ({ error }) => {
+const ErrorPage = ({ error }: { error: Error }) => {
   return (
     <CenterGrid>
       <div>
diff --git a/browser/data-browser/src/views/BookmarkPage/usePreview.ts b/browser/data-browser/src/views/BookmarkPage/usePreview.ts
index 394d3f726..d6b335f4a 100644
--- a/browser/data-browser/src/views/BookmarkPage/usePreview.ts
+++ b/browser/data-browser/src/views/BookmarkPage/usePreview.ts
@@ -1,5 +1,11 @@
-import { AtomicError, ErrorType } from './../../../../lib/src/error';
-import { Resource, urls, useStore, useString } from '@tomic/react';
+import {
+  AtomicError,
+  ErrorType,
+  Resource,
+  urls,
+  useStore,
+  useString,
+} from '@tomic/react';
 import { startTransition, useCallback, useEffect, useState } from 'react';
 import { debounce } from '../../helpers/debounce';
 import { paths } from '../../routes/paths';
diff --git a/browser/data-browser/src/views/ChatRoomPage.tsx b/browser/data-browser/src/views/ChatRoomPage.tsx
index ebd8eb281..49f2c5d69 100644
--- a/browser/data-browser/src/views/ChatRoomPage.tsx
+++ b/browser/data-browser/src/views/ChatRoomPage.tsx
@@ -66,7 +66,7 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
   const disableSend = newMessageVal.length === 0;
 
   /** Creates a message using the internal state */
-  async function sendMessage(e?) {
+  async function sendMessage(e?: React.SyntheticEvent) {
     const messageBackup = newMessageVal;
 
     try {
@@ -106,7 +106,9 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
     inputRef?.current?.focus();
   }
 
-  function handleChangeMessageText(e) {
+  const handleChangeMessageText: React.ChangeEventHandler<
+    HTMLTextAreaElement
+  > = e => {
     setNewMessage(e.target.value);
 
     if (e.target.value === '') {
@@ -128,7 +130,7 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
     if (trows !== textAreaHight) {
       setTextAreaHight(trows);
     }
-  }
+  };
 
   return (
     <FullPageWrapper>
@@ -161,7 +163,7 @@ export function ChatRoomPage({ resource }: ResourcePageProps) {
           title='Send message [enter]'
           disabled={disableSend}
           clean
-          onClick={sendMessage}
+          onClick={() => sendMessage()}
         >
           Send
         </SendButton>
diff --git a/browser/data-browser/src/views/EndpointPage.tsx b/browser/data-browser/src/views/EndpointPage.tsx
index baadac6d8..d5be90db6 100644
--- a/browser/data-browser/src/views/EndpointPage.tsx
+++ b/browser/data-browser/src/views/EndpointPage.tsx
@@ -31,9 +31,9 @@ function EndpointPage({ resource }: EndpointProps): JSX.Element {
   const navigate = useNavigate();
 
   /** Create the URL using the variables */
-  async function constructSubject(e?) {
+  async function constructSubject(e?: React.SyntheticEvent) {
     e && e.preventDefault();
-    const url = new URL(resource.getSubject());
+    const url = new URL(resource.subject);
 
     await Promise.all(
       parameters.map(async propUrl => {
diff --git a/browser/data-browser/src/views/ErrorPage.tsx b/browser/data-browser/src/views/ErrorPage.tsx
index 4be11ec79..8f21f4d8d 100644
--- a/browser/data-browser/src/views/ErrorPage.tsx
+++ b/browser/data-browser/src/views/ErrorPage.tsx
@@ -17,7 +17,6 @@ import { clearAllLocalData } from '../helpers/clearData';
 function ErrorPage({ resource }: ResourcePageProps): JSX.Element {
   const { agent } = useSettings();
   const store = useStore();
-  const subject = resource.getSubject();
 
   if (isUnauthorized(resource.error)) {
     return (
@@ -28,7 +27,11 @@ function ErrorPage({ resource }: ResourcePageProps): JSX.Element {
             <>
               <ErrorBlock error={resource.error!} />
               <span>
-                <Button onClick={() => store.fetchResourceFromServer(subject)}>
+                <Button
+                  onClick={() =>
+                    store.fetchResourceFromServer(resource.subject)
+                  }
+                >
                   Retry
                 </Button>
               </span>
@@ -47,12 +50,14 @@ function ErrorPage({ resource }: ResourcePageProps): JSX.Element {
   return (
     <ContainerWide>
       <Column>
-        <h1>Could not open {resource.getSubject()}</h1>
+        <h1>Could not open {resource.subject}</h1>
         <ErrorBlock error={resource.error!} />
         <Row>
           <Button
             onClick={() =>
-              store.fetchResourceFromServer(subject, { setLoading: true })
+              store.fetchResourceFromServer(resource.subject, {
+                setLoading: true,
+              })
             }
           >
             Retry
@@ -65,7 +70,7 @@ function ErrorPage({ resource }: ResourcePageProps): JSX.Element {
           </Button>
           <Button
             onClick={() =>
-              store.fetchResourceFromServer(subject, {
+              store.fetchResourceFromServer(resource.subject, {
                 fromProxy: true,
                 setLoading: true,
               })
@@ -100,7 +105,7 @@ export class ErrorBoundary extends React.Component<
     this.state = { error: undefined };
   }
 
-  public static getDerivedStateFromError(error) {
+  public static getDerivedStateFromError(error: Error) {
     // Update state so the next render will show the fallback UI.
     return { error };
   }
diff --git a/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx b/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
index 7c4ea60b8..420fa0821 100644
--- a/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
+++ b/browser/data-browser/src/views/OntologyPage/InlineDatatype.tsx
@@ -1,25 +1,26 @@
 import {
   Resource,
   useString,
-  urls,
+  core,
   reverseDatatypeMapping,
-  unknownSubject,
   useResource,
+  type Core,
+  datatypeFromUrl,
 } from '@tomic/react';
 import { ResourceInline } from '../ResourceInline';
 import { toAnchorId } from '../../helpers/toAnchorId';
 import { useOntologyContext } from './OntologyContext';
 
 interface TypeSuffixProps {
-  resource: Resource;
+  resource: Resource<Core.Property>;
 }
 
 export function InlineDatatype({ resource }: TypeSuffixProps): JSX.Element {
-  const [datatype] = useString(resource, urls.properties.datatype);
-  const [classType] = useString(resource, urls.properties.classType);
+  const datatype = resource.props.datatype;
+  const [classType] = useString(resource, core.properties.classtype);
   const { hasClass } = useOntologyContext();
 
-  const name = reverseDatatypeMapping[datatype ?? unknownSubject];
+  const name = reverseDatatypeMapping[datatypeFromUrl(datatype)];
 
   if (!classType) {
     return <span>{name}</span>;
diff --git a/browser/data-browser/tsconfig.json b/browser/data-browser/tsconfig.json
index 5f3bcb8ca..fe3f523b7 100644
--- a/browser/data-browser/tsconfig.json
+++ b/browser/data-browser/tsconfig.json
@@ -15,13 +15,5 @@
   },
   "include": [
     "./src",
-  ],
-  "references": [
-    {
-      "path": "../lib"
-    },
-    {
-      "path": "../react"
-    }
   ]
 }
diff --git a/browser/lib/README.md b/browser/lib/README.md
index 862e2d0f8..440f57387 100644
--- a/browser/lib/README.md
+++ b/browser/lib/README.md
@@ -1,3 +1,3 @@
 # @tomic/lib: The Atomic Data library for typescript/javascript
 
-[**docs**](https://atomic-lib.netlify.app/modules/_tomic_lib)
+[**docs**](https://docs.atomicdata.dev/js)
diff --git a/browser/lib/package.json b/browser/lib/package.json
index 27fbc5696..c497fa62e 100644
--- a/browser/lib/package.json
+++ b/browser/lib/package.json
@@ -1,6 +1,15 @@
 {
+  "name": "@tomic/lib",
   "version": "0.40.0",
   "author": "Joep Meindertsma",
+  "homepage": "https://docs.atomicdata.dev/js",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/atomicdata-dev/atomic-server.git"
+  },
+  "bugs": {
+    "url": "https://github.com/atomicdata-dev/atomic-server/issues"
+  },
   "dependencies": {
     "@noble/ed25519": "1.6.0",
     "@noble/hashes": "^0.5.9",
@@ -8,43 +17,52 @@
     "fast-json-stable-stringify": "^2.1.0",
     "ulidx": "^2.4.1"
   },
-  "description": "",
+  "description": "The Atomic Data library for typescript/javascript",
   "devDependencies": {
+    "@arethetypeswrong/cli": "^0.17.0",
+    "@microsoft/api-extractor": "^7.48.0",
     "@tomic/cli": "workspace:*",
     "@types/fast-json-stable-stringify": "^2.1.2",
     "tslib": "^2.8.0",
+    "tsup": "^8.3.5",
     "typescript": "^5.6.3",
-    "vite": "^5.4.10",
-    "vite-plugin-dts": "^3.9.1",
     "vitest": "^2.1.3"
   },
   "files": [
-    "dist"
+    "dist",
+    "!dist/**/*.d.ts.map"
   ],
-  "gitHead": "2172c73d8df4e5f273e6386676abc91b6c5b2707",
   "license": "MIT",
   "exports": {
-    "import": "./dist/index.js",
-    "require": "./dist/index.cjs",
-    "types": "./dist/src/index.d.ts"
+    ".": {
+      "import": {
+        "types": "./dist/src/index.d.ts",
+        "default": "./dist/index.js"
+      },
+      "require": {
+        "types": "./dist/src/index.d.cts",
+        "default": "./dist/index.cjs"
+      }
+    }
   },
   "main-dev": "src/index.ts",
-  "name": "@tomic/lib",
   "publishConfig": {
     "access": "public"
   },
   "scripts": {
-    "build": "pnpm exec vite build",
+    "build": "tsup",
     "generate-ontologies": "ad-generate ontologies",
+    "lint-package": "pnpm publint && pnpm attw",
     "lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
     "lint-fix": "eslint ./src --ext .js,.jsx,.ts,.tsx --fix",
-    "prepublishOnly": "pnpm run build && pnpm run lint-fix",
+    "prepublishOnly": "pnpm run build && pnpm run lint && pnpm run lint-package",
     "start": "pnpm watch",
     "coverage": "vitest run --coverage",
     "test": "vitest run",
-    "tsc": "tsc --build",
     "typecheck": "pnpm exec tsc --noEmit",
-    "watch": "pnpm exec vite build --watch"
+    "watch": "pnpm exec tsup --watch",
+    "publint": "pnpm dlx publint",
+    "attw": "pnpm exec attw $(pnpm pack)"
   },
   "source": "src/index.ts",
   "type": "module",
diff --git a/browser/lib/src/authentication.ts b/browser/lib/src/authentication.ts
index fcda6adca..8d48a688d 100644
--- a/browser/lib/src/authentication.ts
+++ b/browser/lib/src/authentication.ts
@@ -53,22 +53,23 @@ export async function signRequest(
   /** The resource meant to be fetched */
   subject: string,
   agent: Agent,
-  headers: HeadersObject | Headers,
+  headers: HeadersObject,
 ): Promise<HeadersObject> {
   const timestamp = getTimestampNow();
+  const newHeaders = { ...headers };
 
   if (agent?.subject && !localTryingExternal(subject, agent)) {
-    headers['x-atomic-public-key'] = await agent.getPublicKey();
-    headers['x-atomic-signature'] = await signatureMessage(
+    newHeaders['x-atomic-public-key'] = await agent.getPublicKey();
+    newHeaders['x-atomic-signature'] = await signatureMessage(
       subject,
       agent,
       timestamp,
     );
-    headers['x-atomic-timestamp'] = timestamp;
-    headers['x-atomic-agent'] = agent?.subject;
+    newHeaders['x-atomic-timestamp'] = timestamp.toString();
+    newHeaders['x-atomic-agent'] = agent?.subject;
   }
 
-  return headers as HeadersObject;
+  return newHeaders;
 }
 
 const ONE_DAY = 24 * 60 * 60 * 1000;
diff --git a/browser/lib/src/client.ts b/browser/lib/src/client.ts
index e08a60a44..60301c3f3 100644
--- a/browser/lib/src/client.ts
+++ b/browser/lib/src/client.ts
@@ -123,8 +123,9 @@ export class Client {
 
     try {
       Client.tryValidSubject(subject);
-      const requestHeaders: HeadersObject = {};
-      requestHeaders['Accept'] = JSON_AD_MIME;
+      let requestHeaders: HeadersObject = {
+        Accept: JSON_AD_MIME,
+      };
 
       if (signInfo) {
         // Cookies only work in browsers for same-origin requests right now
@@ -134,7 +135,11 @@ export class Client {
             setCookieAuthentication(signInfo.serverURL, signInfo.agent);
           }
         } else {
-          await signRequest(subject, signInfo.agent, requestHeaders);
+          requestHeaders = await signRequest(
+            subject,
+            signInfo.agent,
+            requestHeaders,
+          );
         }
       }
 
diff --git a/browser/lib/src/commit.ts b/browser/lib/src/commit.ts
index ae1a5c385..b2b1ac5f4 100644
--- a/browser/lib/src/commit.ts
+++ b/browser/lib/src/commit.ts
@@ -11,6 +11,8 @@ import { Resource } from './resource.js';
 import type { Store } from './store.js';
 import { urls, properties } from './urls.js';
 import type { JSONValue, JSONArray } from './value.js';
+import { commits } from './ontologies/commits.js';
+import { core } from './ontologies/core.js';
 
 utils.sha512 = msg => Promise.resolve(sha512(msg));
 
@@ -44,6 +46,8 @@ interface CommitBuilderBase {
   previousCommit?: string;
 }
 
+type JSONADObject = Record<string, JSONValue>;
+
 /** Return the current time as Atomic Data timestamp. Milliseconds since unix epoch. */
 export function getTimestampNow(): number {
   return Math.round(new Date().getTime());
@@ -222,7 +226,7 @@ export class CommitBuilder {
       throw new Error(`No changes to commit in ${this.subject}`);
     }
 
-    const commitPreSigned: CommitPreSigned = {
+    const commitPreSigned: UnsignedCommit = {
       ...this.clone().toPlainObject(),
       createdAt,
       signer: agent,
@@ -239,7 +243,7 @@ export class CommitBuilder {
 }
 
 /** A {@link Commit} without its signature, but with a signer and timestamp */
-interface CommitPreSigned extends CommitBuilderI {
+interface UnsignedCommit extends CommitBuilderI {
   /** https://atomicdata.dev/properties/signer */
   signer: string;
   /** Unix timestamp in milliseconds, see https://atomicdata.dev/properties/createdAt */
@@ -251,7 +255,7 @@ interface CommitPreSigned extends CommitBuilderI {
  * https://atomicdata.dev/classes/Commit If you want to create a Commit, you
  * should probably use the {@link CommitBuilder} and call `.sign()` on it.
  */
-export interface Commit extends CommitPreSigned {
+export interface Commit extends UnsignedCommit {
   /** https://atomicdata.dev/properties/signature */
   signature: string;
   /**
@@ -261,21 +265,34 @@ export interface Commit extends CommitPreSigned {
   id?: string;
 }
 
-/** Replaces a key in a Commit. Ignores it if it's not there */
-function replaceKey(
-  o: Commit | CommitPreSigned,
-  oldKey: string,
-  newKey: string,
-) {
-  if (oldKey in o && oldKey !== newKey) {
-    Object.defineProperty(
-      o,
-      newKey,
-      Object.getOwnPropertyDescriptor(o, oldKey)!,
-    );
-    delete o[oldKey];
-  }
-}
+const serializeMap = {
+  subject: commits.properties.subject,
+  set: commits.properties.set,
+  push: commits.properties.push,
+  remove: commits.properties.remove,
+  destroy: commits.properties.destroy,
+  previousCommit: commits.properties.previousCommit,
+  createdAt: commits.properties.createdAt,
+  signer: commits.properties.signer,
+  signature: commits.properties.signature,
+  id: 'id',
+};
+
+/** Replaces the keys of a Commit object with their respective json-ad key */
+const commitToJsonADObject = (commit: UnsignedCommit | Commit): JSONADObject =>
+  Object.entries(commit).reduce<JSONADObject>(
+    (acc, [key, value]) => {
+      const serializedKey =
+        serializeMap[key as keyof Commit | keyof UnsignedCommit];
+
+      acc[serializedKey] = value as JSONValue;
+
+      return acc;
+    },
+    {
+      [core.properties.isA]: [commits.classes.commit],
+    },
+  );
 
 /**
  * Takes a commit and serializes it deterministically (canonicilaization). Is
@@ -283,7 +300,7 @@ function replaceKey(
  * https://docs.atomicdata.dev/core/json-ad.html#canonicalized-json-ad
  */
 export function serializeDeterministically(
-  commit: CommitPreSigned | Commit,
+  commit: UnsignedCommit | Commit,
 ): string {
   // Remove empty arrays, objects, false values from root
   if (commit.remove && Object.keys(commit.remove).length === 0) {
@@ -302,18 +319,9 @@ export function serializeDeterministically(
     delete commit.destroy;
   }
 
-  replaceKey(commit, 'createdAt', urls.properties.commit.createdAt);
-  replaceKey(commit, 'subject', urls.properties.commit.subject);
-  replaceKey(commit, 'set', urls.properties.commit.set);
-  replaceKey(commit, 'push', urls.properties.commit.push);
-  replaceKey(commit, 'signer', urls.properties.commit.signer);
-  replaceKey(commit, 'signature', urls.properties.commit.signature);
-  replaceKey(commit, 'remove', urls.properties.commit.remove);
-  replaceKey(commit, 'destroy', urls.properties.commit.destroy);
-  replaceKey(commit, 'previousCommit', urls.properties.commit.previousCommit);
-  commit[urls.properties.isA] = [urls.classes.commit];
+  const jsonadCommit = commitToJsonADObject(commit);
 
-  return stringify(commit);
+  return stringify(jsonadCommit);
 }
 
 // /** Checks whether the commit signature is correct */
@@ -372,7 +380,7 @@ export async function generateKeyPair(): Promise<KeyPair> {
 
 export function parseCommitResource(resource: Resource): Commit {
   const commit: Commit = {
-    id: resource.getSubject(),
+    id: resource.subject,
     subject: resource.get(urls.properties.commit.subject) as string,
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     set: resource.get(urls.properties.commit.set) as Record<string, any>,
diff --git a/browser/lib/src/datatypes.ts b/browser/lib/src/datatypes.ts
index fbaaa338c..0d64dc9ff 100644
--- a/browser/lib/src/datatypes.ts
+++ b/browser/lib/src/datatypes.ts
@@ -26,11 +26,11 @@ export enum Datatype {
   UNKNOWN = 'unknown-datatype',
 }
 
-const validDatatypes = new Set<string>(Object.values(Datatype));
+const validDatatypes = Object.values(Datatype) as string[];
 
 /** Convert a URL to a Datatype */
 export const datatypeFromUrl = (url: string): Datatype => {
-  if (validDatatypes.has(url)) {
+  if (validDatatypes.includes(url)) {
     return url as Datatype;
   }
 
diff --git a/browser/lib/src/index.ts b/browser/lib/src/index.ts
index bf3712db0..fff395945 100644
--- a/browser/lib/src/index.ts
+++ b/browser/lib/src/index.ts
@@ -29,10 +29,6 @@
  * @module
  */
 
-import { initOntologies } from './ontologies/index.js';
-
-initOntologies();
-
 export * from './ontologies/core.js';
 export * from './ontologies/collections.js';
 export * from './ontologies/commits.js';
diff --git a/browser/lib/src/ontology.ts b/browser/lib/src/ontology.ts
index 979a39496..f3271337b 100644
--- a/browser/lib/src/ontology.ts
+++ b/browser/lib/src/ontology.ts
@@ -59,6 +59,14 @@ type QuickAccessKnownPropType<Class extends OptionalClass> = {
   >;
 };
 
+declare global {
+  // We need to use var for declaring types on globalThis
+  // eslint-disable-next-line no-var
+  var ATOMIC_SUBJECT_TO_NAME_MAPPING: Map<string, string>;
+  // eslint-disable-next-line no-var
+  var ATOMIC_CLASS_DEFS: Map<string, Record<string, string>>;
+}
+
 /** Type of the dynamically created resource.props field */
 export type QuickAccessPropType<Class extends OptionalClass = UnknownClass> =
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -104,7 +112,7 @@ export function getKnownNameBySubject(subject: string): string | undefined {
 
 export function getKnownClassDefBySubject(
   subject: string,
-): Map<string, Record<string, string>> {
+): Record<string, string> | undefined {
   return globalThis.ATOMIC_CLASS_DEFS.get(subject);
 }
 
diff --git a/browser/lib/src/parse.ts b/browser/lib/src/parse.ts
index 12fcba06f..823e134a6 100644
--- a/browser/lib/src/parse.ts
+++ b/browser/lib/src/parse.ts
@@ -126,16 +126,16 @@ export class JSONADParser {
       return value;
     }
 
-    if (value?.constructor === {}.constructor) {
-      if (Object.keys(value).includes('@id')) {
+    if (isJSONObject(value)) {
+      if ('@id' in value) {
         // It's a named resource that should be parsed too
-        const nestedSubject = value['@id'];
-        this.parseJsonADResource(value as JSONObject);
+        const nestedSubject = value['@id'] as string;
+        this.parseJsonADResource(value);
 
         return nestedSubject;
       } else {
         // It's an anonymous nested Resource
-        return value as JSONObject;
+        return value;
       }
     }
 
@@ -161,3 +161,6 @@ export class JSONADParser {
     return resources;
   }
 }
+
+const isJSONObject = (value: JSONValue): value is JSONObject =>
+  typeof value === 'object' && value !== null && !isArray(value);
diff --git a/browser/lib/src/resource.ts b/browser/lib/src/resource.ts
index 5b1602957..49e82a378 100644
--- a/browser/lib/src/resource.ts
+++ b/browser/lib/src/resource.ts
@@ -23,7 +23,12 @@ import {
 } from './ontology.js';
 import type { Store } from './store.js';
 import { properties, instances, urls } from './urls.js';
-import { valToArray, type JSONValue, type JSONArray } from './value.js';
+import {
+  valToArray,
+  type JSONValue,
+  type JSONArray,
+  type JSONObject,
+} from './value.js';
 
 /** Contains the PropertyURL / Value combinations */
 export type PropVals = Map<string, JSONValue>;
@@ -131,7 +136,7 @@ export class Resource<C extends OptionalClass = any> {
     const getPropSubject = (name: string) => {
       // Check if the property is a default property
       if (name in defaultProps) {
-        return defaultProps[name];
+        return defaultProps[name as keyof typeof defaultProps];
       }
 
       // Check if the property is defined in any of the classes
@@ -157,12 +162,18 @@ export class Resource<C extends OptionalClass = any> {
       get(_target, propName) {
         const propSubject = getPropSubject(propName as string);
 
-        return innerThis.get(propSubject);
+        return innerThis.get(propSubject ?? '');
       },
 
       set(_target, propName, value) {
         const propSubject = getPropSubject(propName as string);
 
+        if (!propSubject) {
+          throw new Error(
+            `Unable to set property: ${propName.toString()} on ${innerThis.subject}. The property's subject could not be found.`,
+          );
+        }
+
         innerThis.set(propSubject, value, false);
 
         return true;
@@ -316,7 +327,7 @@ export class Resource<C extends OptionalClass = any> {
     return this.getArray(propUrl).map(item => {
       if (typeof item === 'string') return item;
 
-      return item!['@id'] as string;
+      return (item as JSONObject)['@id'] as string;
     });
   }
 
@@ -569,7 +580,7 @@ export class Resource<C extends OptionalClass = any> {
     if (unique) {
       values = values
         .filter(value => !propVal.includes(value))
-        .filter(value => !this.commitBuilder.push[propUrl]?.includes(value))
+        .filter(value => !this.commitBuilder.push.get(propUrl)?.has(value))
         .filter((value, index, self) => self.indexOf(value) === index);
     }
 
diff --git a/browser/lib/src/store.ts b/browser/lib/src/store.ts
index 1834ad79f..ee1622665 100644
--- a/browser/lib/src/store.ts
+++ b/browser/lib/src/store.ts
@@ -21,6 +21,7 @@ import { stringToSlug } from './stringToSlug.js';
 import type { JSONValue } from './value.js';
 import { authenticate, fetchWebSocket, startWebsocket } from './websockets.js';
 import { endpoints } from './urls.js';
+import { initOntologies } from './ontologies/index.js';
 
 /** Function called when a resource is updated or removed */
 type ResourceCallback<C extends OptionalClass = UnknownClass> = (
@@ -136,6 +137,7 @@ export class Store {
   private client: Client;
 
   public constructor(opts: StoreOpts = {}) {
+    initOntologies();
     this._resources = new Map();
     this.webSockets = new Map();
     this.subscribers = new Map();
@@ -314,7 +316,7 @@ export class Store {
   }
 
   /**
-   * Always fetches resource from the server then adds it to the store.
+   * Always fetches the resource from the server then adds it to the store.
    */
   public async fetchResourceFromServer<C extends OptionalClass = UnknownClass>(
     /** The resource URL to be fetched */
diff --git a/browser/lib/tsconfig.json b/browser/lib/tsconfig.json
index 9cbdc948f..95d87d7e9 100644
--- a/browser/lib/tsconfig.json
+++ b/browser/lib/tsconfig.json
@@ -1,14 +1,14 @@
 {
-    "extends": "../tsconfig.build.json",
-    "compilerOptions": {
-        "composite": true,
-        "outDir": "./dist",
-        "rootDir": ".",
-        "module": "NodeNext",
-        "moduleResolution": "NodeNext",
-    },
-    "include": [
-        "./src"
-    ],
-    "references": []
+  "extends": "../tsconfig.build.json",
+  "compilerOptions": {
+    "outDir": "./dist",
+    "rootDir": ".",
+    "module": "NodeNext",
+    "moduleResolution": "NodeNext",
+    "declaration": true,
+    "declarationMap": true
+  },
+  "isolatedDeclarations": true,
+  "include": ["./src"],
+  "references": []
 }
diff --git a/browser/lib/tsup.config.ts b/browser/lib/tsup.config.ts
new file mode 100644
index 000000000..53297c271
--- /dev/null
+++ b/browser/lib/tsup.config.ts
@@ -0,0 +1,33 @@
+/// <reference types="node" />
+import { defineConfig } from 'tsup';
+import * as fs from 'node:fs/promises';
+import { exec } from 'node:child_process';
+
+export default defineConfig(options => ({
+  minify: !options.watch,
+  entry: ['src/index.ts'],
+  sourcemap: true,
+  clean: true,
+  format: ['esm', 'cjs'],
+  target: 'es2023',
+  // We need to generate the type definition files ourselves because the build in rollup dts plugin does not work with the way we use module augmentation.
+  // Tsup will switch to microsoft-api-extractor in the future but they don't even support rolling up module augments at all. https://github.com/microsoft/rushstack/issues/1709
+  onSuccess: async () => {
+    console.log('Generating type definition files...');
+
+    // Run the typescript compiler but only emit declaration files.
+    exec('tsc --emitDeclarationOnly --declaration', (err, stdout, stderr) => {
+      if (err || stderr) {
+        console.error(err ?? stderr);
+      }
+
+      // We need a copy of index.d.ts for cjs builds but the actual content can be the same so we can just copy it.
+      console.log('Creating index.d.cts...');
+      fs.copyFile('dist/src/index.d.ts', 'dist/src/index.d.cts')
+        .then(() => {
+          console.log('Build Finished!');
+        })
+        .catch(console.error);
+    });
+  },
+}));
diff --git a/browser/package.json b/browser/package.json
index c5fab2d0f..cd25da5d3 100644
--- a/browser/package.json
+++ b/browser/package.json
@@ -28,6 +28,7 @@
     "dev": "pnpm run start",
     "lint": "pnpm run -r lint",
     "lint-fix": "pnpm run -r lint-fix",
+    "lint-package": "pnpm run -r lint-package",
     "build": "pnpm --filter \"@tomic/lib\" run build && pnpm --filter=!./lib run -r build ",
     "test": "pnpm run -r test",
     "test-e2e": "pnpm run --filter @tomic/e2e test-e2e",
diff --git a/browser/pnpm-lock.yaml b/browser/pnpm-lock.yaml
index 47cb4e8f3..af5767a12 100644
--- a/browser/pnpm-lock.yaml
+++ b/browser/pnpm-lock.yaml
@@ -324,6 +324,12 @@ importers:
         specifier: ^2.4.1
         version: 2.4.1
     devDependencies:
+      '@arethetypeswrong/cli':
+        specifier: ^0.17.0
+        version: 0.17.0
+      '@microsoft/api-extractor':
+        specifier: ^7.48.0
+        version: 7.48.0(@types/node@20.17.0)
       '@tomic/cli':
         specifier: workspace:*
         version: link:../cli
@@ -333,15 +339,12 @@ importers:
       tslib:
         specifier: ^2.8.0
         version: 2.8.0
+      tsup:
+        specifier: ^8.3.5
+        version: 8.3.5(@microsoft/api-extractor@7.48.0(@types/node@20.17.0))(@swc/core@1.7.39)(jiti@2.3.3)(postcss@8.4.47)(typescript@5.6.3)(yaml@2.6.0)
       typescript:
         specifier: ^5.6.3
         version: 5.6.3
-      vite:
-        specifier: ^5.4.10
-        version: 5.4.10(@types/node@20.17.0)(terser@5.36.0)
-      vite-plugin-dts:
-        specifier: ^3.9.1
-        version: 3.9.1(@types/node@20.17.0)(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0))
       vitest:
         specifier: ^2.1.3
         version: 2.1.3(@types/node@20.17.0)(terser@5.36.0)
@@ -352,9 +355,12 @@ importers:
         specifier: workspace:*
         version: link:../lib
       react:
-        specifier: '>17.0.2'
+        specifier: '>18.3.0'
         version: 18.3.1
     devDependencies:
+      '@arethetypeswrong/cli':
+        specifier: ^0.17.0
+        version: 0.17.0
       '@types/react':
         specifier: ^18.3.12
         version: 18.3.12
@@ -364,6 +370,9 @@ importers:
       '@types/react-router-dom':
         specifier: ^5.3.3
         version: 5.3.3
+      tsup:
+        specifier: ^8.3.5
+        version: 8.3.5(@microsoft/api-extractor@7.48.0(@types/node@20.17.0))(@swc/core@1.7.39)(jiti@2.3.3)(postcss@8.4.47)(typescript@5.6.3)(yaml@2.6.0)
       typescript:
         specifier: ^5.6.3
         version: 5.6.3
@@ -435,12 +444,24 @@ packages:
     resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
     engines: {node: '>=6.0.0'}
 
+  '@andrewbranch/untar.js@1.0.3':
+    resolution: {integrity: sha512-Jh15/qVmrLGhkKJBdXlK1+9tY4lZruYjsgkDFj08ZmDiWVBLJcqkok7Z0/R0In+i1rScBpJlSvrTS2Lm41Pbnw==}
+
   '@apideck/better-ajv-errors@0.3.6':
     resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==}
     engines: {node: '>=10'}
     peerDependencies:
       ajv: '>=8'
 
+  '@arethetypeswrong/cli@0.17.0':
+    resolution: {integrity: sha512-xSMW7bfzVWpYw5JFgZqBXqr6PdR0/REmn3DkxCES5N0JTcB0CVgbIynJCvKBFmXaPc3hzmmTrb7+yPDRoOSZdA==}
+    engines: {node: '>=18'}
+    hasBin: true
+
+  '@arethetypeswrong/core@0.17.0':
+    resolution: {integrity: sha512-FHyhFizXNetigTVsIhqXKGYLpazPS5YNojEPpZEUcBPt9wVvoEbNIvG+hybuBR+pjlRcbyuqhukHZm1fr+bDgA==}
+    engines: {node: '>=18'}
+
   '@babel/code-frame@7.25.9':
     resolution: {integrity: sha512-z88xeGxnzehn2sqZ8UdGQEvYErF1odv2CftxInpSYJt6uHuPe9YjahKZITGs3l5LeI9d2ROG+obuDAoSlqbNfQ==}
     engines: {node: '>=6.9.0'}
@@ -962,6 +983,10 @@ packages:
   '@bugsnag/safe-json-stringify@6.0.0':
     resolution: {integrity: sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==}
 
+  '@colors/colors@1.5.0':
+    resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==}
+    engines: {node: '>=0.1.90'}
+
   '@colors/colors@1.6.0':
     resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==}
     engines: {node: '>=0.1.90'}
@@ -1045,6 +1070,12 @@ packages:
     cpu: [ppc64]
     os: [aix]
 
+  '@esbuild/aix-ppc64@0.24.0':
+    resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [aix]
+
   '@esbuild/android-arm64@0.19.11':
     resolution: {integrity: sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q==}
     engines: {node: '>=12'}
@@ -1063,6 +1094,12 @@ packages:
     cpu: [arm64]
     os: [android]
 
+  '@esbuild/android-arm64@0.24.0':
+    resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [android]
+
   '@esbuild/android-arm@0.19.11':
     resolution: {integrity: sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw==}
     engines: {node: '>=12'}
@@ -1081,6 +1118,12 @@ packages:
     cpu: [arm]
     os: [android]
 
+  '@esbuild/android-arm@0.24.0':
+    resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [android]
+
   '@esbuild/android-x64@0.19.11':
     resolution: {integrity: sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg==}
     engines: {node: '>=12'}
@@ -1099,6 +1142,12 @@ packages:
     cpu: [x64]
     os: [android]
 
+  '@esbuild/android-x64@0.24.0':
+    resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [android]
+
   '@esbuild/darwin-arm64@0.19.11':
     resolution: {integrity: sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ==}
     engines: {node: '>=12'}
@@ -1117,6 +1166,12 @@ packages:
     cpu: [arm64]
     os: [darwin]
 
+  '@esbuild/darwin-arm64@0.24.0':
+    resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [darwin]
+
   '@esbuild/darwin-x64@0.19.11':
     resolution: {integrity: sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g==}
     engines: {node: '>=12'}
@@ -1135,6 +1190,12 @@ packages:
     cpu: [x64]
     os: [darwin]
 
+  '@esbuild/darwin-x64@0.24.0':
+    resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [darwin]
+
   '@esbuild/freebsd-arm64@0.19.11':
     resolution: {integrity: sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA==}
     engines: {node: '>=12'}
@@ -1153,6 +1214,12 @@ packages:
     cpu: [arm64]
     os: [freebsd]
 
+  '@esbuild/freebsd-arm64@0.24.0':
+    resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [freebsd]
+
   '@esbuild/freebsd-x64@0.19.11':
     resolution: {integrity: sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw==}
     engines: {node: '>=12'}
@@ -1171,6 +1238,12 @@ packages:
     cpu: [x64]
     os: [freebsd]
 
+  '@esbuild/freebsd-x64@0.24.0':
+    resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [freebsd]
+
   '@esbuild/linux-arm64@0.19.11':
     resolution: {integrity: sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg==}
     engines: {node: '>=12'}
@@ -1189,6 +1262,12 @@ packages:
     cpu: [arm64]
     os: [linux]
 
+  '@esbuild/linux-arm64@0.24.0':
+    resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [linux]
+
   '@esbuild/linux-arm@0.19.11':
     resolution: {integrity: sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q==}
     engines: {node: '>=12'}
@@ -1207,6 +1286,12 @@ packages:
     cpu: [arm]
     os: [linux]
 
+  '@esbuild/linux-arm@0.24.0':
+    resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==}
+    engines: {node: '>=18'}
+    cpu: [arm]
+    os: [linux]
+
   '@esbuild/linux-ia32@0.19.11':
     resolution: {integrity: sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA==}
     engines: {node: '>=12'}
@@ -1225,6 +1310,12 @@ packages:
     cpu: [ia32]
     os: [linux]
 
+  '@esbuild/linux-ia32@0.24.0':
+    resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [linux]
+
   '@esbuild/linux-loong64@0.19.11':
     resolution: {integrity: sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg==}
     engines: {node: '>=12'}
@@ -1243,6 +1334,12 @@ packages:
     cpu: [loong64]
     os: [linux]
 
+  '@esbuild/linux-loong64@0.24.0':
+    resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==}
+    engines: {node: '>=18'}
+    cpu: [loong64]
+    os: [linux]
+
   '@esbuild/linux-mips64el@0.19.11':
     resolution: {integrity: sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg==}
     engines: {node: '>=12'}
@@ -1261,6 +1358,12 @@ packages:
     cpu: [mips64el]
     os: [linux]
 
+  '@esbuild/linux-mips64el@0.24.0':
+    resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==}
+    engines: {node: '>=18'}
+    cpu: [mips64el]
+    os: [linux]
+
   '@esbuild/linux-ppc64@0.19.11':
     resolution: {integrity: sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA==}
     engines: {node: '>=12'}
@@ -1279,6 +1382,12 @@ packages:
     cpu: [ppc64]
     os: [linux]
 
+  '@esbuild/linux-ppc64@0.24.0':
+    resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==}
+    engines: {node: '>=18'}
+    cpu: [ppc64]
+    os: [linux]
+
   '@esbuild/linux-riscv64@0.19.11':
     resolution: {integrity: sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ==}
     engines: {node: '>=12'}
@@ -1297,6 +1406,12 @@ packages:
     cpu: [riscv64]
     os: [linux]
 
+  '@esbuild/linux-riscv64@0.24.0':
+    resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==}
+    engines: {node: '>=18'}
+    cpu: [riscv64]
+    os: [linux]
+
   '@esbuild/linux-s390x@0.19.11':
     resolution: {integrity: sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q==}
     engines: {node: '>=12'}
@@ -1315,6 +1430,12 @@ packages:
     cpu: [s390x]
     os: [linux]
 
+  '@esbuild/linux-s390x@0.24.0':
+    resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==}
+    engines: {node: '>=18'}
+    cpu: [s390x]
+    os: [linux]
+
   '@esbuild/linux-x64@0.19.11':
     resolution: {integrity: sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA==}
     engines: {node: '>=12'}
@@ -1333,6 +1454,12 @@ packages:
     cpu: [x64]
     os: [linux]
 
+  '@esbuild/linux-x64@0.24.0':
+    resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [linux]
+
   '@esbuild/netbsd-x64@0.19.11':
     resolution: {integrity: sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ==}
     engines: {node: '>=12'}
@@ -1351,6 +1478,18 @@ packages:
     cpu: [x64]
     os: [netbsd]
 
+  '@esbuild/netbsd-x64@0.24.0':
+    resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [netbsd]
+
+  '@esbuild/openbsd-arm64@0.24.0':
+    resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [openbsd]
+
   '@esbuild/openbsd-x64@0.19.11':
     resolution: {integrity: sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw==}
     engines: {node: '>=12'}
@@ -1369,6 +1508,12 @@ packages:
     cpu: [x64]
     os: [openbsd]
 
+  '@esbuild/openbsd-x64@0.24.0':
+    resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [openbsd]
+
   '@esbuild/sunos-x64@0.19.11':
     resolution: {integrity: sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ==}
     engines: {node: '>=12'}
@@ -1387,6 +1532,12 @@ packages:
     cpu: [x64]
     os: [sunos]
 
+  '@esbuild/sunos-x64@0.24.0':
+    resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [sunos]
+
   '@esbuild/win32-arm64@0.19.11':
     resolution: {integrity: sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ==}
     engines: {node: '>=12'}
@@ -1405,6 +1556,12 @@ packages:
     cpu: [arm64]
     os: [win32]
 
+  '@esbuild/win32-arm64@0.24.0':
+    resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==}
+    engines: {node: '>=18'}
+    cpu: [arm64]
+    os: [win32]
+
   '@esbuild/win32-ia32@0.19.11':
     resolution: {integrity: sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg==}
     engines: {node: '>=12'}
@@ -1423,6 +1580,12 @@ packages:
     cpu: [ia32]
     os: [win32]
 
+  '@esbuild/win32-ia32@0.24.0':
+    resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==}
+    engines: {node: '>=18'}
+    cpu: [ia32]
+    os: [win32]
+
   '@esbuild/win32-x64@0.19.11':
     resolution: {integrity: sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw==}
     engines: {node: '>=12'}
@@ -1441,6 +1604,12 @@ packages:
     cpu: [x64]
     os: [win32]
 
+  '@esbuild/win32-x64@0.24.0':
+    resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==}
+    engines: {node: '>=18'}
+    cpu: [x64]
+    os: [win32]
+
   '@eslint-community/eslint-utils@4.4.0':
     resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
     engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1595,18 +1764,18 @@ packages:
     resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==}
     hasBin: true
 
-  '@microsoft/api-extractor-model@7.28.13':
-    resolution: {integrity: sha512-39v/JyldX4MS9uzHcdfmjjfS6cYGAoXV+io8B5a338pkHiSt+gy2eXQ0Q7cGFJ7quSa1VqqlMdlPrB6sLR/cAw==}
+  '@microsoft/api-extractor-model@7.30.0':
+    resolution: {integrity: sha512-26/LJZBrsWDKAkOWRiQbdVgcfd1F3nyJnAiJzsAgpouPk7LtOIj7PK9aJtBaw/pUXrkotEg27RrT+Jm/q0bbug==}
 
-  '@microsoft/api-extractor@7.43.0':
-    resolution: {integrity: sha512-GFhTcJpB+MI6FhvXEI9b2K0snulNLWHqC/BbcJtyNYcKUiw7l3Lgis5ApsYncJ0leALX7/of4XfmXk+maT111w==}
+  '@microsoft/api-extractor@7.48.0':
+    resolution: {integrity: sha512-FMFgPjoilMUWeZXqYRlJ3gCVRhB7WU/HN88n8OLqEsmsG4zBdX/KQdtJfhq95LQTQ++zfu0Em1LLb73NqRCLYQ==}
     hasBin: true
 
-  '@microsoft/tsdoc-config@0.16.2':
-    resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==}
+  '@microsoft/tsdoc-config@0.17.1':
+    resolution: {integrity: sha512-UtjIFe0C6oYgTnad4q1QP4qXwLhe6tIpNTRStJ2RZEPIkqQPREAwE5spzVxsdn9UaEMUqhh0AqSx3X4nWAKXWw==}
 
-  '@microsoft/tsdoc@0.14.2':
-    resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==}
+  '@microsoft/tsdoc@0.15.1':
+    resolution: {integrity: sha512-4aErSrCR/On/e5G2hDP0wjooqDdauzEbIq8hIkIe5pXV0rtWJZvdCEKL0ykZxex+IxIwBp0eGeV48hQN07dXtw==}
 
   '@netlify/binary-info@1.0.0':
     resolution: {integrity: sha512-4wMPu9iN3/HL97QblBsBay3E1etIciR84izI3U+4iALY+JHCrI+a2jO0qbAZ/nxKoegypYEaiiqWXylm+/zfrw==}
@@ -2423,27 +2592,31 @@ packages:
   '@rtsao/scc@1.1.0':
     resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==}
 
-  '@rushstack/node-core-library@4.0.2':
-    resolution: {integrity: sha512-hyES82QVpkfQMeBMteQUnrhASL/KHPhd7iJ8euduwNJG4mu2GSOKybf0rOEjOm1Wz7CwJEUm9y0yD7jg2C1bfg==}
+  '@rushstack/node-core-library@5.10.0':
+    resolution: {integrity: sha512-2pPLCuS/3x7DCd7liZkqOewGM0OzLyCacdvOe8j6Yrx9LkETGnxul1t7603bIaB8nUAooORcct9fFDOQMbWAgw==}
     peerDependencies:
       '@types/node': '*'
     peerDependenciesMeta:
       '@types/node':
         optional: true
 
-  '@rushstack/rig-package@0.5.2':
-    resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==}
+  '@rushstack/rig-package@0.5.3':
+    resolution: {integrity: sha512-olzSSjYrvCNxUFZowevC3uz8gvKr3WTpHQ7BkpjtRpA3wK+T0ybep/SRUMfr195gBzJm5gaXw0ZMgjIyHqJUow==}
 
-  '@rushstack/terminal@0.10.0':
-    resolution: {integrity: sha512-UbELbXnUdc7EKwfH2sb8ChqNgapUOdqcCIdQP4NGxBpTZV2sQyeekuK3zmfQSa/MN+/7b4kBogl2wq0vpkpYGw==}
+  '@rushstack/terminal@0.14.3':
+    resolution: {integrity: sha512-csXbZsAdab/v8DbU1sz7WC2aNaKArcdS/FPmXMOXEj/JBBZMvDK0+1b4Qao0kkG0ciB1Qe86/Mb68GjH6/TnMw==}
     peerDependencies:
       '@types/node': '*'
     peerDependenciesMeta:
       '@types/node':
         optional: true
 
-  '@rushstack/ts-command-line@4.19.1':
-    resolution: {integrity: sha512-J7H768dgcpG60d7skZ5uSSwyCZs/S2HrWP1Ds8d1qYAyaaeJmpmmLr9BVw97RjFzmQPOYnoXcKA4GkqDCkduQg==}
+  '@rushstack/ts-command-line@4.23.1':
+    resolution: {integrity: sha512-40jTmYoiu/xlIpkkRsVfENtBq4CW3R4azbL0Vmda+fMwHWqss6wwf/Cy/UJmMqIzpfYc2OTnjYP1ZLD3CmyeCA==}
+
+  '@sindresorhus/is@4.6.0':
+    resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==}
+    engines: {node: '>=10'}
 
   '@sindresorhus/is@5.6.0':
     resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==}
@@ -3173,32 +3346,6 @@ packages:
   '@vitest/utils@2.1.3':
     resolution: {integrity: sha512-xpiVfDSg1RrYT0tX6czgerkpcKFmFOF/gCr30+Mve5V2kewCy4Prn1/NDMSRwaSmT7PRaOF83wu+bEtsY1wrvA==}
 
-  '@volar/language-core@1.11.1':
-    resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==}
-
-  '@volar/source-map@1.11.1':
-    resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==}
-
-  '@volar/typescript@1.11.1':
-    resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==}
-
-  '@vue/compiler-core@3.5.12':
-    resolution: {integrity: sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==}
-
-  '@vue/compiler-dom@3.5.12':
-    resolution: {integrity: sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==}
-
-  '@vue/language-core@1.8.27':
-    resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==}
-    peerDependencies:
-      typescript: '*'
-    peerDependenciesMeta:
-      typescript:
-        optional: true
-
-  '@vue/shared@3.5.12':
-    resolution: {integrity: sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==}
-
   '@xhmikosr/archive-type@6.0.1':
     resolution: {integrity: sha512-PB3NeJL8xARZt52yDBupK0dNPn8uIVQDe15qNehUpoeeLWCZyAOam4vGXnoZGz2N9D1VXtjievJuCsXam2TmbQ==}
     engines: {node: ^14.14.0 || >=16.0.0}
@@ -3281,6 +3428,14 @@ packages:
     resolution: {integrity: sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==}
     engines: {node: '>=12'}
 
+  ajv-draft-04@1.0.0:
+    resolution: {integrity: sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==}
+    peerDependencies:
+      ajv: ^8.5.0
+    peerDependenciesMeta:
+      ajv:
+        optional: true
+
   ajv-errors@3.0.0:
     resolution: {integrity: sha512-V3wD15YHfHz6y0KdhYFjyy9vWtEVALT9UrxfN3zqlI6dMioHnJrqOYfyPKol3oqrnCM9uwkcdCwkJ0WUcbLMTQ==}
     peerDependencies:
@@ -3305,6 +3460,12 @@ packages:
   ajv@6.12.6:
     resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
 
+  ajv@8.12.0:
+    resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
+
+  ajv@8.13.0:
+    resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==}
+
   ajv@8.17.1:
     resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==}
 
@@ -3379,6 +3540,9 @@ packages:
     engines: {node: '>=8.0.0'}
     hasBin: true
 
+  any-promise@1.3.0:
+    resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
+
   anymatch@3.1.3:
     resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
     engines: {node: '>= 8'}
@@ -3673,6 +3837,12 @@ packages:
   builtins@5.1.0:
     resolution: {integrity: sha512-SW9lzGTLvWTP1AY8xeAMZimqDrIaSdLQUcVr9DMef51niJ022Ri87SwRRKYm4A6iHfkPaiVUu/Duw2Wc4J7kKg==}
 
+  bundle-require@5.0.0:
+    resolution: {integrity: sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+    peerDependencies:
+      esbuild: '>=0.18'
+
   byline@5.0.0:
     resolution: {integrity: sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==}
     engines: {node: '>=0.10.0'}
@@ -3749,6 +3919,10 @@ packages:
     resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==}
     engines: {node: ^12.17.0 || ^14.13 || >=16.0.0}
 
+  char-regex@1.0.2:
+    resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==}
+    engines: {node: '>=10'}
+
   character-entities@2.0.2:
     resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==}
 
@@ -3781,6 +3955,9 @@ packages:
   citty@0.1.6:
     resolution: {integrity: sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==}
 
+  cjs-module-lexer@1.4.1:
+    resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==}
+
   classcat@5.0.5:
     resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==}
 
@@ -3816,6 +3993,11 @@ packages:
     resolution: {integrity: sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==}
     engines: {node: '>=18'}
 
+  cli-highlight@2.1.11:
+    resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==}
+    engines: {node: '>=8.0.0', npm: '>=5.0.0'}
+    hasBin: true
+
   cli-progress@3.12.0:
     resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==}
     engines: {node: '>=4'}
@@ -3824,6 +4006,10 @@ packages:
     resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==}
     engines: {node: '>=6'}
 
+  cli-table3@0.6.5:
+    resolution: {integrity: sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==}
+    engines: {node: 10.* || >= 12.*}
+
   cli-truncate@2.1.0:
     resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
     engines: {node: '>=8'}
@@ -3839,6 +4025,9 @@ packages:
     resolution: {integrity: sha512-5mOlNS0mhX0707P2I0aZ2V/cmHUEO/fL7VFLqszkhUsxt7RwnmrInf/eEQKlf5GzvYeHIjT+Ov1HRfNmymlG0w==}
     engines: {node: '>=18'}
 
+  cliui@7.0.4:
+    resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
+
   cliui@8.0.1:
     resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
     engines: {node: '>=12'}
@@ -3906,6 +4095,10 @@ packages:
   commander@2.20.3:
     resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
 
+  commander@4.1.1:
+    resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==}
+    engines: {node: '>= 6'}
+
   commander@6.2.1:
     resolution: {integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==}
     engines: {node: '>= 6'}
@@ -3940,9 +4133,6 @@ packages:
     resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==}
     engines: {node: '>= 14'}
 
-  computeds@0.0.1:
-    resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
-
   concat-map@0.0.1:
     resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
 
@@ -4157,9 +4347,6 @@ packages:
     resolution: {integrity: sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==}
     engines: {node: '>=6'}
 
-  de-indent@1.0.2:
-    resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
-
   debug@2.6.9:
     resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
     peerDependencies:
@@ -4408,6 +4595,9 @@ packages:
   emoji-regex@9.2.2:
     resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==}
 
+  emojilib@2.4.0:
+    resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==}
+
   enabled@2.0.0:
     resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==}
 
@@ -4507,6 +4697,11 @@ packages:
     engines: {node: '>=12'}
     hasBin: true
 
+  esbuild@0.24.0:
+    resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==}
+    engines: {node: '>=18'}
+    hasBin: true
+
   escalade@3.2.0:
     resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
     engines: {node: '>=6'}
@@ -4847,6 +5042,9 @@ packages:
     resolution: {integrity: sha512-/wayUHbdVUWrD72aqRNNrr6+MHnCkumZgNugN0RfiWJpbNJUdAkMk4Z18MGayGZVVqYXR1RWrV+bIFEt5HuBZg==}
     engines: {node: '>=14.18.0'}
 
+  fflate@0.8.2:
+    resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
+
   figures@2.0.0:
     resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==}
     engines: {node: '>=4'}
@@ -5287,9 +5485,8 @@ packages:
   hast-util-whitespace@2.0.1:
     resolution: {integrity: sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==}
 
-  he@1.2.0:
-    resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
-    hasBin: true
+  highlight.js@10.7.3:
+    resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==}
 
   hosted-git-info@4.1.0:
     resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
@@ -5757,6 +5954,10 @@ packages:
   jju@1.4.0:
     resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==}
 
+  joycon@3.1.1:
+    resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==}
+    engines: {node: '>=10'}
+
   js-string-escape@1.0.1:
     resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==}
     engines: {node: '>= 0.8'}
@@ -5856,9 +6057,6 @@ packages:
   known-css-properties@0.35.0:
     resolution: {integrity: sha512-a/RAk2BfKk+WFGhhOCAYqSiFLc34k8Mt/6NWRI4joER0EYUzXIcFivjjnoD3+XU1DggLn/tZc3DOAgke7l8a4A==}
 
-  kolorist@1.8.0:
-    resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==}
-
   kuler@2.0.0:
     resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==}
 
@@ -5904,6 +6102,10 @@ packages:
     resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
     engines: {node: '>=10'}
 
+  lilconfig@3.1.2:
+    resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==}
+    engines: {node: '>=14'}
+
   lines-and-columns@1.2.4:
     resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
 
@@ -5934,6 +6136,10 @@ packages:
     resolution: {integrity: sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==}
     engines: {node: '>=18.0.0'}
 
+  load-tsconfig@0.2.5:
+    resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==}
+    engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+
   locate-character@3.0.0:
     resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
 
@@ -5955,9 +6161,6 @@ packages:
   lodash.debounce@4.0.8:
     resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==}
 
-  lodash.get@4.4.2:
-    resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
-
   lodash.includes@4.3.0:
     resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==}
 
@@ -5967,9 +6170,6 @@ packages:
   lodash.isempty@4.4.0:
     resolution: {integrity: sha512-oKMuF3xEeqDltrGMfDxAPGIVMSSRv8tbRSODbrs4KGsRRLEhrW8N8Rd4DRgB2+621hY8A8XwwrTVhXWpxFvMzg==}
 
-  lodash.isequal@4.5.0:
-    resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==}
-
   lodash.isinteger@4.0.4:
     resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==}
 
@@ -6096,11 +6296,22 @@ packages:
   markdown-table@3.0.4:
     resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==}
 
+  marked-terminal@7.2.1:
+    resolution: {integrity: sha512-rQ1MoMFXZICWNsKMiiHwP/Z+92PLKskTPXj+e7uwXmuMPkNn7iTqC+IvDekVm1MPeC9wYQeLxeFaOvudRR/XbQ==}
+    engines: {node: '>=16.0.0'}
+    peerDependencies:
+      marked: '>=1 <15'
+
   marked@4.3.0:
     resolution: {integrity: sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==}
     engines: {node: '>= 12'}
     hasBin: true
 
+  marked@9.1.6:
+    resolution: {integrity: sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==}
+    engines: {node: '>= 16'}
+    hasBin: true
+
   maxstache-stream@1.0.4:
     resolution: {integrity: sha512-v8qlfPN0pSp7bdSoLo1NTjG43GXGqk5W2NWFnOCq2GlmFFqebGzPCjLKSbShuqIOVorOtZSAy7O/S1OCCRONUw==}
 
@@ -6486,9 +6697,6 @@ packages:
   ms@2.1.3:
     resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
 
-  muggle-string@0.3.1:
-    resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==}
-
   multiparty@4.2.3:
     resolution: {integrity: sha512-Ak6EUJZuhGS8hJ3c2fY6UW5MbkGUPMBEGd13djUzoY/BHqV/gTuFWtC6IuVA7A2+v3yjBS6c4or50xhzTQZImQ==}
     engines: {node: '>= 0.10'}
@@ -6496,6 +6704,9 @@ packages:
   mute-stream@0.0.7:
     resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==}
 
+  mz@2.7.0:
+    resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
+
   nan@2.22.0:
     resolution: {integrity: sha512-nbajikzWTMwsW+eSsNm3QwlOs7het9gGJU5dDZzRTQGk03vyBOauxgI4VakDzE0PtsGTmXPsXTbbjVhRwR5mpw==}
 
@@ -6554,6 +6765,10 @@ packages:
     resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
     engines: {node: '>=10.5.0'}
 
+  node-emoji@2.1.3:
+    resolution: {integrity: sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==}
+    engines: {node: '>=18'}
+
   node-fetch-native@1.6.4:
     resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==}
 
@@ -6887,6 +7102,15 @@ packages:
     resolution: {integrity: sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==}
     engines: {node: '>=12'}
 
+  parse5-htmlparser2-tree-adapter@6.0.1:
+    resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==}
+
+  parse5@5.1.1:
+    resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==}
+
+  parse5@6.0.1:
+    resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
+
   parseurl@1.3.3:
     resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
     engines: {node: '>= 0.8'}
@@ -6894,9 +7118,6 @@ packages:
   pascal-case@3.1.2:
     resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
 
-  path-browserify@1.0.1:
-    resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
-
   path-exists@4.0.0:
     resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
     engines: {node: '>=8'}
@@ -6990,6 +7211,10 @@ packages:
     resolution: {integrity: sha512-xSEmD4pLnV54t0NOUN16yCl7RIB1c5UUOse5HSyEXtBp+FgFQyPeDutc+Q2ZO7/22vImV7VfEjH/1zV2QuqvYw==}
     hasBin: true
 
+  pirates@4.0.6:
+    resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==}
+    engines: {node: '>= 6'}
+
   pkg-dir@4.2.0:
     resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==}
     engines: {node: '>=8'}
@@ -7034,6 +7259,24 @@ packages:
       ts-node:
         optional: true
 
+  postcss-load-config@6.0.1:
+    resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==}
+    engines: {node: '>= 18'}
+    peerDependencies:
+      jiti: '>=1.21.0'
+      postcss: '>=8.0.9'
+      tsx: ^4.8.1
+      yaml: ^2.4.2
+    peerDependenciesMeta:
+      jiti:
+        optional: true
+      postcss:
+        optional: true
+      tsx:
+        optional: true
+      yaml:
+        optional: true
+
   postcss-safe-parser@6.0.0:
     resolution: {integrity: sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==}
     engines: {node: '>=12.0'}
@@ -7574,9 +7817,6 @@ packages:
     resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
     engines: {node: '>=8'}
 
-  resolve@1.19.0:
-    resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==}
-
   resolve@1.22.8:
     resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
     hasBin: true
@@ -7790,6 +8030,10 @@ packages:
     resolution: {integrity: sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==}
     engines: {node: '>=18'}
 
+  skin-tone@2.0.0:
+    resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==}
+    engines: {node: '>=8'}
+
   slash@3.0.0:
     resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
     engines: {node: '>=8'}
@@ -8051,6 +8295,11 @@ packages:
   stylis@4.3.2:
     resolution: {integrity: sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==}
 
+  sucrase@3.35.0:
+    resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==}
+    engines: {node: '>=16 || 14 >=14.17'}
+    hasBin: true
+
   supports-color@5.5.0:
     resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
     engines: {node: '>=4'}
@@ -8071,6 +8320,10 @@ packages:
     resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==}
     engines: {node: '>=8'}
 
+  supports-hyperlinks@3.1.0:
+    resolution: {integrity: sha512-2rn0BZ+/f7puLOHZm1HOJfwBggfaHXUpPUSSG/SWM4TWp5KCfmNYwnC3hruy2rZlMnmWZ+QAGpZfchu3f3695A==}
+    engines: {node: '>=14.18'}
+
   supports-preserve-symlinks-flag@1.0.0:
     resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
     engines: {node: '>= 0.4'}
@@ -8204,6 +8457,13 @@ packages:
   text-table@0.2.0:
     resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
 
+  thenify-all@1.6.0:
+    resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==}
+    engines: {node: '>=0.8'}
+
+  thenify@3.3.1:
+    resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==}
+
   thread-stream@3.1.0:
     resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==}
 
@@ -8311,6 +8571,10 @@ packages:
   tr46@1.0.1:
     resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==}
 
+  tree-kill@1.2.2:
+    resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+    hasBin: true
+
   trim-lines@3.0.1:
     resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==}
 
@@ -8335,6 +8599,9 @@ packages:
     peerDependencies:
       typescript: '>=4.2.0'
 
+  ts-interface-checker@0.1.13:
+    resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
+
   ts-node@10.9.2:
     resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
     hasBin: true
@@ -8361,6 +8628,25 @@ packages:
   tslib@2.8.0:
     resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==}
 
+  tsup@8.3.5:
+    resolution: {integrity: sha512-Tunf6r6m6tnZsG9GYWndg0z8dEV7fD733VBFzFJ5Vcm1FtlXB8xBD/rtrBi2a3YKEV7hHtxiZtW5EAVADoe1pA==}
+    engines: {node: '>=18'}
+    hasBin: true
+    peerDependencies:
+      '@microsoft/api-extractor': ^7.36.0
+      '@swc/core': ^1
+      postcss: ^8.4.12
+      typescript: '>=4.5.0'
+    peerDependenciesMeta:
+      '@microsoft/api-extractor':
+        optional: true
+      '@swc/core':
+        optional: true
+      postcss:
+        optional: true
+      typescript:
+        optional: true
+
   tsutils@3.21.0:
     resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
     engines: {node: '>= 6'}
@@ -8454,6 +8740,11 @@ packages:
     engines: {node: '>=14.17'}
     hasBin: true
 
+  typescript@5.6.1-rc:
+    resolution: {integrity: sha512-E3b2+1zEFu84jB0YQi9BORDjz9+jGbwwy1Zi3G0LUNw7a7cePUrHMRNy8aPh53nXpkFGVHSxIZo5vKTfYaFiBQ==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+
   typescript@5.6.3:
     resolution: {integrity: sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==}
     engines: {node: '>=14.17'}
@@ -8496,6 +8787,10 @@ packages:
     resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==}
     engines: {node: '>=4'}
 
+  unicode-emoji-modifier-base@1.0.0:
+    resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==}
+    engines: {node: '>=4'}
+
   unicode-match-property-ecmascript@2.0.0:
     resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==}
     engines: {node: '>=4'}
@@ -8693,9 +8988,9 @@ packages:
     resolution: {integrity: sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==}
     engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
 
-  validator@13.12.0:
-    resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
-    engines: {node: '>= 0.10'}
+  validate-npm-package-name@5.0.1:
+    resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==}
+    engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
 
   vary@1.1.2:
     resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
@@ -8712,16 +9007,6 @@ packages:
     engines: {node: ^18.0.0 || >=20.0.0}
     hasBin: true
 
-  vite-plugin-dts@3.9.1:
-    resolution: {integrity: sha512-rVp2KM9Ue22NGWB8dNtWEr+KekN3rIgz1tWD050QnRGlriUCmaDwa7qA5zDEjbXg5lAXhYMSBJtx3q3hQIJZSg==}
-    engines: {node: ^14.18.0 || >=16.0.0}
-    peerDependencies:
-      typescript: '*'
-      vite: '*'
-    peerDependenciesMeta:
-      vite:
-        optional: true
-
   vite-plugin-prismjs@0.0.11:
     resolution: {integrity: sha512-20NBQxg/zH+3FTrlU6BQTob720xkuXNYtrx7psAQ4E6pMcRDeLEK77QU9kXURU587+f2To7ASH1JVTGbXVV/vQ==}
     engines: {node: '>=12.0.0'}
@@ -8813,15 +9098,6 @@ packages:
   vscode-textmate@8.0.0:
     resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
 
-  vue-template-compiler@2.7.16:
-    resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==}
-
-  vue-tsc@1.8.27:
-    resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==}
-    hasBin: true
-    peerDependencies:
-      typescript: '*'
-
   w3c-keyname@2.2.8:
     resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==}
 
@@ -9031,10 +9307,18 @@ packages:
     engines: {node: '>= 14'}
     hasBin: true
 
+  yargs-parser@20.2.9:
+    resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
+    engines: {node: '>=10'}
+
   yargs-parser@21.1.1:
     resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
     engines: {node: '>=12'}
 
+  yargs@16.2.0:
+    resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
+    engines: {node: '>=10'}
+
   yargs@17.7.2:
     resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
     engines: {node: '>=12'}
@@ -9054,11 +9338,6 @@ packages:
     resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==}
     engines: {node: '>=12.20'}
 
-  z-schema@5.0.5:
-    resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==}
-    engines: {node: '>=8.0.0'}
-    hasBin: true
-
   zimmerframe@1.1.2:
     resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
 
@@ -9094,6 +9373,8 @@ snapshots:
       '@jridgewell/gen-mapping': 0.3.5
       '@jridgewell/trace-mapping': 0.3.25
 
+  '@andrewbranch/untar.js@1.0.3': {}
+
   '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)':
     dependencies:
       ajv: 8.17.1
@@ -9101,6 +9382,26 @@ snapshots:
       jsonpointer: 5.0.1
       leven: 3.1.0
 
+  '@arethetypeswrong/cli@0.17.0':
+    dependencies:
+      '@arethetypeswrong/core': 0.17.0
+      chalk: 4.1.2
+      cli-table3: 0.6.5
+      commander: 10.0.1
+      marked: 9.1.6
+      marked-terminal: 7.2.1(marked@9.1.6)
+      semver: 7.6.3
+
+  '@arethetypeswrong/core@0.17.0':
+    dependencies:
+      '@andrewbranch/untar.js': 1.0.3
+      cjs-module-lexer: 1.4.1
+      fflate: 0.8.2
+      lru-cache: 10.4.3
+      semver: 7.6.3
+      typescript: 5.6.1-rc
+      validate-npm-package-name: 5.0.1
+
   '@babel/code-frame@7.25.9':
     dependencies:
       '@babel/highlight': 7.25.9
@@ -9797,6 +10098,9 @@ snapshots:
 
   '@bugsnag/safe-json-stringify@6.0.0': {}
 
+  '@colors/colors@1.5.0':
+    optional: true
+
   '@colors/colors@1.6.0': {}
 
   '@cspotcode/source-map-support@0.8.1':
@@ -9873,6 +10177,9 @@ snapshots:
   '@esbuild/aix-ppc64@0.21.5':
     optional: true
 
+  '@esbuild/aix-ppc64@0.24.0':
+    optional: true
+
   '@esbuild/android-arm64@0.19.11':
     optional: true
 
@@ -9882,6 +10189,9 @@ snapshots:
   '@esbuild/android-arm64@0.21.5':
     optional: true
 
+  '@esbuild/android-arm64@0.24.0':
+    optional: true
+
   '@esbuild/android-arm@0.19.11':
     optional: true
 
@@ -9891,6 +10201,9 @@ snapshots:
   '@esbuild/android-arm@0.21.5':
     optional: true
 
+  '@esbuild/android-arm@0.24.0':
+    optional: true
+
   '@esbuild/android-x64@0.19.11':
     optional: true
 
@@ -9900,6 +10213,9 @@ snapshots:
   '@esbuild/android-x64@0.21.5':
     optional: true
 
+  '@esbuild/android-x64@0.24.0':
+    optional: true
+
   '@esbuild/darwin-arm64@0.19.11':
     optional: true
 
@@ -9909,6 +10225,9 @@ snapshots:
   '@esbuild/darwin-arm64@0.21.5':
     optional: true
 
+  '@esbuild/darwin-arm64@0.24.0':
+    optional: true
+
   '@esbuild/darwin-x64@0.19.11':
     optional: true
 
@@ -9918,6 +10237,9 @@ snapshots:
   '@esbuild/darwin-x64@0.21.5':
     optional: true
 
+  '@esbuild/darwin-x64@0.24.0':
+    optional: true
+
   '@esbuild/freebsd-arm64@0.19.11':
     optional: true
 
@@ -9927,6 +10249,9 @@ snapshots:
   '@esbuild/freebsd-arm64@0.21.5':
     optional: true
 
+  '@esbuild/freebsd-arm64@0.24.0':
+    optional: true
+
   '@esbuild/freebsd-x64@0.19.11':
     optional: true
 
@@ -9936,6 +10261,9 @@ snapshots:
   '@esbuild/freebsd-x64@0.21.5':
     optional: true
 
+  '@esbuild/freebsd-x64@0.24.0':
+    optional: true
+
   '@esbuild/linux-arm64@0.19.11':
     optional: true
 
@@ -9945,6 +10273,9 @@ snapshots:
   '@esbuild/linux-arm64@0.21.5':
     optional: true
 
+  '@esbuild/linux-arm64@0.24.0':
+    optional: true
+
   '@esbuild/linux-arm@0.19.11':
     optional: true
 
@@ -9954,6 +10285,9 @@ snapshots:
   '@esbuild/linux-arm@0.21.5':
     optional: true
 
+  '@esbuild/linux-arm@0.24.0':
+    optional: true
+
   '@esbuild/linux-ia32@0.19.11':
     optional: true
 
@@ -9963,6 +10297,9 @@ snapshots:
   '@esbuild/linux-ia32@0.21.5':
     optional: true
 
+  '@esbuild/linux-ia32@0.24.0':
+    optional: true
+
   '@esbuild/linux-loong64@0.19.11':
     optional: true
 
@@ -9972,6 +10309,9 @@ snapshots:
   '@esbuild/linux-loong64@0.21.5':
     optional: true
 
+  '@esbuild/linux-loong64@0.24.0':
+    optional: true
+
   '@esbuild/linux-mips64el@0.19.11':
     optional: true
 
@@ -9981,6 +10321,9 @@ snapshots:
   '@esbuild/linux-mips64el@0.21.5':
     optional: true
 
+  '@esbuild/linux-mips64el@0.24.0':
+    optional: true
+
   '@esbuild/linux-ppc64@0.19.11':
     optional: true
 
@@ -9990,6 +10333,9 @@ snapshots:
   '@esbuild/linux-ppc64@0.21.5':
     optional: true
 
+  '@esbuild/linux-ppc64@0.24.0':
+    optional: true
+
   '@esbuild/linux-riscv64@0.19.11':
     optional: true
 
@@ -9999,6 +10345,9 @@ snapshots:
   '@esbuild/linux-riscv64@0.21.5':
     optional: true
 
+  '@esbuild/linux-riscv64@0.24.0':
+    optional: true
+
   '@esbuild/linux-s390x@0.19.11':
     optional: true
 
@@ -10008,6 +10357,9 @@ snapshots:
   '@esbuild/linux-s390x@0.21.5':
     optional: true
 
+  '@esbuild/linux-s390x@0.24.0':
+    optional: true
+
   '@esbuild/linux-x64@0.19.11':
     optional: true
 
@@ -10017,6 +10369,9 @@ snapshots:
   '@esbuild/linux-x64@0.21.5':
     optional: true
 
+  '@esbuild/linux-x64@0.24.0':
+    optional: true
+
   '@esbuild/netbsd-x64@0.19.11':
     optional: true
 
@@ -10026,6 +10381,12 @@ snapshots:
   '@esbuild/netbsd-x64@0.21.5':
     optional: true
 
+  '@esbuild/netbsd-x64@0.24.0':
+    optional: true
+
+  '@esbuild/openbsd-arm64@0.24.0':
+    optional: true
+
   '@esbuild/openbsd-x64@0.19.11':
     optional: true
 
@@ -10035,6 +10396,9 @@ snapshots:
   '@esbuild/openbsd-x64@0.21.5':
     optional: true
 
+  '@esbuild/openbsd-x64@0.24.0':
+    optional: true
+
   '@esbuild/sunos-x64@0.19.11':
     optional: true
 
@@ -10044,6 +10408,9 @@ snapshots:
   '@esbuild/sunos-x64@0.21.5':
     optional: true
 
+  '@esbuild/sunos-x64@0.24.0':
+    optional: true
+
   '@esbuild/win32-arm64@0.19.11':
     optional: true
 
@@ -10053,6 +10420,9 @@ snapshots:
   '@esbuild/win32-arm64@0.21.5':
     optional: true
 
+  '@esbuild/win32-arm64@0.24.0':
+    optional: true
+
   '@esbuild/win32-ia32@0.19.11':
     optional: true
 
@@ -10062,6 +10432,9 @@ snapshots:
   '@esbuild/win32-ia32@0.21.5':
     optional: true
 
+  '@esbuild/win32-ia32@0.24.0':
+    optional: true
+
   '@esbuild/win32-x64@0.19.11':
     optional: true
 
@@ -10071,6 +10444,9 @@ snapshots:
   '@esbuild/win32-x64@0.21.5':
     optional: true
 
+  '@esbuild/win32-x64@0.24.0':
+    optional: true
+
   '@eslint-community/eslint-utils@4.4.0(eslint@8.57.1)':
     dependencies:
       eslint: 8.57.1
@@ -10271,23 +10647,23 @@ snapshots:
       - encoding
       - supports-color
 
-  '@microsoft/api-extractor-model@7.28.13(@types/node@20.17.0)':
+  '@microsoft/api-extractor-model@7.30.0(@types/node@20.17.0)':
     dependencies:
-      '@microsoft/tsdoc': 0.14.2
-      '@microsoft/tsdoc-config': 0.16.2
-      '@rushstack/node-core-library': 4.0.2(@types/node@20.17.0)
+      '@microsoft/tsdoc': 0.15.1
+      '@microsoft/tsdoc-config': 0.17.1
+      '@rushstack/node-core-library': 5.10.0(@types/node@20.17.0)
     transitivePeerDependencies:
       - '@types/node'
 
-  '@microsoft/api-extractor@7.43.0(@types/node@20.17.0)':
+  '@microsoft/api-extractor@7.48.0(@types/node@20.17.0)':
     dependencies:
-      '@microsoft/api-extractor-model': 7.28.13(@types/node@20.17.0)
-      '@microsoft/tsdoc': 0.14.2
-      '@microsoft/tsdoc-config': 0.16.2
-      '@rushstack/node-core-library': 4.0.2(@types/node@20.17.0)
-      '@rushstack/rig-package': 0.5.2
-      '@rushstack/terminal': 0.10.0(@types/node@20.17.0)
-      '@rushstack/ts-command-line': 4.19.1(@types/node@20.17.0)
+      '@microsoft/api-extractor-model': 7.30.0(@types/node@20.17.0)
+      '@microsoft/tsdoc': 0.15.1
+      '@microsoft/tsdoc-config': 0.17.1
+      '@rushstack/node-core-library': 5.10.0(@types/node@20.17.0)
+      '@rushstack/rig-package': 0.5.3
+      '@rushstack/terminal': 0.14.3(@types/node@20.17.0)
+      '@rushstack/ts-command-line': 4.23.1(@types/node@20.17.0)
       lodash: 4.17.21
       minimatch: 3.0.8
       resolve: 1.22.8
@@ -10297,14 +10673,14 @@ snapshots:
     transitivePeerDependencies:
       - '@types/node'
 
-  '@microsoft/tsdoc-config@0.16.2':
+  '@microsoft/tsdoc-config@0.17.1':
     dependencies:
-      '@microsoft/tsdoc': 0.14.2
-      ajv: 6.12.6
+      '@microsoft/tsdoc': 0.15.1
+      ajv: 8.12.0
       jju: 1.4.0
-      resolve: 1.19.0
+      resolve: 1.22.8
 
-  '@microsoft/tsdoc@0.14.2': {}
+  '@microsoft/tsdoc@0.15.1': {}
 
   '@netlify/binary-info@1.0.0': {}
 
@@ -11198,14 +11574,6 @@ snapshots:
     optionalDependencies:
       rollup: 2.79.2
 
-  '@rollup/pluginutils@5.1.3(rollup@4.24.0)':
-    dependencies:
-      '@types/estree': 1.0.6
-      estree-walker: 2.0.2
-      picomatch: 4.0.2
-    optionalDependencies:
-      rollup: 4.24.0
-
   '@rollup/rollup-android-arm-eabi@4.24.0':
     optional: true
 
@@ -11256,38 +11624,42 @@ snapshots:
 
   '@rtsao/scc@1.1.0': {}
 
-  '@rushstack/node-core-library@4.0.2(@types/node@20.17.0)':
+  '@rushstack/node-core-library@5.10.0(@types/node@20.17.0)':
     dependencies:
+      ajv: 8.13.0
+      ajv-draft-04: 1.0.0(ajv@8.13.0)
+      ajv-formats: 3.0.1(ajv@8.13.0)
       fs-extra: 7.0.1
       import-lazy: 4.0.0
       jju: 1.4.0
       resolve: 1.22.8
       semver: 7.5.4
-      z-schema: 5.0.5
     optionalDependencies:
       '@types/node': 20.17.0
 
-  '@rushstack/rig-package@0.5.2':
+  '@rushstack/rig-package@0.5.3':
     dependencies:
       resolve: 1.22.8
       strip-json-comments: 3.1.1
 
-  '@rushstack/terminal@0.10.0(@types/node@20.17.0)':
+  '@rushstack/terminal@0.14.3(@types/node@20.17.0)':
     dependencies:
-      '@rushstack/node-core-library': 4.0.2(@types/node@20.17.0)
+      '@rushstack/node-core-library': 5.10.0(@types/node@20.17.0)
       supports-color: 8.1.1
     optionalDependencies:
       '@types/node': 20.17.0
 
-  '@rushstack/ts-command-line@4.19.1(@types/node@20.17.0)':
+  '@rushstack/ts-command-line@4.23.1(@types/node@20.17.0)':
     dependencies:
-      '@rushstack/terminal': 0.10.0(@types/node@20.17.0)
+      '@rushstack/terminal': 0.14.3(@types/node@20.17.0)
       '@types/argparse': 1.0.38
       argparse: 1.0.10
       string-argv: 0.3.2
     transitivePeerDependencies:
       - '@types/node'
 
+  '@sindresorhus/is@4.6.0': {}
+
   '@sindresorhus/is@5.6.0': {}
 
   '@sindresorhus/slugify@2.2.1':
@@ -12131,48 +12503,6 @@ snapshots:
       loupe: 3.1.2
       tinyrainbow: 1.2.0
 
-  '@volar/language-core@1.11.1':
-    dependencies:
-      '@volar/source-map': 1.11.1
-
-  '@volar/source-map@1.11.1':
-    dependencies:
-      muggle-string: 0.3.1
-
-  '@volar/typescript@1.11.1':
-    dependencies:
-      '@volar/language-core': 1.11.1
-      path-browserify: 1.0.1
-
-  '@vue/compiler-core@3.5.12':
-    dependencies:
-      '@babel/parser': 7.25.9
-      '@vue/shared': 3.5.12
-      entities: 4.5.0
-      estree-walker: 2.0.2
-      source-map-js: 1.2.1
-
-  '@vue/compiler-dom@3.5.12':
-    dependencies:
-      '@vue/compiler-core': 3.5.12
-      '@vue/shared': 3.5.12
-
-  '@vue/language-core@1.8.27(typescript@5.6.3)':
-    dependencies:
-      '@volar/language-core': 1.11.1
-      '@volar/source-map': 1.11.1
-      '@vue/compiler-dom': 3.5.12
-      '@vue/shared': 3.5.12
-      computeds: 0.0.1
-      minimatch: 9.0.5
-      muggle-string: 0.3.1
-      path-browserify: 1.0.1
-      vue-template-compiler: 2.7.16
-    optionalDependencies:
-      typescript: 5.6.3
-
-  '@vue/shared@3.5.12': {}
-
   '@xhmikosr/archive-type@6.0.1':
     dependencies:
       file-type: 18.7.0
@@ -12279,6 +12609,10 @@ snapshots:
       clean-stack: 4.2.0
       indent-string: 5.0.0
 
+  ajv-draft-04@1.0.0(ajv@8.13.0):
+    optionalDependencies:
+      ajv: 8.13.0
+
   ajv-errors@3.0.0(ajv@8.17.1):
     dependencies:
       ajv: 8.17.1
@@ -12287,6 +12621,10 @@ snapshots:
     optionalDependencies:
       ajv: 8.17.1
 
+  ajv-formats@3.0.1(ajv@8.13.0):
+    optionalDependencies:
+      ajv: 8.13.0
+
   ajv-formats@3.0.1(ajv@8.17.1):
     optionalDependencies:
       ajv: 8.17.1
@@ -12298,6 +12636,20 @@ snapshots:
       json-schema-traverse: 0.4.1
       uri-js: 4.4.1
 
+  ajv@8.12.0:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      json-schema-traverse: 1.0.0
+      require-from-string: 2.0.2
+      uri-js: 4.4.1
+
+  ajv@8.13.0:
+    dependencies:
+      fast-deep-equal: 3.1.3
+      json-schema-traverse: 1.0.0
+      require-from-string: 2.0.2
+      uri-js: 4.4.1
+
   ajv@8.17.1:
     dependencies:
       fast-deep-equal: 3.1.3
@@ -12364,6 +12716,8 @@ snapshots:
     dependencies:
       entities: 2.2.0
 
+  any-promise@1.3.0: {}
+
   anymatch@3.1.3:
     dependencies:
       normalize-path: 3.0.0
@@ -12720,6 +13074,11 @@ snapshots:
     dependencies:
       semver: 7.6.3
 
+  bundle-require@5.0.0(esbuild@0.24.0):
+    dependencies:
+      esbuild: 0.24.0
+      load-tsconfig: 0.2.5
+
   byline@5.0.0: {}
 
   bytes@3.1.2: {}
@@ -12795,6 +13154,8 @@ snapshots:
 
   chalk@5.3.0: {}
 
+  char-regex@1.0.2: {}
+
   character-entities@2.0.2: {}
 
   chardet@0.7.0: {}
@@ -12827,6 +13188,8 @@ snapshots:
     dependencies:
       consola: 3.2.3
 
+  cjs-module-lexer@1.4.1: {}
+
   classcat@5.0.5: {}
 
   clean-css@5.3.3:
@@ -12859,12 +13222,27 @@ snapshots:
     dependencies:
       restore-cursor: 5.1.0
 
+  cli-highlight@2.1.11:
+    dependencies:
+      chalk: 4.1.2
+      highlight.js: 10.7.3
+      mz: 2.7.0
+      parse5: 5.1.1
+      parse5-htmlparser2-tree-adapter: 6.0.1
+      yargs: 16.2.0
+
   cli-progress@3.12.0:
     dependencies:
       string-width: 4.2.3
 
   cli-spinners@2.9.2: {}
 
+  cli-table3@0.6.5:
+    dependencies:
+      string-width: 4.2.3
+    optionalDependencies:
+      '@colors/colors': 1.5.0
+
   cli-truncate@2.1.0:
     dependencies:
       slice-ansi: 3.0.0
@@ -12883,6 +13261,12 @@ snapshots:
       is-wsl: 3.1.0
       is64bit: 2.0.0
 
+  cliui@7.0.4:
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+
   cliui@8.0.1:
     dependencies:
       string-width: 4.2.3
@@ -12951,6 +13335,8 @@ snapshots:
 
   commander@2.20.3: {}
 
+  commander@4.1.1: {}
+
   commander@6.2.1: {}
 
   commander@7.2.0: {}
@@ -12981,8 +13367,6 @@ snapshots:
       normalize-path: 3.0.0
       readable-stream: 4.5.2
 
-  computeds@0.0.1: {}
-
   concat-map@0.0.1: {}
 
   concordance@5.0.4:
@@ -13211,8 +13595,6 @@ snapshots:
     dependencies:
       time-zone: 1.0.0
 
-  de-indent@1.0.2: {}
-
   debug@2.6.9:
     dependencies:
       ms: 2.0.0
@@ -13421,6 +13803,8 @@ snapshots:
 
   emoji-regex@9.2.2: {}
 
+  emojilib@2.4.0: {}
+
   enabled@2.0.0: {}
 
   encodeurl@1.0.2: {}
@@ -13630,6 +14014,33 @@ snapshots:
       '@esbuild/win32-ia32': 0.21.5
       '@esbuild/win32-x64': 0.21.5
 
+  esbuild@0.24.0:
+    optionalDependencies:
+      '@esbuild/aix-ppc64': 0.24.0
+      '@esbuild/android-arm': 0.24.0
+      '@esbuild/android-arm64': 0.24.0
+      '@esbuild/android-x64': 0.24.0
+      '@esbuild/darwin-arm64': 0.24.0
+      '@esbuild/darwin-x64': 0.24.0
+      '@esbuild/freebsd-arm64': 0.24.0
+      '@esbuild/freebsd-x64': 0.24.0
+      '@esbuild/linux-arm': 0.24.0
+      '@esbuild/linux-arm64': 0.24.0
+      '@esbuild/linux-ia32': 0.24.0
+      '@esbuild/linux-loong64': 0.24.0
+      '@esbuild/linux-mips64el': 0.24.0
+      '@esbuild/linux-ppc64': 0.24.0
+      '@esbuild/linux-riscv64': 0.24.0
+      '@esbuild/linux-s390x': 0.24.0
+      '@esbuild/linux-x64': 0.24.0
+      '@esbuild/netbsd-x64': 0.24.0
+      '@esbuild/openbsd-arm64': 0.24.0
+      '@esbuild/openbsd-x64': 0.24.0
+      '@esbuild/sunos-x64': 0.24.0
+      '@esbuild/win32-arm64': 0.24.0
+      '@esbuild/win32-ia32': 0.24.0
+      '@esbuild/win32-x64': 0.24.0
+
   escalade@3.2.0: {}
 
   escape-goat@4.0.0: {}
@@ -14148,6 +14559,8 @@ snapshots:
       got: 12.6.1
       is-plain-obj: 4.1.0
 
+  fflate@0.8.2: {}
+
   figures@2.0.0:
     dependencies:
       escape-string-regexp: 1.0.5
@@ -14626,7 +15039,7 @@ snapshots:
 
   hast-util-whitespace@2.0.1: {}
 
-  he@1.2.0: {}
+  highlight.js@10.7.3: {}
 
   hosted-git-info@4.1.0:
     dependencies:
@@ -15064,6 +15477,8 @@ snapshots:
 
   jju@1.4.0: {}
 
+  joycon@3.1.1: {}
+
   js-string-escape@1.0.1: {}
 
   js-tokens@4.0.0: {}
@@ -15159,8 +15574,6 @@ snapshots:
 
   known-css-properties@0.35.0: {}
 
-  kolorist@1.8.0: {}
-
   kuler@2.0.0: {}
 
   ky@1.7.2: {}
@@ -15202,6 +15615,8 @@ snapshots:
 
   lilconfig@2.1.0: {}
 
+  lilconfig@3.1.2: {}
+
   lines-and-columns@1.2.4: {}
 
   linkify-it@5.0.0:
@@ -15273,6 +15688,8 @@ snapshots:
       rfdc: 1.4.1
       wrap-ansi: 9.0.0
 
+  load-tsconfig@0.2.5: {}
+
   locate-character@3.0.0: {}
 
   locate-path@5.0.0:
@@ -15291,16 +15708,12 @@ snapshots:
 
   lodash.debounce@4.0.8: {}
 
-  lodash.get@4.4.2: {}
-
   lodash.includes@4.3.0: {}
 
   lodash.isboolean@3.0.3: {}
 
   lodash.isempty@4.4.0: {}
 
-  lodash.isequal@4.5.0: {}
-
   lodash.isinteger@4.0.4: {}
 
   lodash.isnumber@3.0.3: {}
@@ -15430,8 +15843,21 @@ snapshots:
 
   markdown-table@3.0.4: {}
 
+  marked-terminal@7.2.1(marked@9.1.6):
+    dependencies:
+      ansi-escapes: 7.0.0
+      ansi-regex: 6.1.0
+      chalk: 5.3.0
+      cli-highlight: 2.1.11
+      cli-table3: 0.6.5
+      marked: 9.1.6
+      node-emoji: 2.1.3
+      supports-hyperlinks: 3.1.0
+
   marked@4.3.0: {}
 
+  marked@9.1.6: {}
+
   maxstache-stream@1.0.4:
     dependencies:
       maxstache: 1.0.7
@@ -16029,8 +16455,6 @@ snapshots:
 
   ms@2.1.3: {}
 
-  muggle-string@0.3.1: {}
-
   multiparty@4.2.3:
     dependencies:
       http-errors: 1.8.1
@@ -16039,6 +16463,12 @@ snapshots:
 
   mute-stream@0.0.7: {}
 
+  mz@2.7.0:
+    dependencies:
+      any-promise: 1.3.0
+      object-assign: 4.1.1
+      thenify-all: 1.6.0
+
   nan@2.22.0:
     optional: true
 
@@ -16235,6 +16665,13 @@ snapshots:
 
   node-domexception@1.0.0: {}
 
+  node-emoji@2.1.3:
+    dependencies:
+      '@sindresorhus/is': 4.6.0
+      char-regex: 1.0.2
+      emojilib: 2.4.0
+      skin-tone: 2.0.0
+
   node-fetch-native@1.6.4: {}
 
   node-fetch@2.7.0:
@@ -16572,6 +17009,14 @@ snapshots:
 
   parse-ms@3.0.0: {}
 
+  parse5-htmlparser2-tree-adapter@6.0.1:
+    dependencies:
+      parse5: 6.0.1
+
+  parse5@5.1.1: {}
+
+  parse5@6.0.1: {}
+
   parseurl@1.3.3: {}
 
   pascal-case@3.1.2:
@@ -16579,8 +17024,6 @@ snapshots:
       no-case: 3.0.4
       tslib: 2.8.0
 
-  path-browserify@1.0.1: {}
-
   path-exists@4.0.0: {}
 
   path-exists@5.0.0: {}
@@ -16657,6 +17100,8 @@ snapshots:
       sonic-boom: 4.2.0
       thread-stream: 3.1.0
 
+  pirates@4.0.6: {}
+
   pkg-dir@4.2.0:
     dependencies:
       find-up: 4.1.0
@@ -16697,6 +17142,14 @@ snapshots:
       postcss: 8.4.47
       ts-node: 10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)
 
+  postcss-load-config@6.0.1(jiti@2.3.3)(postcss@8.4.47)(yaml@2.6.0):
+    dependencies:
+      lilconfig: 3.1.2
+    optionalDependencies:
+      jiti: 2.3.3
+      postcss: 8.4.47
+      yaml: 2.6.0
+
   postcss-safe-parser@6.0.0(postcss@8.4.47):
     dependencies:
       postcss: 8.4.47
@@ -17344,11 +17797,6 @@ snapshots:
 
   resolve-from@5.0.0: {}
 
-  resolve@1.19.0:
-    dependencies:
-      is-core-module: 2.15.1
-      path-parse: 1.0.7
-
   resolve@1.22.8:
     dependencies:
       is-core-module: 2.15.1
@@ -17613,6 +18061,10 @@ snapshots:
       mrmime: 2.0.0
       totalist: 3.0.1
 
+  skin-tone@2.0.0:
+    dependencies:
+      unicode-emoji-modifier-base: 1.0.0
+
   slash@3.0.0: {}
 
   slash@4.0.0: {}
@@ -17889,6 +18341,16 @@ snapshots:
 
   stylis@4.3.2: {}
 
+  sucrase@3.35.0:
+    dependencies:
+      '@jridgewell/gen-mapping': 0.3.5
+      commander: 4.1.1
+      glob: 10.4.5
+      lines-and-columns: 1.2.4
+      mz: 2.7.0
+      pirates: 4.0.6
+      ts-interface-checker: 0.1.13
+
   supports-color@5.5.0:
     dependencies:
       has-flag: 3.0.0
@@ -17908,6 +18370,11 @@ snapshots:
       has-flag: 4.0.0
       supports-color: 7.2.0
 
+  supports-hyperlinks@3.1.0:
+    dependencies:
+      has-flag: 4.0.0
+      supports-color: 7.2.0
+
   supports-preserve-symlinks-flag@1.0.0: {}
 
   svelte-check@3.8.6(@babel/core@7.25.9)(postcss-load-config@3.1.4(postcss@8.4.47)(ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3)))(postcss@8.4.47)(svelte@5.1.4):
@@ -18079,6 +18546,14 @@ snapshots:
 
   text-table@0.2.0: {}
 
+  thenify-all@1.6.0:
+    dependencies:
+      thenify: 3.3.1
+
+  thenify@3.3.1:
+    dependencies:
+      any-promise: 1.3.0
+
   thread-stream@3.1.0:
     dependencies:
       real-require: 0.2.0
@@ -18175,6 +18650,8 @@ snapshots:
     dependencies:
       punycode: 2.3.1
 
+  tree-kill@1.2.2: {}
+
   trim-lines@3.0.1: {}
 
   trim-repeated@1.0.0:
@@ -18193,6 +18670,8 @@ snapshots:
     dependencies:
       typescript: 5.6.3
 
+  ts-interface-checker@0.1.13: {}
+
   ts-node@10.9.2(@swc/core@1.7.39)(@types/node@20.17.0)(typescript@5.6.3):
     dependencies:
       '@cspotcode/source-map-support': 0.8.1
@@ -18226,6 +18705,35 @@ snapshots:
 
   tslib@2.8.0: {}
 
+  tsup@8.3.5(@microsoft/api-extractor@7.48.0(@types/node@20.17.0))(@swc/core@1.7.39)(jiti@2.3.3)(postcss@8.4.47)(typescript@5.6.3)(yaml@2.6.0):
+    dependencies:
+      bundle-require: 5.0.0(esbuild@0.24.0)
+      cac: 6.7.14
+      chokidar: 4.0.1
+      consola: 3.2.3
+      debug: 4.3.7(supports-color@9.4.0)
+      esbuild: 0.24.0
+      joycon: 3.1.1
+      picocolors: 1.1.1
+      postcss-load-config: 6.0.1(jiti@2.3.3)(postcss@8.4.47)(yaml@2.6.0)
+      resolve-from: 5.0.0
+      rollup: 4.24.0
+      source-map: 0.8.0-beta.0
+      sucrase: 3.35.0
+      tinyexec: 0.3.1
+      tinyglobby: 0.2.9
+      tree-kill: 1.2.2
+    optionalDependencies:
+      '@microsoft/api-extractor': 7.48.0(@types/node@20.17.0)
+      '@swc/core': 1.7.39
+      postcss: 8.4.47
+      typescript: 5.6.3
+    transitivePeerDependencies:
+      - jiti
+      - supports-color
+      - tsx
+      - yaml
+
   tsutils@3.21.0(typescript@5.6.3):
     dependencies:
       tslib: 1.14.1
@@ -18321,6 +18829,8 @@ snapshots:
 
   typescript@5.4.2: {}
 
+  typescript@5.6.1-rc: {}
+
   typescript@5.6.3: {}
 
   uc.micro@2.1.0: {}
@@ -18363,6 +18873,8 @@ snapshots:
 
   unicode-canonical-property-names-ecmascript@2.0.1: {}
 
+  unicode-emoji-modifier-base@1.0.0: {}
+
   unicode-match-property-ecmascript@2.0.0:
     dependencies:
       unicode-canonical-property-names-ecmascript: 2.0.1
@@ -18534,7 +19046,7 @@ snapshots:
     dependencies:
       builtins: 5.1.0
 
-  validator@13.12.0: {}
+  validate-npm-package-name@5.0.1: {}
 
   vary@1.1.2: {}
 
@@ -18567,23 +19079,6 @@ snapshots:
       - supports-color
       - terser
 
-  vite-plugin-dts@3.9.1(@types/node@20.17.0)(rollup@4.24.0)(typescript@5.6.3)(vite@5.4.10(@types/node@20.17.0)(terser@5.36.0)):
-    dependencies:
-      '@microsoft/api-extractor': 7.43.0(@types/node@20.17.0)
-      '@rollup/pluginutils': 5.1.3(rollup@4.24.0)
-      '@vue/language-core': 1.8.27(typescript@5.6.3)
-      debug: 4.3.7(supports-color@9.4.0)
-      kolorist: 1.8.0
-      magic-string: 0.30.12
-      typescript: 5.6.3
-      vue-tsc: 1.8.27(typescript@5.6.3)
-    optionalDependencies:
-      vite: 5.4.10(@types/node@20.17.0)(terser@5.36.0)
-    transitivePeerDependencies:
-      - '@types/node'
-      - rollup
-      - supports-color
-
   vite-plugin-prismjs@0.0.11(prismjs@1.29.0):
     dependencies:
       '@babel/core': 7.25.9
@@ -18665,18 +19160,6 @@ snapshots:
 
   vscode-textmate@8.0.0: {}
 
-  vue-template-compiler@2.7.16:
-    dependencies:
-      de-indent: 1.0.2
-      he: 1.2.0
-
-  vue-tsc@1.8.27(typescript@5.6.3):
-    dependencies:
-      '@volar/typescript': 1.11.1
-      '@vue/language-core': 1.8.27(typescript@5.6.3)
-      semver: 7.6.3
-      typescript: 5.6.3
-
   w3c-keyname@2.2.8: {}
 
   wait-port@1.1.0:
@@ -18974,8 +19457,20 @@ snapshots:
 
   yaml@2.6.0: {}
 
+  yargs-parser@20.2.9: {}
+
   yargs-parser@21.1.1: {}
 
+  yargs@16.2.0:
+    dependencies:
+      cliui: 7.0.4
+      escalade: 3.2.0
+      get-caller-file: 2.0.5
+      require-directory: 2.1.1
+      string-width: 4.2.3
+      y18n: 5.0.8
+      yargs-parser: 20.2.9
+
   yargs@17.7.2:
     dependencies:
       cliui: 8.0.1
@@ -18997,14 +19492,6 @@ snapshots:
 
   yocto-queue@1.1.1: {}
 
-  z-schema@5.0.5:
-    dependencies:
-      lodash.get: 4.4.2
-      lodash.isequal: 4.5.0
-      validator: 13.12.0
-    optionalDependencies:
-      commander: 9.5.0
-
   zimmerframe@1.1.2: {}
 
   zip-stream@6.0.1:
diff --git a/browser/react/README.md b/browser/react/README.md
index af27cab24..e079a8975 100644
--- a/browser/react/README.md
+++ b/browser/react/README.md
@@ -3,9 +3,9 @@
 A library for viewing and creating Atomic Data.
 Re-exports `@tomic/lib`.
 
-[**demo + template on codesandbox**!](https://codesandbox.io/s/atomic-data-react-template-4y9qu?file=/src/MyResource.tsx:0-1223)
+[**docs**](https://docs.atomicdata.dev/usecases/react)
 
-[**docs**](https://atomic-lib.netlify.app/modules/_tomic_react)
+[**demo + template on codesandbox**!](https://codesandbox.io/s/atomic-data-react-template-4y9qu?file=/src/MyResource.tsx:0-1223)
 
 ## Setup
 
@@ -15,43 +15,44 @@ Wrap your App in a `StoreContext.Provider`, and pass the newly initialized store
 ```ts
 // App.tsx
 import { StoreContext, Store } from "@tomic/react";
-import { MyResource } from "./MyResource";
 
 // The store contains all the data for
-const store = new Store();
+const store = new Store({
+  serverUrl: 'https://my-atomic-server.com',
+});
 
 export default function App() {
   return (
     <StoreContext.Provider value={store}>
-      <MyResource subject={subject} />
+      // The rest of your app
     </StoreContext.Provider>
   );
 }
 ```
 
-Now, your Store can be accessed in React's context, which you can use the `atomic-react` hooks!
+Now, your Store can be accessed in React's context allowing you to use our hooks!
 
 ## Hooks
 
-### useResource, useString, useTitle
+```tsx
+import { useResource, useString, core } from "@tomic/react";
 
-```ts
-// Get the Resouce, and all its properties
-const resource = useResource('https://atomicdata.dev/classes/Agent');
-// The title takes either the Title, the Shortname or the URL of the resource
-const title = useTitle(resource);
-// All useValue / useString / useArray / useBoolean hooks have a getter and a setter.
-// Use the setter in forms.
-const [description, setDescription] = useString(resource, 'https://atomicdata.dev/properties/description');
-// The current Agent is the signed in user, inluding their private key. This enables you to create Commits and update data on a server.
-const [agent, setAgent] = useCurrentAgent();
-
-return (
-  <>
-    <h1>{title}</h2>
-    <textarea value={description} onChange={e => setDescription(e.target.value)} />
-    <button type={button} onClick={resource.save}>Save & commit</button>
-  </>
-)
+const SomeComponent = () => {
+  // Get the Resouce, and all its properties
+  const resource = useResource('https://atomicdata.dev/classes/Agent');
+  // All useValue / useString / useArray / useBoolean hooks have a getter and a setter.
+  const [description, setDescription] = useString(resource, core.properties.description);
+
+  return (
+    <>
+      <h1>{resource.title}</h2>
+      <textarea value={description} onChange={e => setDescription(e.target.value)} />
+      <button type={button} onClick={resource.save}>Save & commit</button>
+    </>
+  )
+}
 
 ```
+
+There are a lot more hooks and helpers available.
+See the [docs](https://docs.atomicdata.dev/usecases/react) for more information.
diff --git a/browser/react/package.json b/browser/react/package.json
index 63c94d8a3..05f7d134d 100644
--- a/browser/react/package.json
+++ b/browser/react/package.json
@@ -1,41 +1,67 @@
 {
+  "name": "@tomic/react",
   "version": "0.40.0",
   "author": "Joep Meindertsma",
   "description": "Atomic Data React library",
+  "homepage": "https://docs.atomicdata.dev/usecases/react",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/atomicdata-dev/atomic-server.git"
+  },
+  "bugs": {
+    "url": "https://github.com/atomicdata-dev/atomic-server/issues"
+  },
   "dependencies": {
     "@tomic/lib": "workspace:*"
   },
   "devDependencies": {
+    "@arethetypeswrong/cli": "^0.17.0",
     "@types/react": "^18.3.12",
     "@types/react-dom": "^18.3.1",
     "@types/react-router-dom": "^5.3.3",
+    "tsup": "^8.3.5",
     "typescript": "^5.6.3"
   },
   "peerDependencies": {
-    "react": ">17.0.2"
+    "react": ">18.3.0"
   },
   "files": [
-    "dist"
+    "dist",
+    "!dist/**/*.d.ts.map"
   ],
   "license": "MIT",
-  "name": "@tomic/react",
+  "exports": {
+    ".": {
+      "import": {
+        "types": "./dist/src/index.d.ts",
+        "default": "./dist/index.js"
+      },
+      "require": {
+        "types": "./dist/src/index.d.cts",
+        "default": "./dist/index.cjs"
+      }
+    },
+    "./package.json": "./package.json"
+  },
   "main-dev": "src/index.ts",
-  "main": "dist/src/index.js",
+  "types": "dist/src/index.d.ts",
+  "main": "dist/index.cjs",
+  "module": "dist/index.js",
+  "source": "src/index.ts",
+  "type": "module",
   "publishConfig": {
     "access": "public"
   },
   "scripts": {
-    "build": "tsc",
+    "build": "tsup",
     "lint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
     "lint-fix": "eslint ./src --ext .js,.jsx,.ts,.tsx --fix",
-    "prepublishOnly": "pnpm run lint-fix && pnpm run build",
+    "lint-package": "pnpm attw && pnpm publint",
+    "prepublishOnly": "pnpm run lint && pnpm run build && pnpm run lint-package",
     "start": "pnpm watch",
-    "watch": "tsc --build --watch",
-    "tsc": "tsc --build",
-    "typecheck": "pnpm exec tsc --noEmit"
-  },
-  "source": "src/index.ts",
-  "type": "module",
-  "types": "dist/src/index.d.ts",
-  "gitHead": "2172c73d8df4e5f273e6386676abc91b6c5b2707"
+    "watch": "tsup --watch",
+    "typecheck": "pnpm exec tsc --noEmit",
+    "publint": "pnpm dlx publint",
+    "attw": "pnpm exec attw $(pnpm pack)"
+  }
 }
diff --git a/browser/react/src/hooks.ts b/browser/react/src/hooks.ts
index 3b5599a4f..28e74538a 100644
--- a/browser/react/src/hooks.ts
+++ b/browser/react/src/hooks.ts
@@ -58,7 +58,7 @@ export function useResource<C extends OptionalClass = never>(
   return resource;
 }
 
-const stableEmptyArray = [];
+const stableEmptyArray: string[] = [];
 
 /**
  * Converts an array of Atomic URL strings to an array of Resources.
@@ -75,7 +75,7 @@ export function useResources(
     // When a change happens, set the new Resource.
     function handleNotify(updated: Resource) {
       setResources(prev => {
-        prev.set(updated.getSubject(), proxyResource(updated));
+        prev.set(updated.subject, proxyResource(updated));
 
         // We need to create new Maps for react hooks to update - React only checks references, not content
         return new Map(prev);
diff --git a/browser/react/src/useChildren.ts b/browser/react/src/useChildren.ts
index e94bac37e..e797831d9 100644
--- a/browser/react/src/useChildren.ts
+++ b/browser/react/src/useChildren.ts
@@ -1,4 +1,3 @@
-// Sorry for the name of this
 import { Resource } from '@tomic/lib';
 import { useEffect, useState } from 'react';
 
diff --git a/browser/react/tsconfig.json b/browser/react/tsconfig.json
index efb6b93e8..dd42ab894 100644
--- a/browser/react/tsconfig.json
+++ b/browser/react/tsconfig.json
@@ -1,24 +1,14 @@
 {
-    "extends": "../tsconfig.build.json",
-    "compilerOptions": {
-        "composite": true,
-        "outDir": "./dist",
-        "lib": [
-            "ES6",
-            "ES7",
-            "ESNext",
-            "DOM"
-        ],
-        "rootDir": ".",
-        "jsx": "react",
-        "module": "NodeNext"
-    },
-    "include": [
-        "./src"
-    ],
-    "references": [
-        {
-            "path": "../lib"
-        }
-    ]
+  "extends": "../tsconfig.build.json",
+  "compilerOptions": {
+    "declaration": true,
+    "declarationMap": true,
+    "outDir": "./dist",
+    "lib": ["ES6", "ES7", "ESNext", "DOM"],
+    "rootDir": ".",
+    "jsx": "react",
+    "module": "NodeNext",
+    "moduleResolution": "NodeNext"
+  },
+  "include": ["src/**/*"]
 }
diff --git a/browser/react/tsup.config.ts b/browser/react/tsup.config.ts
new file mode 100644
index 000000000..53297c271
--- /dev/null
+++ b/browser/react/tsup.config.ts
@@ -0,0 +1,33 @@
+/// <reference types="node" />
+import { defineConfig } from 'tsup';
+import * as fs from 'node:fs/promises';
+import { exec } from 'node:child_process';
+
+export default defineConfig(options => ({
+  minify: !options.watch,
+  entry: ['src/index.ts'],
+  sourcemap: true,
+  clean: true,
+  format: ['esm', 'cjs'],
+  target: 'es2023',
+  // We need to generate the type definition files ourselves because the build in rollup dts plugin does not work with the way we use module augmentation.
+  // Tsup will switch to microsoft-api-extractor in the future but they don't even support rolling up module augments at all. https://github.com/microsoft/rushstack/issues/1709
+  onSuccess: async () => {
+    console.log('Generating type definition files...');
+
+    // Run the typescript compiler but only emit declaration files.
+    exec('tsc --emitDeclarationOnly --declaration', (err, stdout, stderr) => {
+      if (err || stderr) {
+        console.error(err ?? stderr);
+      }
+
+      // We need a copy of index.d.ts for cjs builds but the actual content can be the same so we can just copy it.
+      console.log('Creating index.d.cts...');
+      fs.copyFile('dist/src/index.d.ts', 'dist/src/index.d.cts')
+        .then(() => {
+          console.log('Build Finished!');
+        })
+        .catch(console.error);
+    });
+  },
+}));
diff --git a/browser/svelte/package.json b/browser/svelte/package.json
index dc3d3f7bf..da58c2cb6 100644
--- a/browser/svelte/package.json
+++ b/browser/svelte/package.json
@@ -3,6 +3,14 @@
   "name": "@tomic/svelte",
   "version": "0.40.0",
   "license": "MIT",
+  "homepage": "https://docs.atomicdata.dev/svelte",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/atomicdata-dev/atomic-server.git"
+  },
+  "bugs": {
+    "url": "https://github.com/atomicdata-dev/atomic-server/issues"
+  },
   "private": false,
   "publishConfig": {
     "access": "public"
@@ -13,7 +21,8 @@
     "build": "vite build && pnpm run package",
     "build:watch": "vite build --watch",
     "preview": "vite preview",
-    "package": "svelte-kit sync && svelte-package && publint",
+    "package": "svelte-kit sync && svelte-package && pnpm dlx publint",
+    "lint-package": "pnpm run package",
     "prepublishOnly": "pnpm run package",
     "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
     "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
diff --git a/browser/tsconfig.build.json b/browser/tsconfig.build.json
index 5fd88634b..3dc3550ac 100644
--- a/browser/tsconfig.build.json
+++ b/browser/tsconfig.build.json
@@ -1,43 +1,18 @@
 {
   "compilerOptions": {
-    "target": "ES5",
-    "module": "ES2022",
-    "lib": [
-      // Not sure if DOM should be here. Lib should also work without a browser!
-      "DOM",
-      "ES6",
-      "ES7",
-      "ESNext"
-    ],
-    // Enforces `.js` relative imports, which is needed because tsc doesn't update filenames
-    "moduleResolution": "nodeNext",
+    "target": "ES2023",
+    "lib": ["DOM", "ES6", "ES7", "ESNext"],
     "esModuleInterop": true,
     "allowSyntheticDefaultImports": true,
     "jsx": "preserve",
     "strictFunctionTypes": true,
     "sourceMap": true,
     "declaration": true,
-    // Enables following definitions to source files instead of d.ts files
-    "declarationMap": true,
-    // used in monorepo ts projects to set precedence in compiling tsc things https://dev.to/t7yang/typescript-yarn-workspace-monorepo-1pao
-    "composite": true,
     "strictNullChecks": true,
-    // Todo: enable this
-    // "noImplicitAny": true
+    "noImplicitAny": true,
     "downlevelIteration": true,
     // Prevent typecheck to fail if some library is doing something wrong
     "skipLibCheck": true
   },
-  "exclude": [
-    "node_modules",
-    "**/node_modules/*"
-  ],
-  "references": [
-    {
-      "path": "lib"
-    },
-    {
-      "path": "react"
-    }
-  ]
+  "exclude": ["node_modules", "**/node_modules/*"]
 }
diff --git a/browser/tsconfig.json b/browser/tsconfig.json
index 8174ed9d2..5277c8b29 100644
--- a/browser/tsconfig.json
+++ b/browser/tsconfig.json
@@ -1,23 +1,4 @@
 {
-    "compilerOptions": {
-        "paths": {
-            "@tomic/lib/*": [
-                "./lib/src/*"
-            ],
-            "@tomic/react/*": [
-                "./react/src/*"
-            ]
-        },
-    },
-    "files": [],
-    "references": [
-        {
-            "path": "lib"
-        },
-        {
-            "path": "react"
-        }
-    ],
     "exclude": [
         "create-template/templates/**/*"
     ]
diff --git a/docs/src/js-cli.md b/docs/src/js-cli.md
index 9c1188778..c5a8f6abf 100644
--- a/docs/src/js-cli.md
+++ b/docs/src/js-cli.md
@@ -22,7 +22,7 @@ const comments = myBlogpost.props.comments; // string[] automatically inferred!
 
 You can install the package globally or as a dev dependency of your project.
 
-**Globally**:
+#### Globally
 
 ```
 npm install -g @tomic/cli
@@ -34,7 +34,7 @@ You should now be able to run:
 ad-generate
 ```
 
-**Dev Dependency:**
+#### Dev Dependency
 
 ```
 npm install -D @tomic/cli
@@ -46,6 +46,14 @@ To run:
 npx ad-generate
 ```
 
+Or add it to your `package.json` scripts:
+
+```json
+"scripts": {
+  "update-ontologies": "ad-generate ontologies"
+}
+```
+
 ### Generating the files
 
 To start generating your ontologies you first need to configure the cli. Start by creating the config file by running:
@@ -90,7 +98,7 @@ If everything went well the generated files should now be in the output folder.
 In order to gain the benefit of the typings we will need to annotate our resource with its respective class as follows:
 
 ```typescript
-import { Book, creativeWorks } from './ontologies/creativeWorks.js';
+import { type Book, creativeWorks } from './ontologies/creativeWorks.js';
 
 const book = await store.getResourceAsync<Book>(
   'https://mybookstore.com/books/1',
@@ -149,7 +157,7 @@ interface AtomicConfig {
 
   /**
    * [OPTIONAL] The @tomic/lib module identifier.
-   * The default should be sufficient in most but if you have given the module an alias you should change this value
+   * The default should be sufficient in most cases but if you have given the module an alias you should change this value
    */
   moduleAlias?: string;
 
@@ -164,4 +172,4 @@ interface AtomicConfig {
 }
 ```
 
-Running `ad-generate init` will create this file for you that you can then tweak to your own preferences.
+Running `ad-generate init` will create this file for you which you can then tweak to your own preferences.
diff --git a/docs/src/js.md b/docs/src/js.md
index defbd88aa..68ec9c045 100644
--- a/docs/src/js.md
+++ b/docs/src/js.md
@@ -75,6 +75,5 @@ const unsub = store.subscribe('https://my-atomic-server.dev/some-resource', reso
 ## What's next?
 
 Next check out [Store](./js-lib/store.md) to learn how to set up a store and fetch data.
-Or read the [Generated Typedocs](https://atomic-lib.netlify.app/modules/_tomic_lib)
 
-If you rather want to see a step-by-step guide on how to use the library in a project check out the [Astro + AtomicServer Guide](<javascript:alert('TODO: Add link');>)
+If you rather want to see a step-by-step guide on how to use the library in a project check out the [Astro + AtomicServer Guide](astro-guide/1-index.md)


Test patch:
diff --git a/browser/lib/vite.config.ts b/browser/lib/vitest.config.ts
similarity index 54%
rename from browser/lib/vite.config.ts
rename to browser/lib/vitest.config.ts
index a7b434017..56f571f52 100644
--- a/browser/lib/vite.config.ts
+++ b/browser/lib/vitest.config.ts
@@ -1,20 +1,15 @@
 import { defineConfig } from 'vite';
-import path from 'path';
-import dts from 'vite-plugin-dts';
+import path from 'node:path';
 
 export default defineConfig({
-  plugins: [dts()],
   server: {
     port: 5175,
   },
   build: {
-    manifest: true,
-    minify: true,
-    reportCompressedSize: true,
     lib: {
       entry: path.resolve(__dirname, 'src/index.ts'),
       fileName: 'index',
-      formats: ['es', 'cjs'],
     },
+    rollupOptions: {},
   },
 });