ast-visitor-pattern

por prisma

Use o padrão de classe congelada/visitor para uniões discriminadas que possuem múltiplos locais de despacho. Use ao criar um novo conjunto de variantes (comandos, nós de IR, …

npx skills add https://github.com/prisma/prisma-next --skill ast-visitor-pattern

AST Class/Visitor Pattern

When a discriminated union has 3+ variants and 2+ dispatch sites (renderers, serializers, classifiers, etc.), replace plain union + switch with frozen subclasses and a visitor interface. This makes adding a new variant a compiler error at every consumer, instead of a silent omission.

Structure

Four pieces, always in the same file:

// 1. Abstract base (not exported — consumers use the union type)
abstract class FooNode {
  abstract readonly kind: string;
  abstract accept<R>(visitor: FooVisitor<R>): R;
  protected freeze(): void { Object.freeze(this); }
}

// 2. Visitor interface
export interface FooVisitor<R> {
  bar(node: BarNode): R;
  baz(node: BazNode): R;
}

// 3. Concrete subclasses — readonly fields, freeze() in constructor
export class BarNode extends FooNode {
  readonly kind = 'bar' as const;
  readonly value: string;
  constructor(value: string) {
    super();
    this.value = value;
    this.freeze();
  }
  accept<R>(visitor: FooVisitor<R>): R { return visitor.bar(this); }
}

export class BazNode extends FooNode {
  readonly kind = 'baz' as const;
  readonly count: number;
  constructor(count: number) {
    super();
    this.count = count;
    this.freeze();
  }
  accept<R>(visitor: FooVisitor<R>): R { return visitor.baz(this); }
}

// 4. Union type
export type Foo = BarNode | BazNode;

Consuming

Define a visitor object (or class) per concern:

const renderVisitor: FooVisitor<string> = {
  bar(node) { return node.value; },
  baz(node) { return String(node.count); },
};

function render(node: Foo): string {
  return node.accept(renderVisitor);
}

Always construct instances, never frozen object literals

This holds everywhere a node is built — tests and production construction surfaces (contract-free factories, builders). A factory must return new BarNode(...), never Object.freeze({ kind: 'bar', value: 'x' }). A frozen plain object has no prototype, so instanceof fails, accept() is missing, and a downstream shallow-copy ({ ...node }) silently strips the type back to an anonymous bag; constructor-time invariants are skipped too.

// ✅
const call = new BarNode('x');
export function bar(value: string): BarNode { return new BarNode(value); }

// ❌
const call: Foo = { kind: 'bar', value: 'x' };
export function bar(value: string): Foo { return Object.freeze({ kind: 'bar', value }); }

When NOT to use

  • Single dispatch site → plain union + switch is simpler
  • Fewer than 3 variants with no expected growth → not worth the boilerplate

Codebase examples

  • MongoAstNode / MongoDdlCommandVisitorpackages/2-mongo-family/4-query/query-ast/src/ddl-commands.ts
  • OpFactoryCall / OpFactoryCallVisitorpackages/3-mongo-target/1-mongo-target/src/core/op-factory-call.ts

Mais skills de prisma

prisma-cli-migrate-reset
prisma
prisma migrate reset
official
prisma-cli-validate
prisma
validação do prisma. Referência ao usar este recurso do Prisma.
official
prisma-next-extension-upgrade
prisma
Upgrade Prisma Next in your extension. Bumps every `@prisma-next/*` dependency to the requested target (or npm `latest`), runs the per-transition upgrade…
official
adr-review
prisma
Revise um ou mais ADRs com um olhar novo (como um membro da equipe sem contexto prévio), identifique problemas narrativos e estruturais e, em seguida, reescreva-os. Use quando o…
official
prisma-next-upgrade
prisma
Upgrade Prisma Next in your app. Bumps every `@prisma-next/*` dependency from the version pinned in the lockfile to the requested target (or npm `latest`),…
official
prisma-cli
prisma
Referência completa para comandos, opções e fluxos de trabalho do Prisma CLI em configuração, migrações e operações de banco de dados. Abrange mais de 20 comandos organizados por prioridade: configuração (init), geração (generate), desenvolvimento (dev), operações de banco de dados (db pull/push/seed/execute) e migrações (migrate dev/deploy/reset/status/diff/resolve). Inclui mudanças do Prisma 7.x: novo arquivo de configuração prisma.config.ts, flags removidas (--skip-generate, --skip-seed, --schema, --url) e explícito...
official
prisma-client-api
prisma
Referência completa da API do Prisma Client para consultas de modelo, operações CRUD, filtragem, relações e transações. Abrange 17 métodos de consulta de modelo, incluindo findUnique, findMany, create, update, delete, upsert e operações em lote com variantes de retorno. Fornece opções de consulta para moldar resultados: select, include, omit, orderBy, take, skip, cursor e distinct. Inclui operadores de filtro escalares e lógicos (equals, in, contains, startsWith, lt, gt) além de filtros de relação (some,...
official
prisma-compute
prisma
Prisma Compute deployment and hosting guide. Use whenever the user mentions Prisma Compute, `prisma.compute.ts`, `defineComputeConfig`, deploying or hosting a Prisma app, `@prisma/cli app deploy`, `compute:deploy`, `create-prisma --deploy`, `PRISMA_SERVICE_TOKEN`, `auth workspace`, Compute apps/deployments/build logs/domains, `@prisma/cli agent install`, localhost vs `0.0.0.0`, deploy port binding, or framework deploy readiness for Hono, Elysia, Next.js, TanStack Start, Astro, Nuxt, Svelte,...
developmentdevopsofficial