Scrydon

SDK du noyau d'ontologie

Accès typé et limité à la requête au noyau d'ontologie d'un environnement d'espace de travail Scrydon.

SDK du noyau d'ontologie

Utilisez createKernelClient depuis @scrydon/ontology-sdk/client dans les appelants côté serveur. Le client est limité à la requête : fournissez le transport admis de l'appelant ainsi que les en-têtes exacts de l'organisation, de l'espace de travail et de son environnement. Ne mettez jamais en cache les en-têtes d'un utilisateur, n'exposez pas les identifiants de service au navigateur et ne remplacez pas le tuple complet par une portée limitée à l'organisation.

import { createKernelClient } from "@scrydon/ontology-sdk/client";

const ontology = createKernelClient({
  baseUrl: `${ontologyServiceUrl}/api/ontology`,
  headers: () => ({
    ...admittedCallerHeaders(),
    "x-organization-id": organizationId,
    "x-workspace-id": workspaceId,
    "x-workspace-environment-id": workspaceEnvironmentId,
  }),
});

const result = await ontology.objects.query({
  ontology: "crm",
  objectTypes: ["Customer"],
  limit: 50,
});

Les lectures publiées résolvent la révision courante, sauf si vous fournissez un revisionId immuable ; les lectures de branche utilisent un apiName de branche. Les écritures passent par actions.submit avec un type d'action final tel que schema.declare, schema.publish, branch.submit ou proposal.approve. Les erreurs sont des valeurs OntologyApiError avec un code stable généré, un httpStatus et des détails bornés. Une réponse non-2xx dépourvue d'enveloppe d'erreur du noyau — un 502 HTML renvoyé par un proxy, un 401 vide provenant du maillage — est elle aussi une OntologyApiError : son code est MALFORMED_ERROR_RESPONSE, httpStatus reprend le statut retourné et details contient le type de contenu de la réponse ainsi qu'un aperçu borné du corps.

Client namespaces

NamespaceMethods
actionssubmit
actionTypesget, list
aliaseslist, resolve
bindingscount, enroll, get, instances, list, materialize, materializeByObjectType, readiness, readinessOf, resolveByObjectType, resume, table
branchesarchive, create, declare, get, list, manifest, publish, rebase, submit
decisionsget
extensionsapply, autoInstall, installed
geolayers
graphexpand, instanceGraph, layout, layoutRun, layoutStatus, neighbors, schemaSlice, search, trail, viewport
linkslist
linkTypesget, list
mappingssuggest
objectsget, list, neighbors, query
ontologieslist
proposalsget, list
rdfexport, import
revisionsresolve
searchquery
typesget, list
watchesdispatches.claim, dispatches.settle, evaluate, list

Error contract

Typed errorHTTP
APPROVAL_REQUIRED409
BRANCH_BASE_STALE409
CONFLICT_DETECTED409
EXPORT_DENIED403
FORBIDDEN403
HISTORICAL_SOURCE_UNAVAILABLE422
HUMAN_REVIEW_REQUIRED422
IDEMPOTENCY_CONFLICT409
IDEMPOTENT_REPLAY200
MIGRATION_REQUIRED422
NOT_FOUND404
PROJECTION_LAGGING503
RECOMMENDATION_STALE409
REVISION_MISMATCH409
RULES_REJECTED422
SHAPE_VIOLATION422
SOURCE_READ_UNAVAILABLE503
STALE_READ_SET409
UNAUTHORIZED401
VALIDATION_FAILED400

Capacités absentes, pannes et le « pas encore » du noyau

Trois familles de rejets se ressemblent sur le fil et doivent être traitées différemment. Le SDK exporte un assistant par famille pour que les appelants ne redérivent jamais la règle depuis details.

Une liaison qui ne peut pas produire de lignes

bindingReadCapabilityReason(error) répond pourquoi une lecture de liaison ne peut pas renvoyer de page, ou null lorsque l'erreur est une vraie faute à présenter comme telle. Le verdict repose sur details.reasonCode — jamais sur la présence éventuelle d'un details.reason lisible par un humain :

Forme sur le filSignificationL'assistant renvoie
VALIDATION_FAILED (400) avec details.reasonCode: "BINDING_KIND_NOT_GOVERNED"Le type de liaison n'a pas de lecteur gouverné (memex_page aujourd'hui). Permanent pour cette version ; réessayer n'aide jamais.le message serveur — binding kind has no governed reader
SOURCE_READ_UNAVAILABLE (503) avec details.reasonCode: "BINDING_SOURCE_NOT_PROVISIONED" (plus details.reason quand le noyau dispose d'une phrase)La source n'est pas encore approvisionnée — p. ex. Table "aircraft_position" not registered — upload a CSV with that name in /tables. Seul un opérateur peut la corriger.details.reason, ou le message serveur si le noyau n'a envoyé aucune phrase
Toute autre forme, y compris un SOURCE_READ_UNAVAILABLE (503) ne portant qu'un details.reason en texte libreUne vraie panne. Réessayez.null

BINDING_READ_REASON_CODES est l'objet constant exporté (KIND_NOT_GOVERNED, SOURCE_NOT_PROVISIONED) ; branchez dessus plutôt que sur le littéral, et utilisez isBindingReadReasonCode(value) pour restreindre un code arrivé en unknown. Une surface de graphe ou de liste doit se dégrader autour des deux premières lignes (afficher la liaison comme ignorée avec la raison) et ne rendre que la troisième comme une erreur.

Un 503 portant un details.reason mais aucun details.reasonCode est une panne, pas une lacune de capacité. Les versions précédentes classaient sur la présence de la phrase : tout 503 qui transportait par hasard un texte de diagnostic cessait d'être réessayé. Le code est le contrat ; la phrase n'est qu'une courtoisie pour la personne qui lit l'écran.

Attendre une projection

Le noyau est event-sourced : une écriture est acquittée quand sa ligne de registre est validée, et les lectures la voient une fois le projecteur à jour. Une lecture émise juste après une écriture peut donc répondre NOT_FOUND ou PROJECTION_LAGGING pour une ressource qui existe. isTransientProjectionError(error) est vrai exactement pour ces deux codes — l'ensemble est TRANSIENT_PROJECTION_ERROR_CODES — et c'est le seul prédicat sur lequel une attente bornée doit réessayer. REVISION_MISMATCH n'en fait délibérément pas partie : il signifie que la prémisse de l'appelant a changé, et relire avec la même prémisse est une boucle, pas une récupération.

import { isTransientProjectionError } from "@scrydon/ontology-sdk/client";

const deadline = Date.now() + 5_000;
for (;;) {
  try {
    return await ontology.branches.get({ ontology, branch });
  } catch (error) {
    if (!isTransientProjectionError(error) || Date.now() >= deadline) throw error;
    await new Promise((resolve) => setTimeout(resolve, 100));
  }
}

Un lien dont les arêtes sont calculées, pas stockées

Dans graph.schema, un lien avec un join déclaré n'a pas de lignes d'arêtes stockées : ses arêtes sont jointes depuis les instances visibles au moment de la lecture. Un tel lien rapporte edgeCount: null avec reason: GRAPH_SCHEMA_LINK_REASONS.COMPUTED_FROM_DECLARED_JOIN, jamais edgeCount: 0 — un zéro se lirait comme « lié, mais aucune valeur de colonne ne correspond », ce qui appelle un autre remède. Le vocabulaire complet des raisons est GRAPH_SCHEMA_LINK_REASONS ; une lecture gouvernée en échec conserve SOURCE_COUNT_UNAVAILABLE.

Branchez sur les constantes publiées plutôt que sur les chaînes brutes — GRAPH_LINK_KIND pour le kind d'un lien (REFERENCE / PROXIMITY) et GRAPH_DIAGNOSTIC_STATUS pour le status d'un diagnostic de liaison (READY / NOT_READY / SKIPPED). Les deux sont exportées depuis @scrydon/ontology-sdk/client avec leurs types dérivés GraphLinkKind / GraphDiagnosticStatus, et le z.enum(...) du schéma de tranche de graphe lit lui-même dans ces constantes : un littéral retapé échoue au typage au lieu de désaccorder silencieusement une branche de votre interface.

GRAPH_LINK_KIND décrit un lien sur le fil. Utilisez LINK_TYPE_KINDS de @scrydon/sdk-authoring/ontologies quand vous discriminez un type de lien que vous avez rédigé dans un manifeste — les deux vocabulaires épellent aujourd'hui les mêmes mots et ne sont pas interchangeables.

Sur cette page

Sur cette page