Hooks

useDocyrusDummyDataGeneratorWizard

One-call wiring of a Docyrus data source to the DummyDataGenerator — handles field-aware strategies, deterministic generation, preview, and batch insert in a single guided flow.

Installation

pnpm dlx @docyrus/cli add @docyrus/hooks-use-docyrus-dummy-data-generator-wizard
Required Packages(3 packages)
pnpm add @docyrus/app-utils @docyrus/api-client @tanstack/react-query

This hook is distributed as source. It needs an authenticated RestApiClient from @docyrus/api-client and a QueryClientProvider from @tanstack/react-query somewhere above your component tree.

Overview

useDocyrusDummyDataGeneratorWizard is the one-call entry point that wires a Docyrus data source to <DummyDataGenerator> and returns a ready-to-render wizard element plus an openWizard() trigger. The hook owns:

  • Field discovery — pass fields directly (e.g. from useDocyrusDataGrid) or let the hook fetch them via useDocyrusDataViewSelect.
  • Strategy seeding — every field gets a sensible default via inferStrategyForField. Users override per field on the configure step (text shape, number range, date window, enum subset, etc.).
  • Deterministic generation — Mulberry32 PRNG with a per-render seed. The same seed produces the same preview rows so the preview matches the inserted rows.
  • Preview rendering — uses useDocyrusFieldComponent(field.type, 'value-renderer') so every Docyrus field type (relation, money, phone, date, enum, multi-select, …) renders identically to <DataGrid>.
  • Batch insert — prefers collection.createMany({ records }) when available, then collection.create(row), then per-record client.post('/v1/apps/:app/data-sources/:ds/items', row). Override completely with insertRecords.

Backend connection

The hook posts each generated row to one endpoint (or batches via the supplied collection):

PhaseMethodEndpointPurpose
InsertPOST/v1/apps/:appSlug/data-sources/:dataSourceSlug/itemsOne call per generated row. Wrap with insertRecords to use a bulk endpoint instead.

Required fields are sourced from one of:

  1. fields option — pass the same DataSourceField[] you already use with useDocyrusDataGrid to skip an extra round-trip.
  2. Auto-load — when fields is omitted the hook composes useDocyrusDataViewSelect under the hood and reads dataSource.fields.

Usage

The hook returns an inline wizard element — drop it anywhere in the layout. Wrap it in your own dialog / drawer / sheet if you want modal behavior.

'use client';

import { useDocyrusAuth } from '@docyrus/signin';

import { useDocyrusDummyDataGeneratorWizard } from '@docyrus/ui/library/hooks/use-docyrus-dummy-data-generator-wizard';

export function ContactsSeederPanel({ onGenerated }: { onGenerated: () => void }) {
  const { client } = useDocyrusAuth();

  if (!client) return null;

  const { wizard } = useDocyrusDummyDataGeneratorWizard({
    client,
    appSlug: 'crm',
    dataSourceSlug: 'contact',
    defaultCount: 25,
    onGenerated: () => onGenerated()
  });

  return wizard;
}

Wrapping in a dialog

import { Dialog, DialogContent } from '@docyrus/ui/primitives/ui/dialog';

const [open, setOpen] = useState(false);
const { wizard } = useDocyrusDummyDataGeneratorWizard({
  client, appSlug, dataSourceSlug
});

return (
  <>
    <Button onClick={() => setOpen(true)}>Seed sample contacts…</Button>
    <Dialog open={open} onOpenChange={setOpen}>
      <DialogContent>{wizard}</DialogContent>
    </Dialog>
  </>
);

Side-by-side with useDocyrusDataGrid

Both hooks accept the same client + appSlug + dataSourceSlug. Wire onGenerated to the grid's reload() so newly inserted rows show up immediately:

const grid = useDocyrusDataGrid({ client, appSlug, dataSourceSlug });
const seeder = useDocyrusDummyDataGeneratorWizard({
  client,
  appSlug,
  dataSourceSlug,
  collection: grid.collection,         // bulk-insert via collection.createMany when available
  fields: grid.fields,                 // skip duplicate metadata fetch
  users: grid.users,                   // populate field-userSelect strategies
  onGenerated: () => grid.reload()
});

return (
  <>
    {grid.toolbar}
    <DataGrid table={grid.table} {...grid.gridProps} />
    {seeder.wizard}
  </>
);

Preview-only flow (no inserts)

const seeder = useDocyrusDummyDataGeneratorWizard({
  client,
  appSlug,
  dataSourceSlug,
  previewOnly: true,
  onGenerated: (_result, rows) => {
    download('seed.json', JSON.stringify(rows, null, 2));
  }
});

Custom batch endpoint

const seeder = useDocyrusDummyDataGeneratorWizard({
  client,
  appSlug,
  dataSourceSlug,
  insertRecords: async (rows) => {
    const response = await client.post(`/v1/apps/${appSlug}/data-sources/${dataSourceSlug}/items/bulk`, { records: rows });
    const errors = (response as { errors?: Array<{ index: number; message: string }> }).errors ?? [];

    return { errors: errors.map(e => ({ rowIndex: e.index, message: e.message })) };
  }
});

API Reference

Parameters

OptionTypeDefaultDescription
clientRestApiClient—Authenticated client from @docyrus/api-client. Required.
appSlugstring—Target app slug. Required.
dataSourceSlugstring—Target data source slug. Required.
appIdstring—Optional multi-tenant isolation key.
fieldsArray<DocyrusFieldLike>—Pre-resolved target fields. When provided, the hook skips its internal data source fetch.
requiredFieldSlugsArray<string>[]Slugs locked to enabled: true.
defaultCountnumber10Initial row count.
maxCountnumber1000UI hard cap.
previewRowCountnumber10Number of rows shown in the preview step.
collection{ create?, createMany? }—Optional collection wrapper. createMany is preferred over per-record create for batch inserts.
usersArray<DummyUserOption>—Tenant users used for field-userSelect / field-userMultiSelect strategies.
relationOptionsByFieldSlugRecord<string, Array<DummyRelationOption>>—Relation pool keyed by field slug. Without it, relation fields are skipped.
previewOnlybooleanfalseWhen true the preview-step CTA is "Finish" — the hook never POSTs anything.
enabledbooleantrueWhen false the hook returns wizard: null (use as a feature flag).
onGenerated(result, rows) => void—Called after the progress phase completes.
onError(error: Error, rowIndex: number) => void—Called whenever a per-row insert throws (default insertRecords only).
insertRecords(rows) => Promise<{ errors }>derivedOverride the per-row insert pipeline.
title / description / iconReactNode / ReactNode / stringtranslated defaultOverride the wizard header copy.
exportFileNamestring<dataSourceSlug>-dummy-dataFile name (without extension) for CSV / XLSX downloads.

Return Value

PropertyTypeDescription
wizardReactElement | nullInline wizard panel. Render it directly or wrap it in a dialog. null when enabled === false.
resetWizard() => voidReset the wizard back to the configure step (clears generated rows + result).
stepDummyDataGeneratorStepCurrent step.
setStep(step) => voidMove to a step programmatically.
count / setCountnumber / (next) => voidRow count + setter. Setter clamps to [1, maxCount].
strategies / setStrategiesDummyStrategyMap / (next) => voidPer-field strategies + setter.
generatedRowsArray<Record<string, unknown>>The rows shown in the preview / saved on the next step.
resultDummyGenerationResult | nullFinal-step summary.
generateAsync() => Array<Record<string, unknown>>Imperative generation that returns the rows (skips the wizard UI).
insertAsync(rows) => Promise<DummyGenerationResult>Imperative insert (skips the wizard UI).
fieldsArray<DocyrusFieldLike>Resolved target fields (from fields prop or useDocyrusDataViewSelect).
isGenerating / isCreatingbooleanPending flags.
errorError | nullLast insert error.

Determinism

Generation uses a Mulberry32 PRNG seeded with a fresh value on every "Regenerate sample" click. Within one click, the preview rows are byte-identical to the rows that get inserted. Pass seed directly to generateDummyRows(ctx) if you want test-stable output.

Error Handling

  • Per-row insert errors are collected and shown as a per-row error list on the result step. The wizard always reaches the result step — partial failures don't abort the run.
  • A thrown insertRecords (the override) marks every row as failed and surfaces the message in the per-row list.

See Also

On this page