From 1d70689bc3610afc1b34ae03902b8f62e928ec9f Mon Sep 17 00:00:00 2001 From: Michael Vorburger Date: Fri, 16 Feb 2024 14:52:04 +0100 Subject: [PATCH] feat (core): Generate JSON Schema from Enola Core Meta Proto during build This commit is part of the overall work I've done over the past few week-ends, see https://github.com/enola-dev/enola/pull/451 for history; it is only commited separately here for clearer future git log. --- .../enola/schemas/Connector.schema.json | 113 +++ docs/models/enola/schemas/Data.schema.json | 74 ++ .../enola/schemas/EntityKind.schema.json | 524 +++++++++++++ .../enola/schemas/EntityKinds.schema.json | 552 +++++++++++++ .../schemas/EntityRelationship.schema.json | 133 ++++ .../schemas/FileSystemRepository.schema.json | 54 ++ docs/models/enola/schemas/Import.schema.json | 41 + docs/models/enola/schemas/Link.schema.json | 75 ++ .../models/enola/schemas/Property.schema.json | 74 ++ docs/models/enola/schemas/Type.schema.json | 709 +++++++++++++++++ docs/models/enola/schemas/Types.schema.json | 739 ++++++++++++++++++ docs/use/connector/model-fs.yaml | 4 +- tools/git/test.bash | 26 + tools/protoc/protoc.bash | 51 ++ tools/test-ci/test.bash | 6 + 15 files changed, 3173 insertions(+), 2 deletions(-) create mode 100644 docs/models/enola/schemas/Connector.schema.json create mode 100644 docs/models/enola/schemas/Data.schema.json create mode 100644 docs/models/enola/schemas/EntityKind.schema.json create mode 100644 docs/models/enola/schemas/EntityKinds.schema.json create mode 100644 docs/models/enola/schemas/EntityRelationship.schema.json create mode 100644 docs/models/enola/schemas/FileSystemRepository.schema.json create mode 100644 docs/models/enola/schemas/Import.schema.json create mode 100644 docs/models/enola/schemas/Link.schema.json create mode 100644 docs/models/enola/schemas/Property.schema.json create mode 100644 docs/models/enola/schemas/Type.schema.json create mode 100644 docs/models/enola/schemas/Types.schema.json create mode 100755 tools/git/test.bash create mode 100755 tools/protoc/protoc.bash diff --git a/docs/models/enola/schemas/Connector.schema.json b/docs/models/enola/schemas/Connector.schema.json new file mode 100644 index 000000000..731cce11a --- /dev/null +++ b/docs/models/enola/schemas/Connector.schema.json @@ -0,0 +1,113 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Connector", + "definitions": { + "Connector": { + "properties": { + "error": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Always fails with this error message (for testing, only). TODO Remove this again? This was really useful in earlier testing, only." + }, + "java_class": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Java class name for in-process connector on the Java classpath." + }, + "fs": { + "$ref": "#/definitions/dev.enola.core.meta.FileSystemRepository", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "title": "TODO java_guice lookup?", + "description": "TODO java_guice lookup?" + }, + "grpc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Invokes remote connector via gRPC. The \"connection string\" here is a target endpoint in hostname:port format. (It's NOT an URI, so there is no scheme:// nor any /path/ or #fragment.)" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Connector" + }, + "dev.enola.core.meta.FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + } + } +} diff --git a/docs/models/enola/schemas/Data.schema.json b/docs/models/enola/schemas/Data.schema.json new file mode 100644 index 000000000..4d698cfc4 --- /dev/null +++ b/docs/models/enola/schemas/Data.schema.json @@ -0,0 +1,74 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Data", + "definitions": { + "Data": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + }, + "type_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The fully qualified name of the (root) Protocol Buffer Message; see https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Data" + } + } +} diff --git a/docs/models/enola/schemas/EntityKind.schema.json b/docs/models/enola/schemas/EntityKind.schema.json new file mode 100644 index 000000000..145ca0d7e --- /dev/null +++ b/docs/models/enola/schemas/EntityKind.schema.json @@ -0,0 +1,524 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/EntityKind", + "definitions": { + "EntityKind": { + "properties": { + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID. The ns may be filled in by the reader, if omitted in *-model.textproto. The entity is the name of THIS EntityKind! This is typically never changed anymore after initial creation. The path contains' the segments' names (here, whereas in Entity it's the \"values\")." + }, + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label of entity, may be several words, any case. This can easily be changed at any time." + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the name in UIs, if there is no logo." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "doc_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "related": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.EntityRelationship", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of related Entities. The string keys here match Entity#related's." + }, + "link": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Link", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of URL links. The string keys here match Entity#links's." + }, + "data": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Data", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of data about the Entity, in machine readable form. The string keys here match Entity#data's." + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Kind", + "description": "Kind of an Entity, as in message Entity." + }, + "dev.enola.core.ID": { + "properties": { + "ns": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Namespace. Serves to distinguish same entity names (below). This is optional if in your use of Enola you avoid name conflicts. It's like in C# or \"package\" in Java or Go or the xmlns: from XML Schema, or whatever the hell confusing thing ;) that Python is doing about this. Validated to only contain [a-z0-9_.] characters, so it's safe in URLs. By convention can contain '.' for sub-namespacing, but does not have to. The namespace of an Entity is always the same as its EntityKind." + }, + "entity": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Entity Kind Name. This is mandatory and thus always present. This refers to an EntityKind and not an individual Entity, despite the name. (In practice this is just shorter and clearer for people to understand.) Validated to only contain [a-z0-9_] characters, so it's safe in URLs." + }, + "paths": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "Path. This is mandatory and thus always present with at least 1 element. Think of this as what would typically uniquely identify this entity IRL; e.g. a \"hostname\" or some UUID or a S/N or whatever is its \"primary key\". Validated to only contain [a-z0-9_-.] characters, so it's safe in URLs. (This restriction could in theory be relaxed, if there was a strong need to support it; as long as sufficient test coverage is added for correct encoding in URIs, see https://en.m.wikipedia.org/wiki/URL_encoding.) Multiple \"segments\" are supported for \"composed keys\", for example a network/context/namespace/name kind of ID." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Id", + "description": "TODO Replace this with //docs/concepts/uri.md! ID of an Entity known to Enola, fully qualified. Can be formatted to and parsed from several different string text forms, see Java class dev.enola.core.IDs.java" + }, + "dev.enola.core.meta.Connector": { + "properties": { + "error": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Always fails with this error message (for testing, only). TODO Remove this again? This was really useful in earlier testing, only." + }, + "java_class": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Java class name for in-process connector on the Java classpath." + }, + "fs": { + "$ref": "#/definitions/dev.enola.core.meta.FileSystemRepository", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "title": "TODO java_guice lookup?", + "description": "TODO java_guice lookup?" + }, + "grpc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Invokes remote connector via gRPC. The \"connection string\" here is a target endpoint in hostname:port format. (It's NOT an URI, so there is no scheme:// nor any /path/ or #fragment.)" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Connector" + }, + "dev.enola.core.meta.Data": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + }, + "type_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The fully qualified name of the (root) Protocol Buffer Message; see https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Data" + }, + "dev.enola.core.meta.EntityRelationship": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID reference to another Entity. This ID's ns/entity/paths fields can contain a template, like Link#uri_template. Alternatively, this can be left empty, and set by connectors." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Relationship", + "description": "Entity#related map model; its key is the same as this in EntityKind#related." + }, + "dev.enola.core.meta.FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + }, + "dev.enola.core.meta.Link": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "uri_template": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "URI template, to create URL. As an ID URI Template (RFC 6570); see https://en.wikipedia.org/wiki/URI_Template. The available variables are the ID's path parameters, as well as a special proto.* which allows to declaratively create links out of the Any proto (instead of coding link generation in the service; which is always still also possible)." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Link", + "description": "Entity#link map model; its key is the same as this in EntityKind#link." + } + } +} diff --git a/docs/models/enola/schemas/EntityKinds.schema.json b/docs/models/enola/schemas/EntityKinds.schema.json new file mode 100644 index 000000000..87330b307 --- /dev/null +++ b/docs/models/enola/schemas/EntityKinds.schema.json @@ -0,0 +1,552 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/EntityKinds", + "definitions": { + "EntityKinds": { + "properties": { + "kinds": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.EntityKind" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Kinds" + }, + "dev.enola.core.ID": { + "properties": { + "ns": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Namespace. Serves to distinguish same entity names (below). This is optional if in your use of Enola you avoid name conflicts. It's like in C# or \"package\" in Java or Go or the xmlns: from XML Schema, or whatever the hell confusing thing ;) that Python is doing about this. Validated to only contain [a-z0-9_.] characters, so it's safe in URLs. By convention can contain '.' for sub-namespacing, but does not have to. The namespace of an Entity is always the same as its EntityKind." + }, + "entity": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Entity Kind Name. This is mandatory and thus always present. This refers to an EntityKind and not an individual Entity, despite the name. (In practice this is just shorter and clearer for people to understand.) Validated to only contain [a-z0-9_] characters, so it's safe in URLs." + }, + "paths": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "Path. This is mandatory and thus always present with at least 1 element. Think of this as what would typically uniquely identify this entity IRL; e.g. a \"hostname\" or some UUID or a S/N or whatever is its \"primary key\". Validated to only contain [a-z0-9_-.] characters, so it's safe in URLs. (This restriction could in theory be relaxed, if there was a strong need to support it; as long as sufficient test coverage is added for correct encoding in URIs, see https://en.m.wikipedia.org/wiki/URL_encoding.) Multiple \"segments\" are supported for \"composed keys\", for example a network/context/namespace/name kind of ID." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Id", + "description": "TODO Replace this with //docs/concepts/uri.md! ID of an Entity known to Enola, fully qualified. Can be formatted to and parsed from several different string text forms, see Java class dev.enola.core.IDs.java" + }, + "dev.enola.core.meta.Connector": { + "properties": { + "error": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Always fails with this error message (for testing, only). TODO Remove this again? This was really useful in earlier testing, only." + }, + "java_class": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Java class name for in-process connector on the Java classpath." + }, + "fs": { + "$ref": "#/definitions/dev.enola.core.meta.FileSystemRepository", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "title": "TODO java_guice lookup?", + "description": "TODO java_guice lookup?" + }, + "grpc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Invokes remote connector via gRPC. The \"connection string\" here is a target endpoint in hostname:port format. (It's NOT an URI, so there is no scheme:// nor any /path/ or #fragment.)" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Connector" + }, + "dev.enola.core.meta.Data": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + }, + "type_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The fully qualified name of the (root) Protocol Buffer Message; see https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Data" + }, + "dev.enola.core.meta.EntityKind": { + "properties": { + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID. The ns may be filled in by the reader, if omitted in *-model.textproto. The entity is the name of THIS EntityKind! This is typically never changed anymore after initial creation. The path contains' the segments' names (here, whereas in Entity it's the \"values\")." + }, + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label of entity, may be several words, any case. This can easily be changed at any time." + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the name in UIs, if there is no logo." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "doc_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "related": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.EntityRelationship", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of related Entities. The string keys here match Entity#related's." + }, + "link": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Link", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of URL links. The string keys here match Entity#links's." + }, + "data": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Data", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of data about the Entity, in machine readable form. The string keys here match Entity#data's." + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Kind", + "description": "Kind of an Entity, as in message Entity." + }, + "dev.enola.core.meta.EntityRelationship": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID reference to another Entity. This ID's ns/entity/paths fields can contain a template, like Link#uri_template. Alternatively, this can be left empty, and set by connectors." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Relationship", + "description": "Entity#related map model; its key is the same as this in EntityKind#related." + }, + "dev.enola.core.meta.FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + }, + "dev.enola.core.meta.Link": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "uri_template": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "URI template, to create URL. As an ID URI Template (RFC 6570); see https://en.wikipedia.org/wiki/URI_Template. The available variables are the ID's path parameters, as well as a special proto.* which allows to declaratively create links out of the Any proto (instead of coding link generation in the service; which is always still also possible)." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Link", + "description": "Entity#link map model; its key is the same as this in EntityKind#link." + } + } +} diff --git a/docs/models/enola/schemas/EntityRelationship.schema.json b/docs/models/enola/schemas/EntityRelationship.schema.json new file mode 100644 index 000000000..b83e2318e --- /dev/null +++ b/docs/models/enola/schemas/EntityRelationship.schema.json @@ -0,0 +1,133 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/EntityRelationship", + "definitions": { + "EntityRelationship": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID reference to another Entity. This ID's ns/entity/paths fields can contain a template, like Link#uri_template. Alternatively, this can be left empty, and set by connectors." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Relationship", + "description": "Entity#related map model; its key is the same as this in EntityKind#related." + }, + "dev.enola.core.ID": { + "properties": { + "ns": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Namespace. Serves to distinguish same entity names (below). This is optional if in your use of Enola you avoid name conflicts. It's like in C# or \"package\" in Java or Go or the xmlns: from XML Schema, or whatever the hell confusing thing ;) that Python is doing about this. Validated to only contain [a-z0-9_.] characters, so it's safe in URLs. By convention can contain '.' for sub-namespacing, but does not have to. The namespace of an Entity is always the same as its EntityKind." + }, + "entity": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Entity Kind Name. This is mandatory and thus always present. This refers to an EntityKind and not an individual Entity, despite the name. (In practice this is just shorter and clearer for people to understand.) Validated to only contain [a-z0-9_] characters, so it's safe in URLs." + }, + "paths": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "Path. This is mandatory and thus always present with at least 1 element. Think of this as what would typically uniquely identify this entity IRL; e.g. a \"hostname\" or some UUID or a S/N or whatever is its \"primary key\". Validated to only contain [a-z0-9_-.] characters, so it's safe in URLs. (This restriction could in theory be relaxed, if there was a strong need to support it; as long as sufficient test coverage is added for correct encoding in URIs, see https://en.m.wikipedia.org/wiki/URL_encoding.) Multiple \"segments\" are supported for \"composed keys\", for example a network/context/namespace/name kind of ID." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Id", + "description": "TODO Replace this with //docs/concepts/uri.md! ID of an Entity known to Enola, fully qualified. Can be formatted to and parsed from several different string text forms, see Java class dev.enola.core.IDs.java" + } + } +} diff --git a/docs/models/enola/schemas/FileSystemRepository.schema.json b/docs/models/enola/schemas/FileSystemRepository.schema.json new file mode 100644 index 000000000..cda9d3618 --- /dev/null +++ b/docs/models/enola/schemas/FileSystemRepository.schema.json @@ -0,0 +1,54 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/FileSystemRepository", + "definitions": { + "FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + } + } +} diff --git a/docs/models/enola/schemas/Import.schema.json b/docs/models/enola/schemas/Import.schema.json new file mode 100644 index 000000000..d05bdd76f --- /dev/null +++ b/docs/models/enola/schemas/Import.schema.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Import", + "definitions": { + "Import": { + "properties": { + "types": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "URLs from where to load additional referenced Types." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Import" + } + } +} diff --git a/docs/models/enola/schemas/Link.schema.json b/docs/models/enola/schemas/Link.schema.json new file mode 100644 index 000000000..f154ca80c --- /dev/null +++ b/docs/models/enola/schemas/Link.schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Link", + "definitions": { + "Link": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "uri_template": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "URI template, to create URL. As an ID URI Template (RFC 6570); see https://en.wikipedia.org/wiki/URI_Template. The available variables are the ID's path parameters, as well as a special proto.* which allows to declaratively create links out of the Any proto (instead of coding link generation in the service; which is always still also possible)." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Link", + "description": "Entity#link map model; its key is the same as this in EntityKind#link." + } + } +} diff --git a/docs/models/enola/schemas/Property.schema.json b/docs/models/enola/schemas/Property.schema.json new file mode 100644 index 000000000..dc1ae540f --- /dev/null +++ b/docs/models/enola/schemas/Property.schema.json @@ -0,0 +1,74 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Property", + "definitions": { + "Property": { + "properties": { + "id": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "integer" + } + ] + }, + "link": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "title": "Type of Property, as Name of another Type.\n TODO Re-consider this... this is wrong, because Property is Types sharable.\n string type = 2 [(dev.enola.type) = \"enola.dev/type\"];", + "description": "Type of Property, as Name of another Type. TODO Re-consider this... this is wrong, because Property is Types sharable. string type = 2 [(dev.enola.type) = \"enola.dev/type\"]; Link to something related. Intended both for human consumption in a UI, as well as machine readable linked data relationships. Typically a Template of an (HTML a/href-like) HTTP URL, or enola: URI. Template parameters refer to other properties of the Type." + }, + "labels": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Human readable label of this property, may be several words, any case. This is a map where the key is an IETF [BCP 47](https://www.rfc-editor.org/info/bcp47) \"language code\" (like \"en\" or \"de-CH\") and the value is text in that language. These can easily be changed at any time without breaking anything in Enola." + }, + "doc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's location - from where a UI will serve it). TODO Is this a [(dev.enola.type) = \"enola.dev/url\"]? Really??" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Property" + } + } +} diff --git a/docs/models/enola/schemas/Type.schema.json b/docs/models/enola/schemas/Type.schema.json new file mode 100644 index 000000000..33d4e1877 --- /dev/null +++ b/docs/models/enola/schemas/Type.schema.json @@ -0,0 +1,709 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Type", + "definitions": { + "Type": { + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short technical name of this Type. Must be unique within the environment this Enola instance operates. Publicly, using something that looks like an IRI/URI/URL is a simple way for uniqueness. For example, \"your.org/something\" (which is technically a relative URI, by chance). This string is NOT (necessarily) a valid URL; e.g. you (generally) cannot \"http GET your.org/something\". As a convenience for humans which type this into their web browser, your.org MAY set up a \"redirector\" which responds with a 30x to somewhere \"interesting\" for a human (not a machine), but that's just \"nice\", nothing more. Enola will never use it as anything else than simply a unique string." + }, + "uri": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "title": "URL of this Type.\n For example, \"https://demo.enola.dev/type/enola.dev/Person\".\n You *CAN* http GET this URL. An Enola server will return a HTML page or\n JSON or something. This is NOT set by the author of the Type, but at\n runtime. It is based on the name.\n TODO string url = 3 [(dev.enola.type) = \"enola.dev/url\"];", + "description": "URL of this Type. For example, \"https://demo.enola.dev/type/enola.dev/Person\". You *CAN* http GET this URL. An Enola server will return a HTML page or JSON or something. This is NOT set by the author of the Type, but at runtime. It is based on the name. TODO string url = 3 [(dev.enola.type) = \"enola.dev/url\"]; URI Template of instances of this Type. For example, \"hello/{message}\" - where the parameter \"message\" refers to a property; so instances would be e.g. \"hello/world\" and \"hello/planets\"." + }, + "labels": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Properties of this Type.\n TODO This needs to be Reference to a Property, not a contained Property...\n TODO TBD! map\u003cstring, Property\u003e properties = 5;", + "description": "Properties of this Type. TODO This needs to be Reference to a Property, not a contained Property... TODO TBD! map\u003cstring, Property\u003e properties = 5; Human readable label of this type, may be several words, any case. This is a map where the key is an IETF [BCP 47](https://www.rfc-editor.org/info/bcp47) \"language code\" (like \"en\" or \"de-CH\") and the value is text in that language. These can easily be changed at any time without breaking anything in Enola." + }, + "doc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's location - from where a UI will serve it). TODO Is this a [(dev.enola.type) = \"enola.dev/url\"]? Really??" + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the label in UIs, if there is no logo. This is not necessarily unique." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's location - from where a UI will serve it)." + }, + "legacy": { + "$ref": "#/definitions/dev.enola.core.meta.EntityKind", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "EntityKind. This is from the original Enola design, and may later be removed. TODO Should this really be embedded? Really? Probably better an ID as reference? Good test! string entity_kind = 10 [(dev.enola.type) = \"enola.dev/EntityKind\"];" + }, + "proto": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Protocol Buffers Message. For example, \"google.protobuf.Timestamp\". TODO We need to be able to \"annotate\" (?) Proto descriptors for LD..." + }, + "string": { + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Empty", + "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }" + }, + "binary": { + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Empty", + "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }" + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "java": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "javas": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Type", + "description": "Unique ID of this Type. For example, \"d19974d6-0695-458d-bdd4-3ad89578db92\". This \"provides a relatively short yet unambiguous way to refer to a type\", as \"fully-qualified type names may be large and waste space when transmitted on the wire\", and it \"lets programmers change the symbolic name while keeping a fixed ID\" (inspired by https://capnproto.org/language.html#unique-ids). It's recommended that this is set by the human author of the Type, but if it's not, it will be automatically generated by hashing the name. (This defeats the purpose of a \"permanent\" ID - but it's at least possible to set it later, if a name is ever changed.) TODO \"Nicely render\" this in the Web UI, using dev.enola.core.ByteSeq. TODO Do we *really* this, actually? bytes id = 1 [(dev.enola.type) = \"enola.dev/id\"];" + }, + "dev.enola.core.ID": { + "properties": { + "ns": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Namespace. Serves to distinguish same entity names (below). This is optional if in your use of Enola you avoid name conflicts. It's like in C# or \"package\" in Java or Go or the xmlns: from XML Schema, or whatever the hell confusing thing ;) that Python is doing about this. Validated to only contain [a-z0-9_.] characters, so it's safe in URLs. By convention can contain '.' for sub-namespacing, but does not have to. The namespace of an Entity is always the same as its EntityKind." + }, + "entity": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Entity Kind Name. This is mandatory and thus always present. This refers to an EntityKind and not an individual Entity, despite the name. (In practice this is just shorter and clearer for people to understand.) Validated to only contain [a-z0-9_] characters, so it's safe in URLs." + }, + "paths": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "Path. This is mandatory and thus always present with at least 1 element. Think of this as what would typically uniquely identify this entity IRL; e.g. a \"hostname\" or some UUID or a S/N or whatever is its \"primary key\". Validated to only contain [a-z0-9_-.] characters, so it's safe in URLs. (This restriction could in theory be relaxed, if there was a strong need to support it; as long as sufficient test coverage is added for correct encoding in URIs, see https://en.m.wikipedia.org/wiki/URL_encoding.) Multiple \"segments\" are supported for \"composed keys\", for example a network/context/namespace/name kind of ID." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Id", + "description": "TODO Replace this with //docs/concepts/uri.md! ID of an Entity known to Enola, fully qualified. Can be formatted to and parsed from several different string text forms, see Java class dev.enola.core.IDs.java" + }, + "dev.enola.core.meta.Connector": { + "properties": { + "error": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Always fails with this error message (for testing, only). TODO Remove this again? This was really useful in earlier testing, only." + }, + "java_class": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Java class name for in-process connector on the Java classpath." + }, + "fs": { + "$ref": "#/definitions/dev.enola.core.meta.FileSystemRepository", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "title": "TODO java_guice lookup?", + "description": "TODO java_guice lookup?" + }, + "grpc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Invokes remote connector via gRPC. The \"connection string\" here is a target endpoint in hostname:port format. (It's NOT an URI, so there is no scheme:// nor any /path/ or #fragment.)" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Connector" + }, + "dev.enola.core.meta.Data": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + }, + "type_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The fully qualified name of the (root) Protocol Buffer Message; see https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Data" + }, + "dev.enola.core.meta.EntityKind": { + "properties": { + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID. The ns may be filled in by the reader, if omitted in *-model.textproto. The entity is the name of THIS EntityKind! This is typically never changed anymore after initial creation. The path contains' the segments' names (here, whereas in Entity it's the \"values\")." + }, + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label of entity, may be several words, any case. This can easily be changed at any time." + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the name in UIs, if there is no logo." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "doc_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "related": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.EntityRelationship", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of related Entities. The string keys here match Entity#related's." + }, + "link": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Link", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of URL links. The string keys here match Entity#links's." + }, + "data": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Data", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of data about the Entity, in machine readable form. The string keys here match Entity#data's." + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Kind", + "description": "Kind of an Entity, as in message Entity." + }, + "dev.enola.core.meta.EntityRelationship": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID reference to another Entity. This ID's ns/entity/paths fields can contain a template, like Link#uri_template. Alternatively, this can be left empty, and set by connectors." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Relationship", + "description": "Entity#related map model; its key is the same as this in EntityKind#related." + }, + "dev.enola.core.meta.FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + }, + "dev.enola.core.meta.Link": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "uri_template": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "URI template, to create URL. As an ID URI Template (RFC 6570); see https://en.wikipedia.org/wiki/URI_Template. The available variables are the ID's path parameters, as well as a special proto.* which allows to declaratively create links out of the Any proto (instead of coding link generation in the service; which is always still also possible)." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Link", + "description": "Entity#link map model; its key is the same as this in EntityKind#link." + } + } +} diff --git a/docs/models/enola/schemas/Types.schema.json b/docs/models/enola/schemas/Types.schema.json new file mode 100644 index 000000000..07ab0ab7d --- /dev/null +++ b/docs/models/enola/schemas/Types.schema.json @@ -0,0 +1,739 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "$ref": "#/definitions/Types", + "definitions": { + "Types": { + "properties": { + "types": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Type" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "TODO Implement, with @Test! Import import = 1;" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Types", + "description": "Types are a collection of enola:dev.enola.core.meta.Type. This is kind of like a https://en.wikipedia.org/wiki/Domain_of_discourse#Universe_of_discourse or the https://en.wikipedia.org/wiki/Universe_(mathematics)." + }, + "dev.enola.core.ID": { + "properties": { + "ns": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Namespace. Serves to distinguish same entity names (below). This is optional if in your use of Enola you avoid name conflicts. It's like in C# or \"package\" in Java or Go or the xmlns: from XML Schema, or whatever the hell confusing thing ;) that Python is doing about this. Validated to only contain [a-z0-9_.] characters, so it's safe in URLs. By convention can contain '.' for sub-namespacing, but does not have to. The namespace of an Entity is always the same as its EntityKind." + }, + "entity": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Entity Kind Name. This is mandatory and thus always present. This refers to an EntityKind and not an individual Entity, despite the name. (In practice this is just shorter and clearer for people to understand.) Validated to only contain [a-z0-9_] characters, so it's safe in URLs." + }, + "paths": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ], + "description": "Path. This is mandatory and thus always present with at least 1 element. Think of this as what would typically uniquely identify this entity IRL; e.g. a \"hostname\" or some UUID or a S/N or whatever is its \"primary key\". Validated to only contain [a-z0-9_-.] characters, so it's safe in URLs. (This restriction could in theory be relaxed, if there was a strong need to support it; as long as sufficient test coverage is added for correct encoding in URIs, see https://en.m.wikipedia.org/wiki/URL_encoding.) Multiple \"segments\" are supported for \"composed keys\", for example a network/context/namespace/name kind of ID." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Id", + "description": "TODO Replace this with //docs/concepts/uri.md! ID of an Entity known to Enola, fully qualified. Can be formatted to and parsed from several different string text forms, see Java class dev.enola.core.IDs.java" + }, + "dev.enola.core.meta.Connector": { + "properties": { + "error": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Always fails with this error message (for testing, only). TODO Remove this again? This was really useful in earlier testing, only." + }, + "java_class": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Java class name for in-process connector on the Java classpath." + }, + "fs": { + "$ref": "#/definitions/dev.enola.core.meta.FileSystemRepository", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "title": "TODO java_guice lookup?", + "description": "TODO java_guice lookup?" + }, + "grpc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Invokes remote connector via gRPC. The \"connection string\" here is a target endpoint in hostname:port format. (It's NOT an URI, so there is no scheme:// nor any /path/ or #fragment.)" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Connector" + }, + "dev.enola.core.meta.Data": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + }, + "type_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The fully qualified name of the (root) Protocol Buffer Message; see https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/any.proto" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Data" + }, + "dev.enola.core.meta.EntityKind": { + "properties": { + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID. The ns may be filled in by the reader, if omitted in *-model.textproto. The entity is the name of THIS EntityKind! This is typically never changed anymore after initial creation. The path contains' the segments' names (here, whereas in Entity it's the \"values\")." + }, + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label of entity, may be several words, any case. This can easily be changed at any time." + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the name in UIs, if there is no logo." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "doc_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's textproto file location - from where a UI will serve it)." + }, + "related": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.EntityRelationship", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of related Entities. The string keys here match Entity#related's." + }, + "link": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Link", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of URL links. The string keys here match Entity#links's." + }, + "data": { + "additionalProperties": { + "$ref": "#/definitions/dev.enola.core.meta.Data", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Description of data about the Entity, in machine readable form. The string keys here match Entity#data's." + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Kind", + "description": "Kind of an Entity, as in message Entity." + }, + "dev.enola.core.meta.EntityRelationship": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "id": { + "$ref": "#/definitions/dev.enola.core.ID", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "ID reference to another Entity. This ID's ns/entity/paths fields can contain a template, like Link#uri_template. Alternatively, this can be left empty, and set by connectors." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Entity Relationship", + "description": "Entity#related map model; its key is the same as this in EntityKind#related." + }, + "dev.enola.core.meta.FileSystemRepository": { + "properties": { + "path": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "format": { + "enum": [ + "FORMAT_UNSPECIFIED", + 0, + "FORMAT_TEXTPROTO", + 1, + "FORMAT_YAML", + 2, + "FORMAT_JSON", + 3 + ], + "oneOf": [ + { + "type": "string" + }, + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Format" + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "File System Repository" + }, + "dev.enola.core.meta.Link": { + "properties": { + "label": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Human readable label, may be shown on a UI." + }, + "description": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short 1-2 sentences of description, may be shown on a UI e.g. as tooltip." + }, + "uri_template": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "URI template, to create URL. As an ID URI Template (RFC 6570); see https://en.wikipedia.org/wiki/URI_Template. The available variables are the ID's path parameters, as well as a special proto.* which allows to declaratively create links out of the Any proto (instead of coding link generation in the service; which is always still also possible)." + }, + "tags": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "description": "Tags." + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Link", + "description": "Entity#link map model; its key is the same as this in EntityKind#link." + }, + "dev.enola.core.meta.Type": { + "properties": { + "name": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Short technical name of this Type. Must be unique within the environment this Enola instance operates. Publicly, using something that looks like an IRI/URI/URL is a simple way for uniqueness. For example, \"your.org/something\" (which is technically a relative URI, by chance). This string is NOT (necessarily) a valid URL; e.g. you (generally) cannot \"http GET your.org/something\". As a convenience for humans which type this into their web browser, your.org MAY set up a \"redirector\" which responds with a 30x to somewhere \"interesting\" for a human (not a machine), but that's just \"nice\", nothing more. Enola will never use it as anything else than simply a unique string." + }, + "uri": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "title": "URL of this Type.\n For example, \"https://demo.enola.dev/type/enola.dev/Person\".\n You *CAN* http GET this URL. An Enola server will return a HTML page or\n JSON or something. This is NOT set by the author of the Type, but at\n runtime. It is based on the name.\n TODO string url = 3 [(dev.enola.type) = \"enola.dev/url\"];", + "description": "URL of this Type. For example, \"https://demo.enola.dev/type/enola.dev/Person\". You *CAN* http GET this URL. An Enola server will return a HTML page or JSON or something. This is NOT set by the author of the Type, but at runtime. It is based on the name. TODO string url = 3 [(dev.enola.type) = \"enola.dev/url\"]; URI Template of instances of this Type. For example, \"hello/{message}\" - where the parameter \"message\" refers to a property; so instances would be e.g. \"hello/world\" and \"hello/planets\"." + }, + "labels": { + "additionalProperties": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Properties of this Type.\n TODO This needs to be Reference to a Property, not a contained Property...\n TODO TBD! map\u003cstring, Property\u003e properties = 5;", + "description": "Properties of this Type. TODO This needs to be Reference to a Property, not a contained Property... TODO TBD! map\u003cstring, Property\u003e properties = 5; Human readable label of this type, may be several words, any case. This is a map where the key is an IETF [BCP 47](https://www.rfc-editor.org/info/bcp47) \"language code\" (like \"en\" or \"de-CH\") and the value is text in that language. These can easily be changed at any time without breaking anything in Enola." + }, + "doc": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Documentation description (as URL; either absolute, or URL relative to the model's location - from where a UI will serve it). TODO Is this a [(dev.enola.type) = \"enola.dev/url\"]? Really??" + }, + "emoji": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "The Emoji shown as prefix to the label in UIs, if there is no logo. This is not necessarily unique." + }, + "logo_url": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Logo (as URL; either absolute, or URL relative to the model's location - from where a UI will serve it)." + }, + "legacy": { + "$ref": "#/definitions/dev.enola.core.meta.EntityKind", + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + {} + ], + "description": "EntityKind. This is from the original Enola design, and may later be removed. TODO Should this really be embedded? Really? Probably better an ID as reference? Good test! string entity_kind = 10 [(dev.enola.type) = \"enola.dev/EntityKind\"];" + }, + "proto": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ], + "description": "Protocol Buffers Message. For example, \"google.protobuf.Timestamp\". TODO We need to be able to \"annotate\" (?) Proto descriptors for LD..." + }, + "string": { + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Empty", + "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }" + }, + "binary": { + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Empty", + "description": "A generic empty message that you can re-use to avoid defining duplicated empty messages in your APIs. A typical example is to use it as the request or the response type of an API method. For instance: service Foo { rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); }" + }, + "connectors": { + "items": { + "$ref": "#/definitions/dev.enola.core.meta.Connector" + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + }, + "java": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "javas": { + "items": { + "oneOf": [ + { + "type": "null" + }, + { + "type": "string" + } + ] + }, + "oneOf": [ + { + "type": "null" + }, + { + "type": "array" + } + ] + } + }, + "additionalProperties": false, + "oneOf": [ + { + "type": "null" + }, + { + "type": "object" + } + ], + "title": "Type", + "description": "Unique ID of this Type. For example, \"d19974d6-0695-458d-bdd4-3ad89578db92\". This \"provides a relatively short yet unambiguous way to refer to a type\", as \"fully-qualified type names may be large and waste space when transmitted on the wire\", and it \"lets programmers change the symbolic name while keeping a fixed ID\" (inspired by https://capnproto.org/language.html#unique-ids). It's recommended that this is set by the human author of the Type, but if it's not, it will be automatically generated by hashing the name. (This defeats the purpose of a \"permanent\" ID - but it's at least possible to set it later, if a name is ever changed.) TODO \"Nicely render\" this in the Web UI, using dev.enola.core.ByteSeq. TODO Do we *really* this, actually? bytes id = 1 [(dev.enola.type) = \"enola.dev/id\"];" + } + } +} diff --git a/docs/use/connector/model-fs.yaml b/docs/use/connector/model-fs.yaml index a918bbf39..9493c711e 100644 --- a/docs/use/connector/model-fs.yaml +++ b/docs/use/connector/model-fs.yaml @@ -1,9 +1,9 @@ kinds: - - id: { ns: demo, entity: book_kind, paths: [ isbn ] } + - id: { ns: demo, entity: book_kind, paths: [isbn] } link: google: label: Google Book Search - uriTemplate: "https://www.google.com/search?tbm=bks&q={path.isbn}" + uriTemplate: "https://www.google.com/search?tbm=bks&q=isbn:{path.isbn}" data: authors: label: Names of the authors of this book. diff --git a/tools/git/test.bash b/tools/git/test.bash new file mode 100755 index 000000000..7b4680208 --- /dev/null +++ b/tools/git/test.bash @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright 2023-2024 The Enola Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set -euox pipefail + +# https://stackoverflow.com/a/2659808 + +git status + +git diff --exit-code + +# TODO Also fail if there are untracked new files (which are not on .gitignore) diff --git a/tools/protoc/protoc.bash b/tools/protoc/protoc.bash new file mode 100755 index 000000000..b272f2f3c --- /dev/null +++ b/tools/protoc/protoc.bash @@ -0,0 +1,51 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright 2023-2024 The Enola Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# TODO Transform this into a Bazel target instead? +# Or an enola exec: resource? +# (Or no need, for either?) +set -euox pipefail + +# TODO Make this using Bazel with a BUILD instead +# (It's kind of dumb how as-is there is a protoc "in" Bazel and a separate one.) + +if ! [ -x "$(command -v protoc)" ]; then + # NB: protoc is *also* installed by .devcontainer/devcontainer.json + # (e.g. from https://github.com/protocolbuffers/protobuf/releases) + sudo apt install -y protobuf-compiler + # TODO Cache protoc installation on GitHub Action! #ci #speed +fi +protoc --version + +# https://github.com/chrusty/protoc-gen-jsonschema +if ! [ -x "$(command -v protoc-gen-jsonschema)" ]; then + # As always, it's NEVER a good idea to use @latest here, but always a fixed version + go install github.com/chrusty/protoc-gen-jsonschema/cmd/protoc-gen-jsonschema@1.4.1 +fi +protoc-gen-jsonschema --version + +PLUGIN=$(go env GOPATH)/bin/protoc-gen-jsonschema +protoc \ + --plugin="${PLUGIN}" \ + --jsonschema_opt=allow_null_values \ + --jsonschema_opt=file_extension=schema.json \ + --jsonschema_opt=disallow_additional_properties \ + --jsonschema_out=docs/models/enola/schemas/ \ + core/lib/src/main/java/dev/enola/core/meta/enola_meta.proto + +mkdir -pv ~/.npm/lib +npx --yes prettier --write docs/models/enola/schemas/*.json diff --git a/tools/test-ci/test.bash b/tools/test-ci/test.bash index a2ff327dd..f352ce9fa 100755 --- a/tools/test-ci/test.bash +++ b/tools/test-ci/test.bash @@ -21,5 +21,11 @@ set -euox pipefail ./test.bash +# TODO Run all this only when model inputs change +tools/protoc/protoc.bash + +# No files (which are not on .gitigore) should have been modified! +tools/git/test.bash + # Test distros: 1. End-user distributed executable fat über JAR, 2. Container Image tools/distro/test.bash