From 7514a16f3a9e95fad3343e41082e253b361ddaf8 Mon Sep 17 00:00:00 2001 From: alex-ketch Date: Wed, 16 Feb 2022 18:24:55 -0500 Subject: [PATCH] feat(Schema): Introduce Primitive type --- python/stencila/schema/types.py | 8 ++++++- r/R/types.R | 9 +++++++- rust/schema/src/schemas.rs | 3 ++- rust/schema/src/types.rs | 11 +++++++-- schema/schema/Node.schema.yaml | 10 ++++----- schema/schema/Primitive.schema.yaml | 14 ++++++++++++ schema/src/bindings/typescript.ts | 15 +++++++++---- schema/src/types.ts | 35 ++++++++++++++++------------- schema/src/util/guards.ts | 22 +++++++++--------- web/src/patches/json/index.test.ts | 18 +++++++++++++++ 10 files changed, 104 insertions(+), 41 deletions(-) create mode 100644 schema/schema/Primitive.schema.yaml diff --git a/python/stencila/schema/types.py b/python/stencila/schema/types.py index a3e13a4096..0d981e9a20 100644 --- a/python/stencila/schema/types.py +++ b/python/stencila/schema/types.py @@ -4520,7 +4520,13 @@ class CitationIntentEnumeration(Enum): """ Union type for all schema nodes, including primitives and entities """ -Node = Union["Entity", "ArrayValidator", "Article", "AudioObject", "BooleanValidator", "Brand", "CitationIntentEnumeration", "Cite", "CiteGroup", "Claim", "Code", "CodeBlock", "CodeChunk", "CodeError", "CodeExecutable", "CodeExpression", "CodeFragment", "Collection", "Comment", "ConstantValidator", "ContactPoint", "CreativeWork", "Datatable", "DatatableColumn", "Date", "DefinedTerm", "Delete", "Emphasis", "EnumValidator", "Enumeration", "Figure", "Function", "Grant", "Heading", "ImageObject", "Include", "IntegerValidator", "Link", "List", "ListItem", "Mark", "Math", "MathBlock", "MathFragment", "MediaObject", "MonetaryGrant", "NontextualAnnotation", "Note", "NumberValidator", "Organization", "Paragraph", "Parameter", "Periodical", "Person", "PostalAddress", "Product", "PropertyValue", "PublicationIssue", "PublicationVolume", "Quote", "QuoteBlock", "Review", "SoftwareApplication", "SoftwareEnvironment", "SoftwareSession", "SoftwareSourceCode", "StringValidator", "Strong", "Subscript", "Superscript", "Table", "TableCell", "TableRow", "ThematicBreak", "Thing", "TupleValidator", "Validator", "Variable", "VideoObject", "VolumeMount", None, "Boolean", "Integer", "Number", "String", "Object", "Array"] +Node = Union["Entity", "ArrayValidator", "Article", "AudioObject", "BooleanValidator", "Brand", "CitationIntentEnumeration", "Cite", "CiteGroup", "Claim", "Code", "CodeBlock", "CodeChunk", "CodeError", "CodeExecutable", "CodeExpression", "CodeFragment", "Collection", "Comment", "ConstantValidator", "ContactPoint", "CreativeWork", "Datatable", "DatatableColumn", "Date", "DefinedTerm", "Delete", "Emphasis", "EnumValidator", "Enumeration", "Figure", "Function", "Grant", "Heading", "ImageObject", "Include", "IntegerValidator", "Link", "List", "ListItem", "Mark", "Math", "MathBlock", "MathFragment", "MediaObject", "MonetaryGrant", "NontextualAnnotation", "Note", "NumberValidator", "Organization", "Paragraph", "Parameter", "Periodical", "Person", "PostalAddress", "Product", "PropertyValue", "PublicationIssue", "PublicationVolume", "Quote", "QuoteBlock", "Review", "SoftwareApplication", "SoftwareEnvironment", "SoftwareSession", "SoftwareSourceCode", "StringValidator", "Strong", "Subscript", "Superscript", "Table", "TableCell", "TableRow", "ThematicBreak", "Thing", "TupleValidator", "Validator", "Variable", "VideoObject", "VolumeMount", "Primitive", "Object", Array["Primitive"]] + + +""" +Union type for all primitives values +""" +Primitive = Union[None, "Boolean", "Integer", "Number", "String"] """ diff --git a/r/R/types.R b/r/R/types.R index 429f930656..222ce76ed5 100644 --- a/r/R/types.R +++ b/r/R/types.R @@ -4600,7 +4600,14 @@ MediaObjectTypes <- Union(MediaObject, AudioObject, ImageObject, VideoObject) #' #' @return A `list` of class `Union` describing valid subtypes of this type #' @export -Node <- Union(Entity, ArrayValidator, Article, AudioObject, BooleanValidator, Brand, CitationIntentEnumeration, Cite, CiteGroup, Claim, Code, CodeBlock, CodeChunk, CodeError, CodeExecutable, CodeExpression, CodeFragment, Collection, Comment, ConstantValidator, ContactPoint, CreativeWork, Datatable, DatatableColumn, Date, DefinedTerm, Delete, Emphasis, EnumValidator, Enumeration, Figure, Function, Grant, Heading, ImageObject, Include, IntegerValidator, Link, List, ListItem, Mark, Math, MathBlock, MathFragment, MediaObject, MonetaryGrant, NontextualAnnotation, Note, NumberValidator, Organization, Paragraph, Parameter, Periodical, Person, PostalAddress, Product, PropertyValue, PublicationIssue, PublicationVolume, Quote, QuoteBlock, Review, SoftwareApplication, SoftwareEnvironment, SoftwareSession, SoftwareSourceCode, StringValidator, Strong, Subscript, Superscript, Table, TableCell, TableRow, ThematicBreak, Thing, TupleValidator, Validator, Variable, VideoObject, VolumeMount, "NULL", "logical", "numeric", "character", "list", Array(Any())) +Node <- Union(Entity, ArrayValidator, Article, AudioObject, BooleanValidator, Brand, CitationIntentEnumeration, Cite, CiteGroup, Claim, Code, CodeBlock, CodeChunk, CodeError, CodeExecutable, CodeExpression, CodeFragment, Collection, Comment, ConstantValidator, ContactPoint, CreativeWork, Datatable, DatatableColumn, Date, DefinedTerm, Delete, Emphasis, EnumValidator, Enumeration, Figure, Function, Grant, Heading, ImageObject, Include, IntegerValidator, Link, List, ListItem, Mark, Math, MathBlock, MathFragment, MediaObject, MonetaryGrant, NontextualAnnotation, Note, NumberValidator, Organization, Paragraph, Parameter, Periodical, Person, PostalAddress, Product, PropertyValue, PublicationIssue, PublicationVolume, Quote, QuoteBlock, Review, SoftwareApplication, SoftwareEnvironment, SoftwareSession, SoftwareSourceCode, StringValidator, Strong, Subscript, Superscript, Table, TableCell, TableRow, ThematicBreak, Thing, TupleValidator, Validator, Variable, VideoObject, VolumeMount, Primitive, "list", Array(Primitive)) + + +#' Union type for all primitives values +#' +#' @return A `list` of class `Union` describing valid subtypes of this type +#' @export +Primitive <- Union("NULL", "logical", "numeric", "character") #' All type schemas that are derived from Thing diff --git a/rust/schema/src/schemas.rs b/rust/schema/src/schemas.rs index bf72f5c1b7..1a892b0ba2 100644 --- a/rust/schema/src/schemas.rs +++ b/rust/schema/src/schemas.rs @@ -61,7 +61,7 @@ pub const SCHEMAS: &[(&str, &str)] = &[ ("MediaObject", r#"{"title":"MediaObject","required":["type","contentUrl"],"examples":[{"type":"MediaObject","bitrate":"44","contentSize":"2","contentUrl":"http://www.example.com/file.mp3","encodingFormat":"audio/mpeg3","embedUrl":"http://www.example.com/full_size/file.mp3"}],"type":"object","propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","author":"authors","comment":"comments","date":"datePublished","editor":"editors","funder":"funders","keyword":"keywords","license":"licenses","maintainer":"maintainers","hasParts":"parts","part":"parts","citations":"references","reference":"references","headline":"title","encodingFormat":"mediaType"},"additionalProperties":false,"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"about":{"type":"array","items":{"$ref":"ThingTypes.schema.json"}},"authors":{"allOf":[{"parser":"scsi"},{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]}}],"aliases":["author"]},"comments":{"type":"array","items":{"$ref":"Comment.schema.json"},"aliases":["comment"]},"content":{"anyOf":[{"type":"array","items":{"$ref":"Node.schema.json"}},{"type":"string"}]},"dateCreated":{"allOf":[{"$ref":"Date.schema.json"}]},"dateReceived":{"allOf":[{"$ref":"Date.schema.json"}]},"dateAccepted":{"allOf":[{"$ref":"Date.schema.json"}]},"dateModified":{"allOf":[{"$ref":"Date.schema.json"}]},"datePublished":{"aliases":["date"],"allOf":[{"$ref":"Date.schema.json"}]},"editors":{"type":"array","items":{"$ref":"Person.schema.json"},"aliases":["editor"]},"funders":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["funder"]},"fundedBy":{"type":"array","items":{"anyOf":[{"$ref":"Grant.schema.json"},{"$ref":"MonetaryGrant.schema.json"}]}},"genre":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}]},"keywords":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}],"aliases":["keyword"]},"isPartOf":{"$ref":"CreativeWorkTypes.schema.json"},"licenses":{"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string","format":"uri"}]},"aliases":["license"]},"maintainers":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["maintainer"]},"parts":{"aliases":["hasParts","part"],"type":"array","items":{"$ref":"CreativeWorkTypes.schema.json"}},"publisher":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"references":{"aliases":["citations","reference"],"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string"}]}},"text":{"type":"string"},"title":{"aliases":["headline"],"anyOf":[{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"version":{"anyOf":[{"type":"string"},{"type":"number"}]},"bitrate":{"type":"number"},"contentSize":{"type":"number"},"contentUrl":{"type":"string"},"embedUrl":{"type":"string"},"mediaType":{"aliases":["encodingFormat"],"type":"string","pattern":"^\\w+/[-+.\\w]+$"}}}"#), ("MediaObjectTypes", r#"{"title":"MediaObjectTypes","anyOf":[{"$ref":"MediaObject.schema.json"},{"$ref":"AudioObject.schema.json"},{"$ref":"ImageObject.schema.json"},{"$ref":"VideoObject.schema.json"}]}"#), ("MonetaryGrant", r#"{"title":"MonetaryGrant","type":"object","propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","fundedItem":"fundedItems","sponsor":"sponsors","funder":"funders"},"additionalProperties":false,"required":["type"],"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"fundedItems":{"type":"array","items":{"$ref":"Thing.schema.json"},"aliases":["fundedItem"]},"sponsors":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["sponsor"]},"amounts":{"type":"number"},"funders":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["funder"]}}}"#), - ("Node", r#"{"title":"Node","anyOf":[{"$ref":"Entity.schema.json"},{"$ref":"ArrayValidator.schema.json"},{"$ref":"Article.schema.json"},{"$ref":"AudioObject.schema.json"},{"$ref":"BooleanValidator.schema.json"},{"$ref":"Brand.schema.json"},{"$ref":"CitationIntentEnumeration.schema.json"},{"$ref":"Cite.schema.json"},{"$ref":"CiteGroup.schema.json"},{"$ref":"Claim.schema.json"},{"$ref":"Code.schema.json"},{"$ref":"CodeBlock.schema.json"},{"$ref":"CodeChunk.schema.json"},{"$ref":"CodeError.schema.json"},{"$ref":"CodeExecutable.schema.json"},{"$ref":"CodeExpression.schema.json"},{"$ref":"CodeFragment.schema.json"},{"$ref":"Collection.schema.json"},{"$ref":"Comment.schema.json"},{"$ref":"ConstantValidator.schema.json"},{"$ref":"ContactPoint.schema.json"},{"$ref":"CreativeWork.schema.json"},{"$ref":"Datatable.schema.json"},{"$ref":"DatatableColumn.schema.json"},{"$ref":"Date.schema.json"},{"$ref":"DefinedTerm.schema.json"},{"$ref":"Delete.schema.json"},{"$ref":"Emphasis.schema.json"},{"$ref":"EnumValidator.schema.json"},{"$ref":"Enumeration.schema.json"},{"$ref":"Figure.schema.json"},{"$ref":"Function.schema.json"},{"$ref":"Grant.schema.json"},{"$ref":"Heading.schema.json"},{"$ref":"ImageObject.schema.json"},{"$ref":"Include.schema.json"},{"$ref":"IntegerValidator.schema.json"},{"$ref":"Link.schema.json"},{"$ref":"List.schema.json"},{"$ref":"ListItem.schema.json"},{"$ref":"Mark.schema.json"},{"$ref":"Math.schema.json"},{"$ref":"MathBlock.schema.json"},{"$ref":"MathFragment.schema.json"},{"$ref":"MediaObject.schema.json"},{"$ref":"MonetaryGrant.schema.json"},{"$ref":"NontextualAnnotation.schema.json"},{"$ref":"Note.schema.json"},{"$ref":"NumberValidator.schema.json"},{"$ref":"Organization.schema.json"},{"$ref":"Paragraph.schema.json"},{"$ref":"Parameter.schema.json"},{"$ref":"Periodical.schema.json"},{"$ref":"Person.schema.json"},{"$ref":"PostalAddress.schema.json"},{"$ref":"Product.schema.json"},{"$ref":"PropertyValue.schema.json"},{"$ref":"PublicationIssue.schema.json"},{"$ref":"PublicationVolume.schema.json"},{"$ref":"Quote.schema.json"},{"$ref":"QuoteBlock.schema.json"},{"$ref":"Review.schema.json"},{"$ref":"SoftwareApplication.schema.json"},{"$ref":"SoftwareEnvironment.schema.json"},{"$ref":"SoftwareSession.schema.json"},{"$ref":"SoftwareSourceCode.schema.json"},{"$ref":"StringValidator.schema.json"},{"$ref":"Strong.schema.json"},{"$ref":"Subscript.schema.json"},{"$ref":"Superscript.schema.json"},{"$ref":"Table.schema.json"},{"$ref":"TableCell.schema.json"},{"$ref":"TableRow.schema.json"},{"$ref":"ThematicBreak.schema.json"},{"$ref":"Thing.schema.json"},{"$ref":"TupleValidator.schema.json"},{"$ref":"Validator.schema.json"},{"$ref":"Variable.schema.json"},{"$ref":"VideoObject.schema.json"},{"$ref":"VolumeMount.schema.json"},{"$ref":"Null.schema.json"},{"$ref":"Boolean.schema.json"},{"$ref":"Integer.schema.json"},{"$ref":"Number.schema.json"},{"$ref":"String.schema.json"},{"$ref":"Object.schema.json"},{"$ref":"Array.schema.json"}]}"#), + ("Node", r#"{"title":"Node","anyOf":[{"$ref":"Entity.schema.json"},{"$ref":"ArrayValidator.schema.json"},{"$ref":"Article.schema.json"},{"$ref":"AudioObject.schema.json"},{"$ref":"BooleanValidator.schema.json"},{"$ref":"Brand.schema.json"},{"$ref":"CitationIntentEnumeration.schema.json"},{"$ref":"Cite.schema.json"},{"$ref":"CiteGroup.schema.json"},{"$ref":"Claim.schema.json"},{"$ref":"Code.schema.json"},{"$ref":"CodeBlock.schema.json"},{"$ref":"CodeChunk.schema.json"},{"$ref":"CodeError.schema.json"},{"$ref":"CodeExecutable.schema.json"},{"$ref":"CodeExpression.schema.json"},{"$ref":"CodeFragment.schema.json"},{"$ref":"Collection.schema.json"},{"$ref":"Comment.schema.json"},{"$ref":"ConstantValidator.schema.json"},{"$ref":"ContactPoint.schema.json"},{"$ref":"CreativeWork.schema.json"},{"$ref":"Datatable.schema.json"},{"$ref":"DatatableColumn.schema.json"},{"$ref":"Date.schema.json"},{"$ref":"DefinedTerm.schema.json"},{"$ref":"Delete.schema.json"},{"$ref":"Emphasis.schema.json"},{"$ref":"EnumValidator.schema.json"},{"$ref":"Enumeration.schema.json"},{"$ref":"Figure.schema.json"},{"$ref":"Function.schema.json"},{"$ref":"Grant.schema.json"},{"$ref":"Heading.schema.json"},{"$ref":"ImageObject.schema.json"},{"$ref":"Include.schema.json"},{"$ref":"IntegerValidator.schema.json"},{"$ref":"Link.schema.json"},{"$ref":"List.schema.json"},{"$ref":"ListItem.schema.json"},{"$ref":"Mark.schema.json"},{"$ref":"Math.schema.json"},{"$ref":"MathBlock.schema.json"},{"$ref":"MathFragment.schema.json"},{"$ref":"MediaObject.schema.json"},{"$ref":"MonetaryGrant.schema.json"},{"$ref":"NontextualAnnotation.schema.json"},{"$ref":"Note.schema.json"},{"$ref":"NumberValidator.schema.json"},{"$ref":"Organization.schema.json"},{"$ref":"Paragraph.schema.json"},{"$ref":"Parameter.schema.json"},{"$ref":"Periodical.schema.json"},{"$ref":"Person.schema.json"},{"$ref":"PostalAddress.schema.json"},{"$ref":"Product.schema.json"},{"$ref":"PropertyValue.schema.json"},{"$ref":"PublicationIssue.schema.json"},{"$ref":"PublicationVolume.schema.json"},{"$ref":"Quote.schema.json"},{"$ref":"QuoteBlock.schema.json"},{"$ref":"Review.schema.json"},{"$ref":"SoftwareApplication.schema.json"},{"$ref":"SoftwareEnvironment.schema.json"},{"$ref":"SoftwareSession.schema.json"},{"$ref":"SoftwareSourceCode.schema.json"},{"$ref":"StringValidator.schema.json"},{"$ref":"Strong.schema.json"},{"$ref":"Subscript.schema.json"},{"$ref":"Superscript.schema.json"},{"$ref":"Table.schema.json"},{"$ref":"TableCell.schema.json"},{"$ref":"TableRow.schema.json"},{"$ref":"ThematicBreak.schema.json"},{"$ref":"Thing.schema.json"},{"$ref":"TupleValidator.schema.json"},{"$ref":"Validator.schema.json"},{"$ref":"Variable.schema.json"},{"$ref":"VideoObject.schema.json"},{"$ref":"VolumeMount.schema.json"},{"$ref":"Primitive.schema.json"},{"$ref":"Object.schema.json"},{"type":"array","items":{"$ref":"Primitive.schema.json"}}]}"#), ("NontextualAnnotation", r#"{"title":"NontextualAnnotation","type":"object","additionalProperties":false,"required":["type","content"],"propertyAliases":{},"properties":{"id":{"type":"string"},"content":{"type":"array","items":{"$ref":"InlineContent.schema.json"}}}}"#), ("Note", r#"{"title":"Note","required":["type","content"],"type":"object","additionalProperties":false,"propertyAliases":{},"properties":{"id":{"type":"string"},"noteType":{"type":"string","enum":["Footnote","Endnote","Sidenote"]},"content":{"type":"array","items":{"$ref":"BlockContent.schema.json"}}}}"#), ("Null", r#"{"title":"Null","type":"null"}"#), @@ -74,6 +74,7 @@ pub const SCHEMAS: &[(&str, &str)] = &[ ("Periodical", r#"{"title":"Periodical","examples":[{"type":"Periodical","title":"Nature","issns":["0028-0836","1476-4687"],"dateStart":"1869-11-04T00:00:00.000Z","url":"https://www.nature.com/"}],"type":"object","propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","author":"authors","comment":"comments","date":"datePublished","editor":"editors","funder":"funders","keyword":"keywords","license":"licenses","maintainer":"maintainers","hasParts":"parts","part":"parts","citations":"references","reference":"references","headline":"title","issn":"issns"},"additionalProperties":false,"required":["type"],"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"about":{"type":"array","items":{"$ref":"ThingTypes.schema.json"}},"authors":{"allOf":[{"parser":"scsi"},{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]}}],"aliases":["author"]},"comments":{"type":"array","items":{"$ref":"Comment.schema.json"},"aliases":["comment"]},"content":{"anyOf":[{"type":"array","items":{"$ref":"Node.schema.json"}},{"type":"string"}]},"dateCreated":{"allOf":[{"$ref":"Date.schema.json"}]},"dateReceived":{"allOf":[{"$ref":"Date.schema.json"}]},"dateAccepted":{"allOf":[{"$ref":"Date.schema.json"}]},"dateModified":{"allOf":[{"$ref":"Date.schema.json"}]},"datePublished":{"aliases":["date"],"allOf":[{"$ref":"Date.schema.json"}]},"editors":{"type":"array","items":{"$ref":"Person.schema.json"},"aliases":["editor"]},"funders":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["funder"]},"fundedBy":{"type":"array","items":{"anyOf":[{"$ref":"Grant.schema.json"},{"$ref":"MonetaryGrant.schema.json"}]}},"genre":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}]},"keywords":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}],"aliases":["keyword"]},"isPartOf":{"$ref":"CreativeWorkTypes.schema.json"},"licenses":{"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string","format":"uri"}]},"aliases":["license"]},"maintainers":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["maintainer"]},"parts":{"aliases":["hasParts","part"],"type":"array","items":{"$ref":"CreativeWorkTypes.schema.json"}},"publisher":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"references":{"aliases":["citations","reference"],"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string"}]}},"text":{"type":"string"},"title":{"aliases":["headline"],"anyOf":[{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"version":{"anyOf":[{"type":"string"},{"type":"number"}]},"dateStart":{"$ref":"Date.schema.json"},"dateEnd":{"$ref":"Date.schema.json"},"issns":{"type":"array","items":{"type":"string"},"aliases":["issn"]}}}"#), ("Person", r#"{"title":"Person","parser":"person","examples":[{"type":"Person","honorificPrefix":"Dr","givenNames":["Marie","Skłodowska"],"familyNames":["Curie"],"honorificSuffix":"PhD"}],"type":"object","propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","affiliation":"affiliations","email":"emails","familyName":"familyNames","surname":"familyNames","surnames":"familyNames","lastName":"familyNames","lastNames":"familyNames","funder":"funders","firstName":"givenNames","firstNames":"givenNames","givenName":"givenNames","prefix":"honorificPrefix","suffix":"honorificSuffix","telephone":"telephoneNumbers","telephoneNumber":"telephoneNumbers"},"additionalProperties":false,"required":["type"],"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"address":{"anyOf":[{"$ref":"PostalAddress.schema.json"},{"type":"string"}]},"affiliations":{"type":"array","items":{"$ref":"Organization.schema.json"},"aliases":["affiliation"]},"emails":{"type":"array","items":{"type":"string","format":"email"},"aliases":["email"]},"familyNames":{"aliases":["familyName","surname","surnames","lastName","lastNames"],"allOf":[{"parser":"ssi"},{"type":"array","items":{"type":"string"}}]},"funders":{"type":"array","items":{"anyOf":[{"$ref":"Organization.schema.json"},{"$ref":"Person.schema.json"}]},"aliases":["funder"]},"givenNames":{"aliases":["firstName","firstNames","givenName"],"allOf":[{"parser":"ssi"},{"type":"array","items":{"type":"string"}}]},"honorificPrefix":{"aliases":["prefix"],"type":"string"},"honorificSuffix":{"aliases":["suffix"],"type":"string"},"jobTitle":{"type":"string"},"memberOf":{"type":"array","items":{"$ref":"Organization.schema.json"}},"telephoneNumbers":{"aliases":["telephone","telephoneNumber"],"type":"array","items":{"type":"string"}}}}"#), ("PostalAddress", r#"{"title":"PostalAddress","type":"object","additionalProperties":false,"required":["type"],"propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","availableLanguage":"availableLanguages","email":"emails","telephone":"telephoneNumbers","telephoneNumber":"telephoneNumbers"},"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"availableLanguages":{"type":"array","items":{"type":"string"},"aliases":["availableLanguage"]},"emails":{"type":"array","items":{"type":"string","format":"email"},"aliases":["email"]},"telephoneNumbers":{"aliases":["telephone","telephoneNumber"],"type":"array","items":{"type":"string"}},"streetAddress":{"type":"string"},"postOfficeBoxNumber":{"type":"string"},"addressLocality":{"type":"string"},"addressRegion":{"type":"string"},"postalCode":{"type":"string"},"addressCountry":{"type":"string"}}}"#), + ("Primitive", r#"{"title":"Primitive","anyOf":[{"$ref":"Null.schema.json"},{"$ref":"Boolean.schema.json"},{"$ref":"Integer.schema.json"},{"$ref":"Number.schema.json"},{"$ref":"String.schema.json"}]}"#), ("Product", r#"{"title":"Product","examples":[{"type":"Product","brand":{"type":"Brand","name":"Astro"},"name":"Astrolabe","logo":{"type":"ImageObject","contentUrl":"http://www.product-astrolabe.com/logo.png","caption":"Astrolabe Logo"},"productID":"AA55"}],"type":"object","propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","brand":"brands"},"additionalProperties":false,"required":["type"],"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"brands":{"type":"array","items":{"$ref":"Brand.schema.json"},"aliases":["brand"]},"logo":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"productID":{"type":"string"}}}"#), ("PropertyValue", r#"{"title":"PropertyValue","required":["type","value"],"type":"object","additionalProperties":false,"propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images"},"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"propertyID":{"type":"string"},"value":{"anyOf":[{"type":"boolean"},{"type":"integer"},{"type":"number"},{"type":"string"}]}}}"#), ("PublicationIssue", r#"{"title":"PublicationIssue","examples":[{"type":"PublicationIssue","url":"https://www.nature.com/nature/volumes/571/issues/7766","issueNumber":571,"datePublished":"2019-07-25T00:00:00.000Z","isPartOf":{"type":"PublicationVolume","volumeNumber":571,"isPartOf":{"type":"Periodical","title":"Nature"}}}],"type":"object","additionalProperties":false,"required":["type"],"propertyAliases":{"alternateName":"alternateNames","identifier":"identifiers","image":"images","author":"authors","comment":"comments","date":"datePublished","editor":"editors","funder":"funders","keyword":"keywords","license":"licenses","maintainer":"maintainers","hasParts":"parts","part":"parts","citations":"references","reference":"references","headline":"title"},"properties":{"id":{"type":"string"},"alternateNames":{"type":"array","items":{"type":"string"},"aliases":["alternateName"]},"description":{"anyOf":[{"type":"array","items":{"$ref":"BlockContent.schema.json"}},{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"identifiers":{"type":"array","items":{"anyOf":[{"$ref":"PropertyValue.schema.json"},{"type":"string"}]},"aliases":["identifier"]},"images":{"type":"array","items":{"anyOf":[{"$ref":"ImageObject.schema.json"},{"type":"string","format":"uri"}]},"aliases":["image"]},"name":{"type":"string"},"url":{"type":"string","format":"uri"},"about":{"type":"array","items":{"$ref":"ThingTypes.schema.json"}},"authors":{"allOf":[{"parser":"scsi"},{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]}}],"aliases":["author"]},"comments":{"type":"array","items":{"$ref":"Comment.schema.json"},"aliases":["comment"]},"content":{"anyOf":[{"type":"array","items":{"$ref":"Node.schema.json"}},{"type":"string"}]},"dateCreated":{"allOf":[{"$ref":"Date.schema.json"}]},"dateReceived":{"allOf":[{"$ref":"Date.schema.json"}]},"dateAccepted":{"allOf":[{"$ref":"Date.schema.json"}]},"dateModified":{"allOf":[{"$ref":"Date.schema.json"}]},"datePublished":{"aliases":["date"],"allOf":[{"$ref":"Date.schema.json"}]},"editors":{"type":"array","items":{"$ref":"Person.schema.json"},"aliases":["editor"]},"funders":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["funder"]},"fundedBy":{"type":"array","items":{"anyOf":[{"$ref":"Grant.schema.json"},{"$ref":"MonetaryGrant.schema.json"}]}},"genre":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}]},"keywords":{"allOf":[{"parser":"csi"},{"type":"array","items":{"type":"string"}}],"aliases":["keyword"]},"isPartOf":{"$ref":"CreativeWorkTypes.schema.json"},"licenses":{"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string","format":"uri"}]},"aliases":["license"]},"maintainers":{"type":"array","items":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"aliases":["maintainer"]},"parts":{"aliases":["hasParts","part"],"type":"array","items":{"$ref":"CreativeWorkTypes.schema.json"}},"publisher":{"anyOf":[{"$ref":"Person.schema.json"},{"$ref":"Organization.schema.json"}]},"references":{"aliases":["citations","reference"],"type":"array","items":{"anyOf":[{"$ref":"CreativeWorkTypes.schema.json"},{"type":"string"}]}},"text":{"type":"string"},"title":{"aliases":["headline"],"anyOf":[{"type":"array","items":{"$ref":"InlineContent.schema.json"},"minItems":2},{"type":"string"}]},"version":{"anyOf":[{"type":"string"},{"type":"number"}]},"issueNumber":{"anyOf":[{"type":"integer"},{"type":"string"}]},"pageStart":{"anyOf":[{"type":"integer"},{"type":"string"}]},"pageEnd":{"anyOf":[{"type":"integer"},{"type":"string"}]},"pagination":{"type":"string"}}}"#), diff --git a/rust/schema/src/types.rs b/rust/schema/src/types.rs index f883ee6f3c..428ad69682 100644 --- a/rust/schema/src/types.rs +++ b/rust/schema/src/types.rs @@ -5361,13 +5361,20 @@ pub enum Node { Variable(Variable), VideoObject(VideoObject), VolumeMount(VolumeMount), + Primitive(Primitive), + Object(Object), + Vec(Vec), +} + +/// Union type for all primitives values +#[derive(Clone, Debug, AsRefStr, Serialize, Deserialize)] +#[serde(untagged)] +pub enum Primitive { Null(Null), Boolean(Boolean), Integer(Integer), Number(Number), String(String), - Object(Object), - Array(Array), } /// All type schemas that are derived from Thing diff --git a/schema/schema/Node.schema.yaml b/schema/schema/Node.schema.yaml index cf8a3c3b7e..1a9fd7a358 100644 --- a/schema/schema/Node.schema.yaml +++ b/schema/schema/Node.schema.yaml @@ -9,10 +9,8 @@ $comment: | Array should come last to avoid single items (e.g. a single string) being coerced into an array. anyOf: - - $ref: 'Null' - - $ref: Boolean - - $ref: Integer - - $ref: Number - - $ref: String + - $ref: Primitive - $ref: Object - - $ref: Array + - type: array + items: + $ref: Primitive diff --git a/schema/schema/Primitive.schema.yaml b/schema/schema/Primitive.schema.yaml new file mode 100644 index 0000000000..bd88241c4e --- /dev/null +++ b/schema/schema/Primitive.schema.yaml @@ -0,0 +1,14 @@ +title: Primitive +category: other +status: unstable +description: Union type for all primitives values +$comment: | + The entity types in this union are automatically inserted during the build. + The order of these types is important because it determines the + order of attempted coercion (ie. parsing and reshaping to arrays). +anyOf: + - $ref: 'Null' + - $ref: Boolean + - $ref: Integer + - $ref: Number + - $ref: String diff --git a/schema/src/bindings/typescript.ts b/schema/src/bindings/typescript.ts index ae2f4d40a5..5567d8b96a 100644 --- a/schema/src/bindings/typescript.ts +++ b/schema/src/bindings/typescript.ts @@ -41,7 +41,14 @@ export const generateTypeDefinitions = async (): Promise => { ${autogeneratedHeader('build:ts', path.basename(__filename), '//')} type Integer = number -type Primitive = null | boolean | number | string | Array | { [key: string]: Primitive } + +type Json = + | string + | number + | boolean + | null + | { [property: string]: Json } + | Json[]; // Remove properties from an Object if their value is undefined const compact = (o: O): O => @@ -97,9 +104,9 @@ export const titleToType = (title: string): string => { case 'String': return 'string' case 'Object': - return 'Record' + return '{ [property: string]: Json }' case 'Array': - return 'Array' + return 'Array' default: return title } @@ -236,7 +243,7 @@ const schemaToType = (schema: JsonSchema): string => { if (type === 'number') return 'number' if (type === 'string') return 'string' if (type === 'array') return arrayToType(schema) - if (type === 'object') return 'Record' + if (type === 'object') return '{ [property: string]: Json }' throw new Error(`Unhandled schema: ${JSON.stringify(schema)}`) } diff --git a/schema/src/types.ts b/schema/src/types.ts index 824d2db731..cb598d379b 100644 --- a/schema/src/types.ts +++ b/schema/src/types.ts @@ -5,13 +5,14 @@ // in the `schema` directory and run `npm run build:ts` to regenerate it. type Integer = number -type Primitive = - | null - | boolean - | number + +type Json = | string - | Array - | { [key: string]: Primitive } + | number + | boolean + | null + | { [property: string]: Json } + | Json[] // Remove properties from an Object if their value is undefined const compact = (o: O): O => @@ -22,7 +23,7 @@ const compact = (o: O): O => ) export interface Types { - Array: Array + Array: Array ArrayValidator: ArrayValidator Article: Article AudioObject: AudioObject @@ -89,13 +90,14 @@ export interface Types { Null: null Number: number NumberValidator: NumberValidator - Object: Record + Object: { [property: string]: Json } Organization: Organization Paragraph: Paragraph Parameter: Parameter Periodical: Periodical Person: Person PostalAddress: PostalAddress + Primitive: Primitive Product: Product PropertyValue: PropertyValue PublicationIssue: PublicationIssue @@ -212,7 +214,7 @@ export type Entity = { | 'VideoObject' | 'VolumeMount' id?: string - meta?: Record + meta?: { [property: string]: Json } } /** @@ -2274,13 +2276,14 @@ export type Node = | Variable | VideoObject | VolumeMount - | null - | boolean - | Integer - | number - | string - | Record - | Array + | Primitive + | { [property: string]: Json } + | Array + +/** + * Union type for all primitives values + */ +export type Primitive = null | boolean | Integer | number | string /** * All type schemas that are derived from Thing diff --git a/schema/src/util/guards.ts b/schema/src/util/guards.ts index c6fd07bf3e..e74a5167b4 100644 --- a/schema/src/util/guards.ts +++ b/schema/src/util/guards.ts @@ -10,7 +10,9 @@ import { } from '../types' export type TypeMapGeneric< - T extends { type: string } & Record = { type: string } + T extends { type: Entity['type'] } & Record = { + type: Entity['type'] + } > = { [key in T['type']]: key } type ExtractGeneric = Type extends TypeMap @@ -28,7 +30,7 @@ type ExtractGeneric = Type extends TypeMap */ export const isInTypeMap = >(typeMap: T) => - (node?: Node): node is ExtractGeneric => + (node?: unknown): node is ExtractGeneric => isEntity(node) ? Object.keys(typeMap).includes(node.type) : false /** @@ -36,7 +38,7 @@ export const isInTypeMap = * (i.e. not an `Entity`). */ export const isPrimitive = ( - node?: Node + node?: unknown ): node is null | boolean | number | string => { const type = typeof node if (node === null) return true @@ -52,7 +54,7 @@ export const isPrimitive = ( /** * Type guard to determine whether a node is an `Entity` */ -export const isEntity = (node?: Node): node is Entity => { +export const isEntity = (node?: unknown): node is Entity => { if (node === null || node === undefined) return false return Object.prototype.hasOwnProperty.call(node, 'type') } @@ -64,7 +66,7 @@ export const isEntity = (node?: Node): node is Entity => { */ export const isA = ( type: K, - node: Node | undefined + node: unknown ): node is Types[K] => isEntity(node) && node.type === type /** @@ -75,7 +77,7 @@ export const isA = ( */ export const isType = (type: K) => - (node?: Node): node is Types[K] => + (node?: unknown): node is Types[K] => isA(type, node) /** @@ -85,7 +87,7 @@ export const isType = */ export const isIn = ( union: K, - node: Node | undefined + node: unknown ): node is Unions[K] => isEntity(node) && node.type in unions[union] /** @@ -95,7 +97,7 @@ export const isIn = ( */ export const isMember = (type: K) => - (node?: Node): node is Unions[K] => + (node?: unknown): node is Unions[K] => isIn(type, node) /** @@ -103,7 +105,7 @@ export const isMember = * * e.g. `nodes.filter(isInlineContent)` */ -export const isInlineContent = (node?: Node): node is InlineContent => +export const isInlineContent = (node?: unknown): node is InlineContent => isPrimitive(node) || isIn('InlineContent', node) /** @@ -111,5 +113,5 @@ export const isInlineContent = (node?: Node): node is InlineContent => * * e.g. `nodes.filter(isBlockContent)` */ -export const isBlockContent = (node?: Node): node is BlockContent => +export const isBlockContent = (node?: unknown): node is BlockContent => isIn('BlockContent', node) diff --git a/web/src/patches/json/index.test.ts b/web/src/patches/json/index.test.ts index 5158db48f9..37210bcff3 100644 --- a/web/src/patches/json/index.test.ts +++ b/web/src/patches/json/index.test.ts @@ -1,4 +1,5 @@ import { applyAdd, applyRemove, applyReplace, diff } from '.' +import { codeChunk } from '@stencila/schema' test('diff:array', () => { const arraySimple = [1, 2, 3] @@ -47,6 +48,23 @@ test('diff:object', () => { ]) }) +test('diff:schema node', () => { + const obj = { a: 'foo', b: [1, 2, 3] } + expect( + diff(obj, codeChunk({ programmingLanguage: 'rust', text: '2+2' })) + ).toEqual({ + ops: [ + { + address: [], + items: 1, + length: 1, + type: 'Replace', + value: { programmingLanguage: 'rust', text: '2+2', type: 'CodeChunk' }, + }, + ], + }) +}) + test('applyAdd', () => { const value = { string: '', array: [], object: {} }