spec/vectors/niadra-expr.v0.json: o servidor e os dois SDKs rodam o mesmo arquivo.
Tipos de campo e como os valores viajam
Osfields de um evento e um push de objeto levam cada valor em JSON, na forma que o tipo declarado espera:
Um valor de outro tipo fica guardado como veio, mas uma expressão sobre o campo não consegue lê-lo como o tipo dele: um valor em dinheiro enviado como a string
"38000.00" não é número para uma leitura, um campo derivado ou um temporizador. Um campo que o tipo não declara fica como campo simples e abre uma problema de dados de drift, nunca uma recusa. O que um evento diz de si mesmo (operation, version, last_event_type, source_version, record_ref, input_refs) é escrituração: nunca é drift e só é servido quando o tipo o declara como campo. Cada chave dos fields de um evento vale para todos os objetos dos object_refs dele, então mande um objeto por evento.
O que um campo declara
Um campo
plain não declara observers nem unobserved_blocks. Mudar a sensitivity, o access ou o pii de um campo, a licença de uma fonte ou as finalidades do tipo é uma decisão de privacidade: pede também o papel que responde pela segurança.
O que o servidor recusa num tipo
Além da forma do documento, um tipo é recusado, com o caminho de cada entrada que quebra uma regra (por exemplotimers.launch_at.on_fire: transition(scheduled->actve) is not a transition of the lifecycle), quando:
- Um campo, um valor, um eixo de tempo ou um campo derivado usa um nome que outro já tem, ou um nome que a linguagem reserva (abaixo).
- Um estado que o ciclo de vida, um temporizador ou um vocabulário nomeia não está declarado; um
timers_onnomeia um eixo não declarado; um campo de conteúdo,completeness.total_field, um defeito conhecido, uma chave deunionou uma ação derefreshnomeia um campo ou valor não declarado;prefer_source,use_source,quote()ou um vocabulário nomeia uma fonte não declarada; um campo derivado nomeia uma relação não declarada, ou uma cujo tipo o registro não declara, ou umminoumaxsobre um campo que esse tipo não tem. - Um eixo derivado não nomeia a regra dele, ou uma regra está num eixo que não é derivado; um tipo derivado por introspecção perdeu a impressão digital.
- Um membro quebra a própria regra: um campo
plaincom observadores, umclaim_max_ageacima demax_age, e as regras de fontes, ciclo de vida, temporizadores, releitura e finalidades que Tipos de objeto e estado descreve. - Uma expressão não se lê ou não se resolve contra o tipo: as condições (
when,active_when,where) dão verdadeiro ou falso, e oduede um temporizador dá uma data ou um instante.
niadra-expr
A linguagem é pequena, determinística e total: sem laços, sem recursão, sem E/S e sem relógio além do que recebe, com texto e aninhamento limitados, e um resultado ou um de três erros para toda entrada. O mesmo texto dá o mesmo resultado no servidor, em cada SDK e no seu worker de resolução.Tokens
- Espaços, tabulações e quebras de linha separam tokens.
- Um nome é
[a-z_][a-z0-9_]*, no máximo 64 caracteres, ASCII minúsculo. - Um número são dígitos com um
.opcional e pelo menos um dígito depois dele; não há sinal, um número negativo vem de uma subtração. - Uma duração é um inteiro de no máximo seis dígitos seguido de
ms,s,min,houd(mnão é unidade, e1.5hse escreve90min). - Uma string vai entre aspas simples, numa linha só, com
\'e\\como únicos escapes, no máximo 256 caracteres. - Os operadores são
==,!=,<,<=,>,>=,+,-,(,),[,],,e.; as palavras-chave sãoand,or,not,in,true,false,none,yes,no,unobservedeknown_defect.
Gramática
or liga mais frouxo, depois and, not, uma comparação, + e - (da esquerda para a direita) e .. Comparações não se encadeiam: a < b < c é erro. Um nome com pontos como lead.city é um nome só, com partes; depois de um grupo ou de uma chamada, . lê um campo de uma cotação. As palavras lógicas só aparecem de um lado de == ou !=.
Valores e os quatro valores lógicos
unobserved e known_defect são desconhecidos. Um valor presente é um booleano, um número, uma string, uma duração (milissegundos inteiros), uma data, um instante (ao milissegundo) ou uma lista. Não observado nunca é falso: uma comparação com um valor desconhecido é desconhecida, e a negação dela também.
Nomes
Um nome de uma parte é, nesta ordem: um nome de contexto (state, o estado do ciclo de vida; derived_status; watch_count, 0 por padrão; purpose, a finalidade da leitura, display por padrão); um campo, um valor calculado ou um eixo de tempo do objeto; um nome de ausência declarado; senão, um campo que ninguém observou, unobserved. Um nome com pontos é uma entrada declarada desse caminho (lead.city), config.<chave> (o valor de configuração da empresa, ausente quando não definido) ou <campo>.completeness. As palavras-chave e state, derived_status, watch_count, purpose e config são reservados. Um estado é uma string: state == 'open', nunca state == open.
Operadores
x == yesé verdadeiro exatamente quandoxlevayes, e o mesmo para as outras palavras lógicas; o resultado é sempre verdadeiro ou falso:available == unobservedpergunta se um valor foi observado.- Fora isso, quando um dos lados de uma comparação, de
+ou de-é desconhecido, o resultado é desconhecido (known_defectquando um deles o leva). - Igualdade: duas ausências são iguais quando uma não tem nome ou as duas têm o mesmo (
noneé qualquer ausência); uma ausência nunca é igual a um valor presente; números pelo valor, strings pelos caracteres, durações pelo tamanho, datas e instantes como instantes (uma data é o início do dia), listas item a item; qualquer outro par éexpr_type. - Ordem (
<,<=,>,>=) é falsa quando um dos lados é ausente; números, strings (por ponto de código), durações, datas e instantes se comparam; qualquer outro tipo éexpr_type. inrecebe uma lista à direita: verdadeiro quando a esquerda é igual a um item, desconhecido quando um item desconhecido poderia decidir, falso nos outros casos.and,orenotrecebem verdadeiro, falso ou desconhecido, com lógica de três valores, da esquerda para a direita, e o primeiro operando que decide para a avaliação:false and xnunca avaliax.+e-: número com número; duração com duração; uma data ou um instante mais ou menos uma duração dá um instante; uma data mais ou menos dias úteis dá uma data; duas datas ou instantes subtraídos dão uma duração. Um operando ausente dá uma ausência.
Funções
Os prazos de um tribunal, de um contrato ou de um produto são regras da sua empresa, como valores declarados: a linguagem só conta dias úteis simples.
Erros e limites
Uma expressão tem no máximo 1.024 caracteres, 256 tokens e 16 grupos aninhados; uma lista literal no máximo 64 itens, uma string no máximo 256 caracteres, um nome no máximo 64 e uma duração no máximo seis dígitos. Uma lista lida de um encaixe tem no máximo 1.000 itens, e uma contagem de dias úteis no máximo 1.000.
Próximos passos
Tipos de objeto e estado
Para que serve um tipo, frescor, a finalidade da leitura e objetos compartilhados.
Leituras tipadas
POST /v1/state/read: campos, valores, leituras e temporizadores.
