npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@weaverse/schema

v0.13.1

Published

Schema definitions for Weaverse

Readme

@weaverse/schema

This package provides Zod-based schema definitions for Weaverse components, ensuring type safety and validation across the Weaverse ecosystem.

Overview

The schema package defines the structure and validation rules for:

  • Input types (text, image, video, etc.)
  • Component schemas (title, type, settings, inspector groups)
  • Configuration options for various input types
  • Page types and component enablement rules

Key Types

Input Types

The package supports the following input types:

  • heading - Section headings (label only, no data binding)
  • text, textarea, richtext - Text inputs
  • url - URL inputs
  • image, video - Media inputs
  • switch - Boolean toggles
  • range - Numeric ranges with min/max/step
  • select, toggle-group - Choice inputs
  • product, product-list, collection, collection-list, blog, metaobject - Shopify resources
  • color, datepicker, map-autocomplete, position - Specialized inputs

Core Schemas

// Basic input for data-bound fields
export type BasicInput = {
  type: InputType
  name: string
  label?: string
  placeholder?: string
  helpText?: string
  configs?: ConfigsProps
  shouldRevalidate?: boolean
  condition?: string
  defaultValue?: string | number | boolean | Record<string, unknown> | unknown
}

// Heading input for non-data-bound labels
export type HeadingInput = {
  type: 'heading'
  label: string
  [key: string]: any
}

// Inspector group containing inputs
export type InspectorGroup = {
  group: string
  inputs: (BasicInput | HeadingInput)[]
}

// Element schema for components
export type ElementSchema = {
  title: string
  type: string
  limit?: number
  inspector?: InspectorGroup[] // @deprecated Use settings instead
  settings?: InspectorGroup[]
  childTypes?: string[]
  /** @deprecated Use enabled instead. */
  enabledOn?: {
    pages?: ('*' | PageType)[]
    groups?: ('*' | 'header' | 'footer' | 'body')[]
  }
  enabled?: Resolvable<boolean, ComponentAvailabilityContext>
  presets?: {
    children?: Array<{ type: string; [key: string]: any }>
    [key: string]: any
  }
}

Usage with @weaverse/hydrogen

The hydrogen package extends these base schemas with additional functionality:

import type { BasicInput, HeadingInput, InspectorGroup } from '@weaverse/schema'

// Hydrogen extends the base types with runtime capabilities
export type HydrogenBasicInput = BasicInput & {
  // Additional hydrogen-specific properties
}

// Components use the schema types for type safety
export const myComponent: HydrogenComponent = {
  schema: {
    title: 'My Component',
    type: 'my-component',
    settings: [
      {
        group: 'Settings',
        inputs: [
          {
            type: 'text',
            name: 'title',
            label: 'Title',
            defaultValue: 'Hello World'
          }
        ]
      }
    ]
  }
}

Enhanced API Features

Structured Validation Results

The enhanced validation system provides detailed error information:

import { validateSchema, parseSchema, isValidSchema } from '@weaverse/schema'

// Get detailed validation results
const result = validateSchema(mySchema)
if (!result.success) {
  result.issues.forEach(issue => {
    console.log(`Error: ${issue.message}`)
    if (issue.path) {
      console.log(`At: ${issue.path.join('.')}`)
    }
    if (issue.expected) {
      console.log(`Expected: ${JSON.stringify(issue.expected)}`)
    }
  })
}

// Parse with throwing on errors
try {
  const validSchema = parseSchema(unknownData)
} catch (error) {
  console.error('Schema validation failed:', error.message)
}

// Simple validation check
if (isValidSchema(data)) {
  // TypeScript knows data is SchemaType
  console.log(data.title)
}

Context-aware component availability

Use enabled when availability depends on the current page or placement group:

import { createSchema } from '@weaverse/schema'

const schema = createSchema({
  title: 'Freebies',
  type: 'freebies',
  enabled: ({ page, group }) =>
    page.type === 'CUSTOM' &&
    page.handle === 'freebies/essential' &&
    group === 'body',
})

enabled accepts a boolean or a synchronous callback. The callback receives page (id, type, handle, and locale) and group (body, header, or footer). The SDK preserves callbacks without executing them; the Weaverse preview bridge evaluates them against its current page context.

enabledOn is deprecated. Move its page and group checks into enabled:

// Before
const legacy = createSchema({
  title: 'Product recommendations',
  type: 'product-recommendations',
  enabledOn: { pages: ['PRODUCT'], groups: ['body'] },
})

// After
const current = createSchema({
  title: 'Product recommendations',
  type: 'product-recommendations',
  enabled: ({ page, group }) => page.type === 'PRODUCT' && group === 'body',
})

Schema Builder Pattern

Create schemas fluently with the builder pattern:

import { schemaBuilder, inputHelpers, groupHelpers } from '@weaverse/schema'

const schema = schemaBuilder()
  .title('Product Card')
  .type('product-card')
  .limit(10)
  .addSetting(
    groupHelpers.content([
      inputHelpers.text('title', 'Product Title'),
      inputHelpers.textarea('description', 'Product Description'),
      inputHelpers.image('image', 'Product Image')
    ])
  )
  .addSetting(
    groupHelpers.style([
      inputHelpers.select('layout', 'Layout', [
        { label: 'Card', value: 'card' },
        { label: 'List', value: 'list' }
      ]),
      inputHelpers.switch('showPrice', 'Show Price', true)
    ])
  )
  .enabled(({ page, group }) =>
    ['PRODUCT', 'COLLECTION'].includes(page.type) && group === 'body'
  )
  .build()

Input Helpers

Create common inputs easily:

import { inputHelpers } from '@weaverse/schema'

// Text inputs
const titleInput = inputHelpers.text('title', 'Title', {
  placeholder: 'Enter title...',
  helpText: 'This will be displayed as the main heading'
})

// Range inputs with configuration
const paddingInput = inputHelpers.range('padding', 'Padding', {
  min: 0,
  max: 100,
  step: 5,
  unit: 'px'
})

// Select inputs with options
const alignmentInput = inputHelpers.select('alignment', 'Text Alignment', [
  { label: 'Left', value: 'left' },
  { label: 'Center', value: 'center' },
  { label: 'Right', value: 'right' }
])

// Switch with default value
const visibleInput = inputHelpers.switch('visible', 'Visible', true)

// Heading separators
const sectionHeading = inputHelpers.heading('Advanced Settings')

Group Helpers

Create common setting groups:

import { groupHelpers, inputHelpers } from '@weaverse/schema'

const contentGroup = groupHelpers.content([
  inputHelpers.text('title'),
  inputHelpers.textarea('description'),
  inputHelpers.image('backgroundImage')
])

const layoutGroup = groupHelpers.layout([
  inputHelpers.range('columns', 'Columns', { min: 1, max: 4 }),
  inputHelpers.select('spacing', 'Spacing', [
    { label: 'Small', value: 'sm' },
    { label: 'Medium', value: 'md' },
    { label: 'Large', value: 'lg' }
  ])
])

const styleGroup = groupHelpers.style([
  inputHelpers.heading('Colors'),
  inputHelpers.text('backgroundColor', 'Background Color'),
  inputHelpers.text('textColor', 'Text Color')
])

Schema Composition

Merge and extend existing schemas:

import { mergeSchemas, createSchema } from '@weaverse/schema'

const baseCardSchema = createSchema({
  title: 'Base Card',
  type: 'base-card',
  settings: [
    groupHelpers.content([
      inputHelpers.text('title'),
      inputHelpers.textarea('description')
    ])
  ]
})

const productCardSchema = mergeSchemas(baseCardSchema, {
  title: 'Product Card',
  type: 'product-card',
  settings: [
    groupHelpers.content([
      inputHelpers.image('productImage'),
      inputHelpers.switch('showPrice', 'Show Price', true)
    ])
  ]
})

Schema Registry

Manage multiple schemas centrally:

import { schemaRegistry } from '@weaverse/schema'

// Register schemas
schemaRegistry.register('hero-banner', heroSchema)
schemaRegistry.register('product-card', productCardSchema)
schemaRegistry.register('testimonial', testimonialSchema)

// Retrieve schemas
const heroSchema = schemaRegistry.get('hero-banner')

// List all schemas
const allSchemas = schemaRegistry.list()

// Validate all registered schemas
const validation = schemaRegistry.validateAll()
console.log(`Valid schemas: ${validation.valid.length}`)
console.log(`Invalid schemas: ${validation.invalid.length}`)

Development Tools

Debug and analyze schemas:

import { devTools } from '@weaverse/schema'

// Analyze schema structure
const analysis = devTools.analyzeSchema(mySchema)
console.log(`Schema "${analysis.stats.title}" has ${analysis.stats.inputCount} inputs`)

// Pretty print for debugging
console.log(devTools.prettyPrint(mySchema))

// Generate TypeScript interface
const tsInterface = devTools.generateTypeInterface(mySchema)
console.log(tsInterface)
// Output:
// interface ProductCardProps {
//   title: string
//   description: string
//   showPrice?: boolean
//   layout: 'card' | 'list'
// }

Build-time component manifests

Use the build-only @weaverse/schema/manifest entrypoint to turn registered component modules into a deterministic artifact. This subpath is not re-exported by the normal Schema or Hydrogen runtime entries, so storefront bundles do not load the generator or its JSON Schema.

import { generateComponentManifest } from '@weaverse/schema/manifest'

let artifact = await generateComponentManifest(components, {
  source: {
    name: 'pilot',
    revision: process.env.GIT_SHA,
    version: '1.0.0',
  },
})

await writeFile('.weaverse/component-manifest.json', artifact.json)
console.log(artifact.hash) // sha256:...

The generator validates component schemas, rejects duplicate types, sorts components and free-form non-index object keys by deterministic UTF-16 code-unit order, preserves author-defined array order, uses ECMAScript's numeric ordering for array-index object keys, writes two-space JSON with one trailing newline, and hashes those exact UTF-8 bytes. It records loader presence but never runs loaders or schema callbacks. Function-based availability and setting conditions are represented as { dynamic: true } for later exact-runtime validation.

Mark sensitive or server-only settings whose values must not reach agent-facing artifacts:

{
  type: 'text',
  name: 'apiKey',
  label: 'API key',
  sensitive: true,
  defaultValue: '',
}

sensitive: true covers both secret values and server-only configuration. Those defaults are omitted from settings, presets, nested child presets, and representative examples. Generated artifacts contain schema contracts only; they never contain merchant values.

The version-one runtime validator and JSON Schema are exported as ComponentManifestSchema and componentManifestJsonSchema. Contract changes that would invalidate existing manifests require a new manifest version.

Type Safety

All types are inferred from Zod schemas, ensuring:

  • Runtime validation matches TypeScript types
  • Single source of truth for type definitions
  • Automatic type generation from schema changes
  • Context-aware component availability callbacks are preserved for preview-side evaluation

Development

# Install dependencies
pnpm install

# Build the package
pnpm run build

# Type check
pnpm run typecheck

Type Safety and Required Fields

Important Note on TypeScript Configuration

The title and type fields are required at runtime (enforced by Zod validation), but may appear as optional in TypeScript when strict mode is disabled.

Runtime Validation

createSchema() returns the original schema and reports validation issues in development. Use parseSchema() when invalid input must throw:

const schema = createSchema({
  title: 'My Component',
  type: 'my-component',
})

const validatedSchema = parseSchema(unknownSchema) // Throws on invalid input

TypeScript Type Safety

For better TypeScript type safety, you have several options:

Option 1: Use SchemaTypeStrict (Recommended)

import { createSchemaTypeSafe, type SchemaTypeStrict } from '@weaverse/schema'

const schema: SchemaTypeStrict = {
  title: 'My Component',    // Required (enforced by TypeScript)
  type: 'my-component',     // Required (enforced by TypeScript)
  settings: [
    // ... your settings
  ],
}

const validatedSchema = createSchemaTypeSafe(schema)

Option 2: Enable TypeScript Strict Mode

Add to your tsconfig.json:

{
  "compilerOptions": {
    "strict": true
  }
}

Option 3: Use the Standard Types (with runtime validation)

import { createSchema, type SchemaType } from '@weaverse/schema'

// TypeScript may not enforce required fields, but runtime validation will
const schema = createSchema({
  title: 'My Component',
  type: 'my-component',
})

API Reference

Types

  • SchemaType - Inferred type from ElementSchema (may show optional fields without strict mode)
  • SchemaTypeStrict - Explicit type with enforced required fields
  • BasicInput - Schema for basic input types
  • HeadingInput - Schema for heading inputs
  • InspectorGroup - Schema for inspector groups
  • PageType - Enum of available page types
  • ComponentPresets - Schema for component presets

Functions

  • createSchema(schema: SchemaType) - Returns a schema and schedules development-only validation
  • createSchemaTypeSafe(schema: SchemaTypeStrict) - Type-safe schema creation with enforced required fields

Schemas

  • ElementSchema - Main Zod schema for component definitions
  • BasicInputSchema - Schema for basic input types
  • HeadingInputSchema - Schema for heading inputs
  • InspectorGroupSchema - Schema for inspector groups

Migration from Previous Versions

The schema package is now the source of truth for all component schema types. The hydrogen package re-exports these types for backward compatibility.

Deprecated Fields

  • inspector is deprecated in favor of settings (both have the same structure)
  • enabledOn is deprecated in favor of enabled; move page and group checks into the callback

Type System Architecture

This package follows the Weaverse type hierarchy:

core → react → schema|hydrogen

Where:

  • @weaverse/schema is the source of truth for component schema types
  • @weaverse/hydrogen imports and re-exports schema types
  • All packages use Zod for runtime validation with TypeScript type inference

Contributing

Please ensure all schemas include proper validation rules and TypeScript types.