Documentação
Convenções de engenharia
Padrões usados para computação de domínio, validação de esquema, serviços de efeito, acesso a banco de dados e verificação.
Traduzido automaticamente do inglês. Ver o original em inglês
Estrutura de origem
Use identificadores, comentários, documentação e mensagens de commit em inglês. Os projetos TypeScript usam verificação rigorosa; interfaces públicas devem preservar tipos explícitos e decodificar valores externos em vez de propagar dados não verificados. Os manifestos do pacote expõem pontos de entrada de origem e os módulos do aplicativo usam importações relativas apropriadas à sua ferramenta de construção.
A área de trabalho apresenta telas de grupo, componentes, lojas e auxiliares em apps/desktop/src/features. Os adaptadores de rota permanecem em src/pages, enquanto o shell do aplicativo e a configuração do cliente residem em src/app. A geometria central permanece independente do estado da UI e do acesso ao banco de dados.
Geometria e unidades de saída
A geometria principal do vetor e da entidade analítica usa milímetros e radianos. O posicionamento da cena, os controles de recursos e os campos do eixo rotativo CAM possuem convenções de ângulo específicas do contrato, incluindo graus. Siga cada esquema ao adaptar entre eles. A conversão de exibição da IU pertence ao limite da exibição. As operações de usinagem utilizam adicionalmente parâmetros de avanço, fuso, profundidade e folga com significados definidos por seus esquemas; um número simples nunca deve adquirir uma unidade implícita apenas de um rótulo.
O código G publica conversão de saída e formatação de números específicas do controlador. O emissor compartilhado expõe formatNumber, arredonda para a contagem decimal solicitada, normaliza o zero negativo e rastreia a posição emitida. A formatação do feed pode omitir uma parte fracionária para valores integrais. Use o emissor em vez de formatar palavras de movimento de forma independente em cada chamador.
Mantenha distintas as evidências do modelo e a geometria aproximada da exibição. Uma superfície tesselada é útil para renderização e análise, mas por si só não prova que uma operação B-rep exata foi bem-sucedida.
Serviços de efeito
Extensão de serviços Context.Service e expor métodos de retorno de efeito digitados. Uma camada constrói a implementação e fornece suas dependências. apps/sidecar/src/layers.ts é o ponto de integração para repositórios, serviços, manipuladores, autorização e configuração de tempo de execução.
Recursos com vida útil, como identificadores SQLite, são adquiridos e liberados dentro do escopo da camada proprietária. Usar Effect.try ou Effect.tryPromise para traduzir exceções estrangeiras em erros significativos. Nomes de operações estáveis em erros e rastreamento tornam as falhas diagnosticáveis sem acoplar chamadores a um driver de armazenamento.
A composição das camadas é importante: camadas irmãs mescladas não fornecem serviços automaticamente umas às outras. O registro da etapa do fluxo de trabalho Sidecar é colocado em camadas após o executor necessário; a etapa AI é registrada onde o serviço AI está disponível.
Validação e erros
As entradas e saídas HTTP são declaradas em packages/api/src/groups. Valide a entrada desconhecida nesses limites. O contrato inclui erros de mensagem simples, envelopes de sucesso/erro e alguns corpos de erro digitados; preservar o status declarado do endpoint e a representação da resposta.
Erros voltados para HTTP usam esquemas de efeito e anotações de status. Por exemplo, BadRequest, Unauthorized, NotFound, e Conflict são declarados em packages/api/src/errors.ts. Falhas internas do banco de dados realizam uma operação e causam DatabaseError. Mapeie falhas internas no limite HTTP em vez de expor detalhes do driver aos clientes.
Regenerar clientes após uma mudança de contrato com bun run generate. Verifique a saída confirmada com bun run generate:check. As pastas geradas são saídas; a geração exclui explicitamente terminais que um destino não pode representar.
Persistência e configuração
Os repositórios de aplicativos usam o Database serviço de @cadcamfun/db e seu query(operation, run) ajudante. Mudar packages/db/src/schema.ts antes de gerar migrações. Revise SQL e metadados gerados juntos; não execute um experimento de esquema destrutivo no banco de dados de um usuário.
O sidecar lê a configuração em apps/sidecar/src/config.ts e passa por isso AppConfigService. As credenciais usam valores editados onde o serviço os exige. Mantenha os valores secretos do token e do provedor fora dos logs, da documentação e da saída de solução de problemas. O shell nativo fornece seu próprio token de inicialização e caminhos de armazenamento.
A documentação do Studio é uma ferramenta local separada com sua própria seleção de caminho no packages/web/script/studio-server.ts. Não presuma que o caminho do banco de dados ou a sessão de login corresponda à área de trabalho em execução.
Verificação
bun test packages/core
bun run --filter @cadcamfun/core typecheck
bun run generate:check
# Documentation content and build
bun test packages/web/test
bun run --filter @cadcamfun/web typecheck
bun run --filter @cadcamfun/web build Escolha verificações que exercitem o limite afetado. Mudanças puras no kernel precisam de casos de regressão numérica e geométrica. As alterações HTTP precisam de cobertura de manipulador e esquema. As alterações na documentação precisam de rotas válidas, âncoras, exemplos e uma construção de site bem-sucedida. Uma execução de teste completa do espaço de trabalho é bun run test, que inclui pacotes, aplicativos e scripts.
Campos opcionais, nulos e valores de transporte
Um campo opcional pode ser omitido. Um campo anulável pode conter explicitamente null. São propriedades separadas: o contrato do projeto exige description nas linhas retornadas, permitindo nulo, e uma solicitação de criação permite a omissão desse campo. Preserve essas distinções ao criar clientes ou corrigir documentos salvos.
A validação de transporte também é diferente da validação de negócios. A carga útil de criação do projeto permite um nome omitido no nível do esquema, mas o manipulador retorna 400 com Project name is required se estiver faltando ou vazio. Um tipo gerado por si só não pode estabelecer que uma operação será admitida para um recurso ou conta corrente existente.
Os parâmetros de consulta HTTP são texto codificado. Use os campos de consulta declarados do cliente ou a codificação de URL em vez de concatenar entradas arbitrárias do usuário em uma URL. Codifique uma chave ou identificador de projeto como um segmento de caminho único e envie tokens de portador em cabeçalhos em vez de links copiados.
O referência de API de projetos mostra esses campos e códigos de status; o passo a passo capturado demonstra o resultado da validação do manipulador.
Manter documentação executável
Escreva um exemplo na superfície pública exata que ele nomeia. O Promise SDK e o cliente Effect completo baseado em contrato têm diferentes formatos de método/entrada e cobertura. Uma solicitação de gerador orientada por configurações é diferente de uma solicitação de kernel nativo e um programa gerado é diferente de um registro de percurso salvo.
O instantâneo de referência da API é gerado a partir do contrato do aplicativo. Depois de alterar um endpoint, gere-o novamente dentro do espaço de trabalho da web com bun run generate:api-reference. Correr bun run check:api-reference para compará-lo com a fonte atual. O agrupamento de recursos, o texto do artigo, a navegação e a recuperação do assistente ainda devem descrever esse contrato fielmente.
Ao documentar uma resposta capturada de uma execução isolada, identifique quaisquer IDs normalizados, carimbos de data/hora ou campos omitidos. Rotule os modelos de solicitação como modelos. Não apresente um identificador inventado ou um exemplo de esquema não executado como uma resposta de produção observada.
Padrões de efeitos usados em todo
import { Context, Data, Effect, Layer } from "effect"
import { AppConfigService } from "../config.ts"
export class StorageError extends Data.TaggedError("StorageError")<{
readonly operation: string
readonly cause: unknown
}> {}
export class Storage extends Context.Service<Storage, {
readonly read: (key: string) => Effect.Effect<Uint8Array, StorageError>
}>()("cadcamfun/Storage") {
static readonly layer = Layer.effect(Storage, Effect.gen(function* () {
const config = yield* AppConfigService // dependencies come from the context
return Storage.of({
read: (key) => Effect.tryPromise({
try: () => Bun.file(`${config.dataDir}/storage/${key}`).bytes(),
catch: (cause) => new StorageError({ operation: "read", cause }),
}),
})
}))
} - As chaves de serviço têm namespace:
"cadcamfun/Database","cadcamfun/AppConfig","cadcamfun/ApiClient". - Erros são
Data.TaggedErrorserviços internos eSchema.TaggedErrorcom umhttpApiStatusno limite HTTP. Os manipuladores mapeiam o primeiro para o segundo. - Recursos com uso vitalício
Effect.acquireReleaseentão eles fecham quando o escopo da camada fecha. - Funções nomeadas usam
Effect.fn("area.name")portanto, os rastreamentos carregam um nome de extensão legível, por exemplocam.runKernelRequest. - A configuração é lida uma vez, em
AppConfigService; nenhum outro módulo lêprocess.envno sidecar.
Regras de nomenclatura e layout
| Coisa | Convenção | Exemplo |
|---|---|---|
| Arquivos | kebab-case, um conceito por arquivo, teste próximo a ele | cam-program.ts, cam-program.test.ts |
| IDs de operação | <group>.<method> | projects.create, health.check |
| Rótulos de consulta | pontilhado, recurso primeiro | projects.list, toolpaths.update |
| Unidades | milímetros, graus, segundos; mm/min para alimentação, m/min para Vc | feed: 5696 |
| Coordenadas | Z para cima, destro; o programa se move nas coordenadas de trabalho | origem no topo do centro de estoque |
| IDs | Sequências UUID | crypto.randomUUID() |