Relatude Help

TypeScript

The starter's tsconfig.json sets:

Option Why
"jsx": "react-jsx" TSX compiles to react/jsx-runtime, a shared module; no file imports React for JSX
"moduleResolution": "bundler" imports resolve as Vite resolves them; relative imports need no .js
"strict": true null checks and the other strict checks
"isolatedModules": true Vite compiles each file on its own; re-export a type with export type
"skipLibCheck": true the packages' declarations are not checked again
"lib": ["ES2022", "DOM", "DOM.Iterable"] the browser's APIs

The types come with the packages: BladeProps, PropertyEditorProps, CmsApi, NodeData and the rest from @relatude/sdk, component props from @relatude/ui, and React's from @types/react.

Vite strips types without checking them, so a type error never stops npm run dev or npm run build. Your editor marks errors as you type; run npm run typecheck before you build.

To read the site's content with types, describe the C# model's types by their CodeNames, with only the properties the plugin reads. A decimal is db.Decimal, and a relation end is db.One<T> or db.Many<T> (chapter 19):

import { useEffect, useState } from 'react';
import { db, useCms } from '@relatude/sdk';

interface IProductPage { Name: string; Price: db.Decimal; Stock: number }
const Product = db.nodeType<IProductPage>('IProductPage');

export function LowStock() {
  const { store } = useCms();
  const [rows, setRows] = useState<db.Node<IProductPage>[]>([]);
  useEffect(() => {
    store?.query(Product)
      .where(p => p.Stock.lt(5))
      .orderBy(p => p.Name)
      .page(0, 20)
      .execute()
      .then(result => setRows(result.items));
  }, [store]);
  return <ul>{rows.map(r => <li key={r.$id}>{r.Name}: {r.Stock}</li>)}</ul>;
}

The field handles are typed, so p.Stock.startsWith('a') does not compile, and a misspelt property is an error in your editor rather than in the query. store is null in the offline demo (?demo).