Documentação
IU da área de trabalho
Espaços de trabalho SolidJS, um cliente API local e um shell Tauri que possui integração nativa.
Traduzido automaticamente do inglês. Ver o original em inglês
Arquitetura de aplicativo
O aplicativo de desktop combina um webview SolidJS, Vite, Three.js e um shell Tauri v2 Rust. O webview possui telas e estados de interação. O sidecar Bun possui manipuladores de API, acesso a banco de dados, sessões de IA e serviços de projeto. O processo Rust possui a janela, os menus, a bandeja, as caixas de diálogo do sistema operacional, o acesso às chaves, as atualizações e o ciclo de vida do sidecar.
apps/desktop/src/main.tsx monta o aplicativo. app/App.tsx estabelece a conexão API e fornece estado compartilhado; app/routes.tsx mapeia URLs para módulos de páginas lentas. Telas de recursos ao vivo features/. A presença de uma rota não estabelece a disponibilidade de seus serviços externos: o faturamento precisa da configuração do Stripe e a IA precisa de um provedor configurado.
Inicialização e recuperação de conexão
- O shell inicia o sidecar empacotado com um token de inicialização gerado e dados de aplicativo e diretórios de migração.
- O sidecar vincula uma porta efêmera em
127.0.0.1, aguarda a resposta de sua rota de integridade e grava um JSONreadyevento contendo a porta. - A visualização da web invoca
get_sidecar_endpointe cria um cliente API e um tempo de execução de efeito gerenciado. - Uma solicitação de integridade bem-sucedida cria o estado do aplicativo e monta o roteador e o shell.
O webview permite 150 segundos para recuperação de conexão, com um tempo limite de 30 segundos por tentativa e uma pausa de repetição de 750 milissegundos. Tentativas fracassadas descartam o endpoint armazenado em cache para que um sidecar reiniciado possa fornecer uma nova porta. O supervisor Rust espera 60 segundos para cada handshake pronto e permite uma reinicialização automática. A nova tentativa fica disponível quando o orçamento de conexão do webview expira.
A visualização do navegador usa uma API na memória
Fora do Tauri, um navegador sem VITE_SIDECAR_URL usa src/testing/fake-api.ts. Os dados de visualização são locais na página em execução; coleções não suportadas retornam HTTP 501. Para conectar um navegador a um sidecar real, forneça ambos VITE_SIDECAR_URL e VITE_SIDECAR_TOKEN ao iniciar o Vite.
Rotas de tela
| Área | Rotas e módulos |
|---|---|
| Projetos | /projects, /projects/create, /projects/:id, e /projects/:id/history; telas em features/projects/screens. |
| Projeto e fabricação | /cad montagens CadPage; /cam montagens CamPage. Desenhos e percursos da ferramenta salvos possuem rotas de detalhe separadas. |
| Recursos | /library, /materials, /tools, /machinee suas páginas de detalhes usam módulos de recursos de biblioteca. Os componentes possuem rotas de lista e detalhe. |
| Assistente | /ai e o painel do assistente acoplado compartilha o estado do recurso AI. A atividade de IA alterna o painel. |
| Configurações | /settings, /settings/companion, configurações de MCP e configurações de assinatura. |
| Conta e colaboração | Autenticação, perfil, organização, convite, bate-papo, mercado, plug-in, custos, análises e rotas de administração carregam módulos de recursos. |
Usar app/routes.tsx para nomes exatos de parâmetros e pages/ para localizar a tela montada em um URL. Os adaptadores de rota são intencionalmente pequenos; leia a tela e suas chamadas de API ao diagnosticar uma visualização vazia ou uma ação com falha.
Organização de origem
app/: inicialização, roteador, cliente API global, integração nativa, shell e atalhos de teclado.pages/: adaptadores de rota importando ou reexportando telas.features/: áreas de produtos com telas, componentes, ganchos, estado e auxiliares específicos de domínio.shared/: controles reutilizáveis, componentes do shell, estado do aplicativo, cache de consultas e histórico de comandos.viewport/: desenho de tela, encaixe, gestos de ferramentas, renderização Three.js, malha e reprodução.i18n/,styles/, etesting/: traduções, estilos globais e acessórios de teste.
A área de trabalho depende de @cadcamfun/api para o contrato HTTP e em @cadcamfun/core para geometria e operações CAM. A persistência do banco de dados permanece por trás da API secundária. O histórico do editor local é diferente das versões persistentes de desenho ou percurso e do controle de versão do projeto.
Concha nativa
A janela de produção é 1440 × 900 por padrão, com um mínimo de 960 × 600. Tauri prepara o frontend de apps/desktop/dist, um sidecar específico do alvo de src-tauri/binariese gerou migrações como recursos. Ele registra .cadcam, .nc, e .gcode associações de arquivos. Abrir um arquivo compatível ou iniciar uma segunda instância encaminha os caminhos dos arquivos para a janela existente.
src-tauri/src/sidecar.rs supervisiona o processo filho. Fechar o aplicativo escreve um {"event":"shutdown"} linha para o stdin da criança e espera um pouco antes de colhê-lo; a criança também observa o fechamento do stdin. O token de inicialização é composto por 32 bytes aleatórios, codificados em hexadecimal como 64 caracteres, e as linhas de log secundárias que podem conter credenciais são editadas. Os logs são separados do stdout, que carrega o handshake de prontidão/erro. Os segredos nativos são acessados por meio de src-tauri/src/secrets.rs usando o chaveiro do sistema operacional.
No macOS, o shell registra o plugin Liquid Glass. A visualização na web segue a configuração do vidro e retrocede quando o efeito não está disponível. A configuração da App Store desativa a opção de API privada; a configuração regular permite isso. Estas são configurações de compilação separadas.
Limites de segurança e persistência
A política de conteúdo de produção permite ativos locais, conexões de API de loopback, imagens de dados/blob e avaliação de WebAssembly. Não permite execução remota arbitrária de scripts. As permissões nativas têm escopo em src-tauri/capabilities; a política de desenvolvimento também permite o Vite e seu websocket.
open_path canoniza caminhos, limita-os a diretórios de usuários/aplicativos permitidos e rejeita extensões executáveis, como .exe, .app, .sh, .bat, .msi, e .jar. .. segmentos e links simbólicos não podem escapar das pastas permitidas porque ambos os lados são canônicos. A seleção e o salvamento de arquivos usam diálogos e validação nativos. Um token de inicialização concede acesso à API do aplicativo local; trate-o separadamente de um token complementar ou de um token de ponte de IA no escopo do projeto.
As configurações da UI, o estado da consulta da API, os comandos do editor, as versões do projeto armazenadas e os segredos nativos têm proprietários diferentes. Diagnostique cada um por meio de seu serviço real, em vez de assumir que todo o estado do aplicativo está armazenado no SQLite.
Integração de recursos
Os módulos de recursos CAD e CAM compõem componentes de viewport reutilizáveis com seus próprios painéis, armazenamentos e fluxos de salvamento. O painel do assistente recebe o contexto do projeto e do editor e transmite eventos da ferramenta por meio do estado do recurso de IA. As telas de recursos usam o cliente API em vez de acessar diretamente o banco de dados.
Para uma alteração na interface do usuário, siga o adaptador de rota até sua tela de recursos e, em seguida, inspecione o feature store ou gancho que envia a solicitação. Reutilize componentes compartilhados somente quando o contrato existente corresponder à interação. Mantenha a geometria pura no pacote principal e o comportamento nativo do sistema operacional no shell Rust.
Carregamento de rota e erros
Cada rota usa o limite de importação lenta do Solid. A tabela inclui uma página abrangente, /500, /offlinee rotas legais. Uma navegação direta do navegador deve ser servida por meio do servidor de desenvolvimento Vite ou do webview empacotado para que o roteador do cliente possa resolver a URL.
A API de visualização implementa um conjunto limitado de coleções e pode injetar deliberadamente falhas de solicitação em testes. Uma renderização de visualização bem-sucedida demonstra o comportamento da UI em relação a esses equipamentos; verifique persistência, permissões, streaming e integrações externas com o sidecar ao vivo.
Interface de comando nativa
| Comando | Propósito |
|---|---|
get_sidecar_endpoint | Aguarde o sidecar supervisionado e retorne seu URL base e token de lançamento. A espera abrange uma reinicialização: dois tempos limite de prontidão de 60 segundos mais 5 segundos (125 segundos). |
get_logs_dir, open_path | Resolva o diretório de log do aplicativo como uma string e abra um caminho absoluto existente com o abridor do sistema operacional. Os caminhos devem ser resolvidos nos dados do aplicativo, log, Documentos, Downloads ou pasta Desktop. |
secret_get, secret_set, secret_delete | Acesse entradas de chaves nativas no com.cadcamfun.app serviço. As chaves são 1–128 bytes de letras ASCII, dígitos e . _ - : (por exemplo ai.anthropic.apiKey); secret_get retorna null para uma entrada perdida. |
pick_file, save_file | pick_file({ filters: [{ name, extensions }] }) retorna o caminho escolhido ou null em cancelar. save_file({ defaultName, contents }) escreve texto UTF-8 no caminho escolhido e o retorna, ou null em cancelar; diretórios e extensões executáveis são rejeitados. |
set_recent_projects | Atualize o menu de projetos recentes da bandeja. |
check_for_updates, install_update | Solicite uma verificação do atualizador ou instale uma atualização pendente. install_update aceita um opcional unsavedWork sinalizador (padrão false) para que uma instalação não interrompa um editor aberto. |
The invoke handler is registered in src-tauri/src/lib.rs. Capabilities and generated command permissions also control availability; command registration alone does not establish webview access. Command errors are serialized as { kind, message } with kinds such as sidecar, invalid_path, io, dialog, and path; no command panics.
Eventos nativos
A casca emite sidecar-status para mudanças no ciclo de vida, open-file com caminhos suportados, menu para seleção de menu e update://status para o progresso do atualizador. As seleções de projetos recentes da bandeja são representadas por tray.recent.<projectId> identificadores de menu. Os módulos de menu e bandeja do shell definem seus conjuntos completos de identificadores.
Os ouvintes devem ter como escopo o ciclo de vida de seu componente ou aplicativo e ser removidos na limpeza. O webview deve resolver novamente o endpoint após a reinicialização do sidecar, em vez de continuar a usar a porta anterior.
Desenvolvimento e verificação
bun run --filter @cadcamfun/desktop dev
bun run desktop:dev
bun run --filter @cadcamfun/desktop typecheck
bun test apps/desktop/src
bun run build:desktop O primeiro comando executa uma visualização do navegador. desktop:dev compila o sidecar real e prepara as migrações antes de iniciar o Tauri. O pacote desktop tauri:dev em vez disso, o script cria um binário stub somente quando não existe nenhum binário; use-o para trabalho de shell isolado e verifique qual binário está presente antes de interpretar suas respostas de API.
A área de trabalho build script é executado vite build apenas; ele não compila o sidecar nem empacota um pacote Tauri. Usar bun scripts/build.ts para o pipeline de lançamento completo (consulte Liberar).
Preferências e configurações
O armazenamento de configurações compartilhadas mantém um registro validado em cadcamfun.settings no armazenamento local do webview. Campos ausentes, inválidos ou ilegíveis retornam de forma independente. Uma área de armazenamento cheia ou bloqueada não interrompe a edição, mas as alterações de preferência podem não persistir. As preferências de visualização do navegador pertencem à origem do navegador e são separadas das preferências nativas de visualização da web.
| Contexto | Valores aceitos/padrão | Efeito operacional |
|---|---|---|
| Tema | light, dark, system; sistema padrão | O modo do sistema segue as alterações no esquema de cores do sistema operacional. |
| Unidades de exibição | mm ou in; padrão mm | Apresentação de controles; as coordenadas do desenho central permanecem em milímetros. |
| Decimais | Inteiro 0–6; padrão 3 | Precisão de apresentação de comprimento. |
| Postagem padrão | grbl, linuxcnc, smoothwb, gcode, fanuc; grbl padrão | Uma gramática de saída selecionada é uma preferência, não uma prova de que a máquina está configurada ou verificada. |
| Tolerância de desenho | Tolerância central validada; padrão 0.01 mm | Preferência de precisão compartilhada usada pelos consumidores de desenho/percurso. |
| Estado instantâneo | Booleano; padrão ativado | Preferência de status compartilhada. Editores individuais são donos de seu comportamento instantâneo; o independente Editor2D atualmente habilita seu snap à grade internamente. |
| Vidro | Booleano; padrão ativado | Solicita material de janela do macOS quando o host nativo oferece suporte. |
A tela Configurações possui guias Perfil, Conta, Segurança, Assinatura, Notificações, IA, Dispositivos e Idioma. A guia Dispositivos incorpora o painel de gateway complementar. As configurações de idioma incluem a alternância do vidro. O armazenamento de localidade comum valida atualmente a localidade padrão; não inferir cobertura de tradução adicional a partir de uma lista de rótulos de exibição.
Salve e reabra um programa CAM
- Gere ou carregue o código NC no CAM e abra a caixa de diálogo salvar/exportar a partir do ponto de entrada existente.
- Para uma exportação de arquivo, escolha o código G ou o formato de percurso portátil. O código G baixa o texto NC atual; a escolha do percurso grava um texto estruturado
.cam.jsoninstantâneo. - Para persistência do aplicativo, escolha um projeto existente, um novo projeto ou atualize o programa já salvo. Forneça o nome do programa e os campos de destino obrigatórios.
- Ao atualizar, o fluxo de salvamento registra o programa completo anterior como uma versão do percurso antes de substituir os dados atuais.
- Abra o item salvo em sua rota detalhada do percurso para inspecionar ou restaurar versões.
O resumo salvo inclui linhas NC, bytes, movimentos, identificadores de ferramentas, nomes de operações, estoque, unidades, deslocamento de trabalho e identidade de verificação quando essa evidência pertence ao NC atual. Um texto NC modificado pode tornar obsoletas as evidências previamente computadas. Revise a relação código/evidência atual antes de confiar no resumo.
Se a criação de um novo projeto for bem-sucedida, mas uma etapa de salvamento posterior falhar, o modal retém o destino criado para novas tentativas e inclui seu identificador no erro. Tentar novamente nesse modal evita criar o mesmo projeto novamente. Não presuma que o fluxo de salvamento é uma transação atômica entre recursos.
A exportação de arquivos e a persistência do projeto são operações diferentes
Um arquivo de código G baixado não cria uma linha de percurso de projeto. Um instantâneo portátil carrega um estado mais rico do que o NC simples. Verifique um programa salvo reabrindo-o no aplicativo e verifique uma exportação inspecionando o arquivo baixado.
Diagnóstico de teclado e falhas
Cmd/Ctrl+K abre a paleta de comandos e Cmd/Ctrl+J alterna o painel do assistente. Os atalhos do shell são ignorados quando o foco está em um elemento de entrada, área de texto, seleção ou conteúdo editável. As telas do editor têm seu próprio controle de teclado. Vários retornos de chamada de comando shell, incluindo Salvar/Exportar na tabela de atalhos genérica, são espaços reservados; use os controles reais de salvar/exportar do recurso em vez de assumir que cada acelerador listado executa uma operação de documento.
| Comportamento observado | Verificar |
|---|---|
| A inicialização espera e, em seguida, Tentar novamente aparece | Erro secundário/saída pronta, binário de destino, recurso de migração e logs de aplicativos. Uma porta em cache pode pertencer a um processo anterior. |
| Uma tela é renderizada, mas as solicitações retornam 501 | Modo de fixação do navegador. Inicie o sidecar real e passe ambas as variáveis de endpoint do Vite. |
| Os dados da área de trabalho diferem de um script manual | O diretório de dados e token de cada processo; um nome de arquivo por si só não identifica o banco de dados. |
| Um comando nativo não está disponível | Invoque registro, permissões de capacidade, suporte ao sistema operacional e se o código é executado dentro do Tauri. |
| As configurações são revertidas após a reinicialização | Disponibilidade e validação de armazenamento. Os campos armazenados inválidos retornam aos padrões. |
| A evidência do programa salvo difere do NC | Se o NC foi editado após geração. Recalcule a verificação apropriada para o texto/programa real. |
Âncoras de implementação: shared/state/settings.ts, app/shortcuts.ts, features/settings/screens/settings.tsx, e features/cam/components/SaveCamModal.tsx.
Cargas úteis de eventos nativos
| Evento | Carga útil | Notas |
|---|---|---|
sidecar-status | { state: "starting" }, { state: "ready", port }, { state: "restarting" }, { state: "failed", message } | Depois restarting, chamar get_sidecar_endpoint de novo; a porta muda. |
update://status | status: checking, upToDate (version), available (version, notes, date, critical), downloading (downloaded, total), ready (version), failed (message); mais dismissible | Uma atualização crítica e uma reinicialização pendente não podem ser descartadas. Uma verificação falhada nunca é mostrada como um erro de bloqueio. |
menu | ID do item de menu, como file.new, file.open, file.save, view.devtools, help.documentation | Uso de itens da bandeja tray.quit e tray.recent.<projectId>. |
open-file | Caminhos de .cadcam, .nc, ou .gcode arquivos | Enviado quando o sistema operacional abre um arquivo com o aplicativo ou uma segunda instância é iniciada. |
install_update pode ser recusado com um motivo digitado: unsavedWork ("o editor tem trabalho não salvo; aplique a atualização assim que for salvo"), noneAvailable (nada pendente ou já instalado), ou failed (falha no download ou verificação de assinatura). Ele instala apenas a atualização anunciada pela última verificação.
import { invoke } from "@tauri-apps/api/core"
import { listen } from "@tauri-apps/api/event"
const { baseUrl, token } = await invoke<{ baseUrl: string; token: string }>("get_sidecar_endpoint")
const path = await invoke<string | null>("pick_file", {
filters: [{ name: "G-code", extensions: ["nc", "gcode"] }],
}) // null when the user cancels
await invoke("save_file", { defaultName: "part.nc", contents: gcodeText })
const unlisten = await listen<{ state: string; port?: number }>("sidecar-status", (e) => {
if (e.payload.state === "ready") reconnect()
})
// later: unlisten()
try {
await invoke("install_update", { unsavedWork: editorIsDirty })
} catch (error) {
// { kind, message }: the update variant carries the refusal (unsavedWork | noneAvailable | failed)
} get_sidecar_endpoint retorna { baseUrl, token } (serializado em camelCase de SidecarEndpoint). Erros de cada comando chegam como o valor rejeitado de invoke, em forma { kind, message }.
Atalhos de teclado
| Atalho | Ação | Grupo |
|---|---|---|
Cmd/Ctrl+K | Abra a paleta de comandos | navegação |
Cmd/Ctrl+Shift+P | Novo projeto | navegação |
Cmd/Ctrl+Z / Cmd/Ctrl+Shift+Z | Desfazer/refazer | editar |
Cmd/Ctrl+S, Cmd/Ctrl+Shift+E | Salvar, exportar (espaços reservados de shell; use os próprios controles do recurso) | editar |
Cmd/Ctrl+0 | Zoom para ajustar | visualizar |
Cmd/Ctrl+= / Cmd/Ctrl+- | Aumentar/diminuir zoom | visualizar |
Cmd/Ctrl+J | Alternar o painel do assistente | ai |
Cmd aplica-se ao macOS e Ctrl em outro lugar. O ID de cada atalho também é o sufixo da chave de tradução (por exemplo settings.shortcut.palette), e a tela Configurações renderiza essa mesma tabela, para que a documentação e o aplicativo não possam se separar.
Cada rota de tela
O roteador em apps/desktop/src/app/routes.tsx declara 68 rotas, cada uma carregada lentamente de apps/desktop/src/pages/ (segmentos dinâmicos são _id_.tsx arquivos). Agrupados por primeiro segmento:
| Área | Rotas |
|---|---|
* | * |
500 | /500 |
admin | /admin/analytics /admin/feature-flags |
ai | /ai |
analytics | /analytics/history /analytics |
auth | /auth/forgot-password /auth/magic-link /auth/magic-link/verify /auth/reset-password /auth/signin /auth/signup /auth/two-factor /auth/verify-email /auth/verify |
cad | /cad |
cam | /cam |
costs | /costs |
components | /components/:id /components |
drawings | /drawings/:id |
/ | / |
invitations | /invitations/:token |
legal | /legal/privacy /legal/terms /legal/third-party-licenses |
library | /library |
machine | /machine/:id /machine |
marketplace | /marketplace /marketplace/items/:id /marketplace/purchase/success /marketplace/purchases /marketplace/seller/dashboard |
materials | /materials/:id /materials |
mcp | /mcp/directory /mcp/servers/:id |
offline | /offline |
organizations | /organizations/:id /organizations/:id/chat/:conversationId /organizations/:id/chat /organizations/:id/chat/new-group /organizations/:id/chat/new /organizations/create /organizations |
plugins | /plugins/:id /plugins |
pricing | /pricing |
profile | /profile /profile/settings |
projects | /projects/:id/history /projects/:id /projects/create /projects |
settings | /settings /settings/companion /settings/mcp/config-editor /settings/mcp/edit/:id /settings/mcp /settings/subscription |
third-party-licenses | /third-party-licenses |
toolpaths | /toolpaths/:id /toolpaths |
tools | /tools/:id /tools |
waitlist | /waitlist |
* renderiza a página 404 e /500 a página de erro. /offline renderiza a tela offline; como as páginas de autenticação, convite, 404, 500 e de sucesso de compra, ele usa o layout independente sem o aplicativo Chrome. Como cada página é uma importação lenta, o código da tela só é carregado na primeira visita; um carregamento de bloco com falha aparece como um erro de rota, não como um aplicativo em branco.