Linha do tempo
Como o Sapphire foi construído — da primeira ideia até o 1.0 e além.
Clique numa temporada para abrir as fases · Clique numa fase para ver os detalhes
O Sapphire começa como uma ideia: definir o formato dos dados uma vez e gerar um schema para cada ORM. Ainda sem código — só o problema e o objetivo.
O conceito ganha uma primeira implementação feita à mão — sem estrutura de verdade, só o suficiente para mostrar que a ideia de um schema só podia funcionar.
Uma refatoração arquitetural: os fields deixam de conhecer qualquer ORM, e os adapters passam a ser resolvidos por nome através de um registry. O projeto ainda se chamava "Ruby" nesta fase.
A API do builder fica imutável e o TypeField sai da inferência de tipos, deixando os tipos inferidos mais precisos e previsíveis.
Encanamento de release: integração contínua, regras de lint e formatação, o mapa de exports do pacote e uma proteção prepublishOnly.
O código migra para um monorepo — packages/core e packages/mongo — com build dual ESM + CJS.
O Field é reescrito como um brand-type, e o Infer deriva um tipo TypeScript preciso direto da definição do schema.
Chega uma API de validação de verdade: parse e safeParse, devolvendo issues estruturadas, com uma hierarquia de mensagens para textos de erro customizados.
O vocabulário completo de modifiers é finalizado, e o registry de adapters deixa de usar um enum de ORM para usar chaves de texto — abrindo caminho para adapters de terceiros.
Novos field types — tuple, literal, enum, record e ref — além de um ArrayField homogêneo e um registry de schemas nomeados, construídos sobre uma nova representação intermediária.
O ObjectField ganha operadores de composição — pick, omit, partial, required, extend, merge — além de opções no nível do schema, como timestamps e índices.
O adapter Mongo é reescrito do zero para honrar cada parte da representação intermediária.
Um novo pacote converte a IR do Sapphire em um documento JSON Schema 2020-12.
Um novo pacote gera definições de tabela do Drizzle — pgTable, mysqlTable e sqliteTable — a partir da IR.
Sem código novo de runtime — esta fase produz /docs, exemplos executáveis, um README raiz reescrito e uma verificação de docs no CI.
Uma varredura comparando o design e o plano da V1 com o código real, além de uma auditoria tripla de QA: cobertura de testes, benchmarks e testes no nível de tipos.
Agindo sobre um code review extenso: 6 bugs de correctness, 5 inconsistências de API/IR, 10 smells de código e 4 drifts de documentação.
Uma segunda rodada de bugs, inconsistências e smells — os itens que as passagens anteriores deixaram para trás, resolvidos na main após o PR #16.
Planejamento da divisão do sapphire-mongo em um pacote nativo do Mongo e um pacote sapphire-mongoose separado.
Uma revisão pesada de toda a biblioteca, caçando bugs, inconsistências e smells antes de ir a público.
Prontidão para publicar no npm — changesets, packaging e workflows de release — culminando no lançamento 1.0.0.
O refine adiciona validação custom síncrona — predicados arbitrários por campo e regras cross-field — expressos dentro do mesmo schema.
refine assíncrono mais parseAsync / safeParseAsync, para regras que precisam consultar o banco — unicidade, existência.
llms.txt e llms-full.txt, além de uma listagem no Context7, para que assistentes de IA gerem código Sapphire correto em vez de adivinhar a API.
Limpar o backlog restante do code-review e adicionar um teste de integração com MySQL real no CI.
Um .adapter() tipado via module augmentation, e geração de mock data a partir de um schema. Um esboço — ainda não planejado em detalhe.
Um quinto adapter, sapphire-prisma, gerando um schema .prisma — uma DSL de texto, diferente da saída em objeto de runtime dos outros quatro. Um esboço.