Skip to content

Code Style

Imports follow a strict order, separated by blank lines:

// 1. Type-only imports
import type { Foo } from './types'
// 2. External packages
import { useState } from 'react'
// 3. Internal packages
import { hash } from '@xnet/crypto'
// 4. Local relative imports
import { helper } from './utils'
CategoryConventionExample
FunctionscamelCase, verb-firstcreateNode, verifySignature
TypesPascalCaseNodeStore, SyncStatus
ConstantsSCREAMING_SNAKEMAX_UPDATE_SIZE, DEFAULT_TTL
ClassesPascalCaseSpatialIndex, Viewport
Type parametersSingle uppercaseT, P
Unused parametersPrefix with __event, _unused
  • Strict mode enabled — no implicit any, strict null checks
  • Prefer type over interface for object shapes
  • Explicit return types on exported functions
  • Template literal types for branded strings: `xnet://${string}/`
  • No any without justification — use unknown instead
  • Named exports only — no default exports
  • Barrel files (index.ts) re-export from internal modules
  • Export types inline: export { fn, type FnResult }
  • Factory functions alongside classes: createFoo() next to class Foo
/**
* @xnet/sync - Unified sync primitives for xNet
*/
// ─── Section Name ────────────────────────────────────────
/**
* Create a signed envelope for a Yjs update.
* @example
* const envelope = signYjsUpdate(update, did, key, clientId)
*/
  • Return { valid: boolean, errors: [] } for validation — don’t throw
  • Try-catch with type narrowing: err instanceof Error ? err : new Error(String(err))
  • Early returns for edge cases
  • Boolean returns for simple success/failure
  • Return typed objects from hooks (not tuples)
  • Use refs for values accessed in callbacks (avoid stale closures)
  • Always return cleanup functions from useEffect
  • Debug logging via localStorage: localStorage.getItem('xnet:sync:debug')
  • Prefer Tailwind over custom CSS