Git Product home page Git Product logo

schema-dts's Introduction

Build Status Coverage Status schema-dts npm version schema-dts-gen version

schema-dts

JSON-LD TypeScript types for Schema.org vocabulary.

schema-dts provides TypeScript definitions for Schema.org vocabulary in JSON-LD format. The typings are exposed as complete sets of discriminated type unions, allowing for easy completions and stricter validation.

Example of Code Completion using schema-dts

This repository contains two NPM packages:

  • schema-dts-gen Providing a command-line tool to generate TypeScript files based on a specific Schema version and layer.
  • schema-dts Pre-packaged TypeScript typings of latest Schema.org schema, without pending and other non-core layers.

Note: This is not an officially supported Google product.

Usage

To use the typings for your project, simply add the schema-dts NPM package to your project:

npm install schema-dts

Then you can use it by importing "schema-dts".

Root context

You will usually want your top-level item to include a @context, like https://schema.org. In order for your object type to accept this property, you can augment it with WithContext, e.g.:

import type {Person, WithContext} from 'schema-dts';

const p: WithContext<Person> = {
  '@context': 'https://schema.org',
  '@type': 'Person',
  name: 'Eve',
  affiliation: {
    '@type': 'School',
    name: 'Nice School',
  },
};

Graphs and IDs

JSON-LD supports '@graph' objects that have richer interconnected links between the nodes. You can do that easily in schema-dts by using the Graph type.

Notice that any node can have an @id when defining it. And you can reference the same node from different places by simply using an ID stub, for example { '@id': 'https://my.site/about/#page } below is an ID stub.

The example below shows potential JSON-LD for an About page. It includes definitions of Alyssa P. Hacker (the author & subject of the page), the specific page in this URL, and the website it belongs to. Some objects are still defined as inline nested objects (e.g. Occupation), since they are only referenced by their parent. Other objects are defined at the top-level with an @id, because multiple nodes refer to them.

import type {Graph} from 'schema-dts';

const graph: Graph = {
  '@context': 'https://schema.org',
  '@graph': [
    {
      '@type': 'Person',
      '@id': 'https://my.site/#alyssa',
      name: 'Alyssa P. Hacker',
      hasOccupation: {
        '@type': 'Occupation',
        name: 'LISP Hacker',
        qualifications: 'Knows LISP',
      },
      mainEntityOfPage: {'@id': 'https://my.site/about/#page'},
      subjectOf: {'@id': 'https://my.site/about/#page'},
    },
    {
      '@type': 'AboutPage',
      '@id': 'https://my.site/#site',
      url: 'https://my.site',
      name: "Alyssa P. Hacker's Website",
      inLanguage: 'en-US',
      description: 'The personal website of LISP legend Alyssa P. Hacker',
      mainEntity: {'@id': 'https://my.site/#alyssa'},
    },
    {
      '@type': 'WebPage',
      '@id': 'https://my.site/about/#page',
      url: 'https://my.site/about/',
      name: "About | Alyssa P. Hacker's Website",
      inLanguage: 'en-US',
      isPartOf: {
        '@id': 'https://my.site/#site',
      },
      about: {'@id': 'https://my.site/#alyssa'},
      mainEntity: {'@id': 'https://my.site/#alyssa'},
    },
  ],
};

Schema Typings Generator

The Schema Typings Generator is available in the schema-dts-gen package.

npm install schema-dts-gen
npx schema-dts-gen --ontology=https://schema.org/version/latest/schemaorg-all-https.nt

Command line usage:

  • Specify your ontology

    • Specify --ontology: An HTTPs URL to an .nt NTriple file declaring your ontology.

      Must be compatible with Schema.org, including the Schema.org DataTypes and specifying a top-level Thing type.

  • --context: Defaults to https://schema.org, the value or values to be used with the "@context" property.

    Can be either a single URL, or a comma separated list of two or more name:URL pairs.

    The context affects names of string properties in types, as well as the values of an object's "@type".

  • --deprecated/--nodeprecated: Whether or not to include deprecated Schema.org types and properties. When included, these types will still be marked with @deprecated JSDOC tags.

  • --verbose: Outputs additional logs and debugging notes to stderr.

Developers

Use NPM to install dependencies:

npm install

We have wrappers around tsc and tsc --build to build our generator other .d.ts files.

To generate TypeScript from the latest Schema.org Schema:

npm run build-gen && npm run build-schema

or simply build the schema-dts generator:

npm run build-gen

To contribute changes, see the CONTRIBUTING.md file.

schema-dts's People

Contributors

antoinerousseau avatar dependabot[bot] avatar eyas avatar sangotaro avatar shnydercom avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

schema-dts's Issues

Rich Result Text shows "offer" error when using Motorcycle type

When trying to use the Motorcycle as "@type" for 'itemOffer' the Rich Result test throw an error about offer for Product snippets.
If we change the @type to Car the error is gone.

The issue appears to be in the "itemOffered" part.
We get error when using Motorcycle as type:

"itemOffered": {
  "@type": "Motorcycle",
  "name": "Long name of product",
  "itemCondition": "UsedCondition",
},

Screen Shot 2023-04-28 at 5 42 43 PM

while using Car as type will pass:

"itemOffered": {
  "@type": "Car",
  "name": "Long name of product",
  "itemCondition": "UsedCondition",
},

Screen Shot 2023-04-28 at 6 05 07 PM

Is this intended behaviour?

(Schema also tested on the validator.schema.org)
Test code example used in Rich Result Text to reproduce:

 <html>
  <head>
    <title>Executive Anvil</title>
    <script type="application/ld+json">
      {
        "@context": "https://schema.org/",
        "@type": "Product",
        "name": "Long name of product",
        "brand": {
          "@type": "Brand",
          "name": "Brand Name"
        },
        "image": {
          "@type": "ImageObject",
          "url": "#"
        },
        "description": "<p>Test</p>\n",
        "offers": {
          "@type": "Offer",
          "url": "url of the product",
          "availability": "InStock",
          "name": "Long name of product",
          "image": {
            "@type": "ImageObject",
            "url": "#"
          },
          "offeredBy": {
            "@type": "Person",
            "name": "Name and Surname of the seller",
            "address": {
              "@type": "PostalAddress",
              "streetAddress": "My street address",
              "addressLocality": "The city",
              "postalCode": "Some postal code",
              "addressCountry": "UN"
            }
          },
          "itemOffered": {
            "@type": "Motorcycle",
            "name": "Long name of product",
            "itemCondition": "UsedCondition"
          },
          "priceSpecification": {
            "@type": "PriceSpecification",
            "price": "99.99",
            "priceCurrency": "EUR"
          }
        }
      }
    </script>
  </head>
  <body>
  </body>
</html>

WithContext<T> should be assignable to T

After updating from 0.7 to 0.8, I get errors with this code:

const list: WithContext<ItemList> = {
    "@context": "https://schema.org",
    "@type": "ItemList",
    itemListElement: articleList.map((articleItem, i) =>
      getArticleItemStructuredData({
        articleItem,
        position: i + 1,
      })
    ),
}

The property @type gives the following error: Type '"ItemList"' is not assignable to type '"OfferCatalog"'

I would be able to bypass this error by importing and using ItemListLeaf instead of ItemList, but this interface is not exported. For now my workaround was to recreate the interface (based on the sourcecode, I use Omit<> to deny all members except ItemListLeaf from the intersection).

type ItemListLeaf = Exclude<
  ItemList,
  BreadcrumbList | OfferCatalog | HowToStep | HowToSection
>;

Notice that when I run the output of this code in the Rich Results Test or in the Structured Data Testing Tool, I don't get any errors, that's why I think the problem might not be in my original interface, but in the way the typings are built.

BUG: schema-dts-gen and custom context - prefixes other than "schema" are ignored during generation of code for types

schema-dts-gen accepts a --context parameter, which sets the value of the @context property.

Imagine we have a custom schema for an external extension which we will call custom-schema.nt, which is a mix of all the schema.org types along with custom types, which we prefix with the demo namespace. We can auto-generate TypeScript code as follows:

npx schema-dts-gen --ontology=https://somelocation.com/custom-schema.nt 
--context=schema:https://schema.org/,demo:https://example.com/demo/ > my-generated-code.ts

This nicely creates WithContext and Graph:

export type WithContext<T extends Thing> = Graph | (T & {
    "@context": {
        "schema": "https://schema.org/";
        "demo": "https://example.com/demo/";
    };
});
export interface Graph {
    "@context": {
        "schema": "https://schema.org/";
        "demo": "https://example.com/demo/";
    };
    "@graph": readonly Thing[];
}

However, the custom demo prefix is ignored during code generation - currently we get:

interface DemoBase extends ThingBase {
    /** Indicates whether this resource is a template. */
    "https://example.com/demo/isTemplate"?: SchemaValue<Boolean>;
}
interface DemoLeaf extends DemoBase {
    "@type": "https://example.com/demo/Demo";
}
/** A Demo */
export type Demo = DemoLeaf;

whereas what would be nice would be:

interface DemoBase extends ThingBase {
    /** Indicates whether this resource is a template. */
    "demo:isTemplate"?: SchemaValue<Boolean>;
}
interface DemoLeaf extends DemoBase {
    "@type": "demo:Demo";
}
/** A Demo */
export type Demo = DemoLeaf;

Context-aware Generation

Right now the schema generated always assumes the "@context" to be used will be http(s?)://schema.org.

That's still the right default for the pre-generated package.

Might be fun to allow people to provide their own context string or dictionary.

  • If schema.org isn't present in a string or as a key to the dictionary, generate the full URL.
  • If provided as a named key, use "schema:propName" and "schema:TypeName" instead (where "schema" is the key used).

[question] JSON marshal/unmarshal?

Thanks for showing me how to define the types of JSON-LD in TypeScript. I like the compiler and IDE gives me warnings when I try to set bad fields and values. To serialize to JSON is also super easy.

Now, my question is how to unmarshal JSON to the typed objects? I thought I could get the @type and assert the type but so far not successful. If you already have a solution please let me know.

Add ISO_3166 2 beside of addressCountry

  "address": {
    "@type": "PostalAddress",
    "addressCountry": "IR",
    ...
  "address": {
    "@type": "PostalAddress",
    "addressCountry": "IR",
    "subdivisionISO": "IR-07",
    ...

https://en.wikipedia.org/wiki/ISO_3166-2

For example Tehran in IR (Iran) is IR-07
https://en.wikipedia.org/wiki/ISO_3166-2:IR#Current_codes

Key name suggest

  • subdivision
  • subdivisionISO
  • addressSubdivision
  • addressSubdivisionISO
  • addressCountrySubdivisionISO
  • addressCountrySubdivision
  • countrySubdivisionISO
  • countrySubdivision

Support custom ontology

Generator should accept a totally different ontology outside of schema.org (so long as it's complete).

We'd still want it to use the schema.org DataTypes, and domainIncludes/rangeIncludes for defining schema shape.

NPM package sickly

NPM install failed because of missing "bin": "./dist/gen/cli/cli.js"

(version 0.7.1)

Increasing HTML size

Hello,

I have 480 currency items and when I use schema-dts its increasing HTML size, how can I set export async like .json-ld file? I can success it with PHP, now I want to use for my NextJS project with this npm package.

<script type="text/javascript"> document.addEventListener("DOMContentLoaded", function() { $("select[name=market]").on('change',function(){ window.location.href = $(this).val(); }); $.getJSON( "/CURRENCY-LIST-PAGE.jsonld", function( data ) { $( "<script/>", { "type": "application/ld+json", "html": JSON.stringify(data) }).appendTo( "head" ); }); }); </script>

Generate types for external schema

I am trying to generate types for the GS1 web vocabulary. I have included the context used

schema-dts-gen --ontology=https://schema.org/version/latest/schemaorg-all-https.nt --context=cc:http://creativecommons.org/ns#,cert:http://www.w3.org/ns/auth/cert#,dbp:http://dbpedia.org/property/,dc:http://purl.org/dc/elements/1.1/,dcterms:http://purl.org/dc/elements/1.1/,doap:http://usefulinc.com/ns/doap#,exif:http://www.w3.org/2003/12/exif/ns#,fn:http://www.w3.org/2005/xpath-functions#,foaf:http://xmlns.com/foaf/0.1/,geo:http://www.w3.org/2003/01/geo/wgs84_pos#,geonames:http://www.geonames.org/ontology#,gr:http://purl.org/goodrelations/v1#,gs1:https://gs1.org/voc/,log:http://www.w3.org/2000/10/swap/log#,owl:http://www.w3.org/2002/07/owl#,rdf:http://www.w3.org/1999/02/22-rdf-syntax-ns#,rdfs:http://www.w3.org/2000/01/rdf-schema#,rei:http://www.w3.org/2004/06/rei#,rsa:http://www.w3.org/ns/auth/rsa#,rss:http://purl.org/rss/1.0/,schema:http://schema.org/,sfn:http://www.w3.org/ns/sparql#,sioc:http://rdfs.org/sioc/ns#,skos:http://www.w3.org/2004/02/skos/core#,sw:http://www.w3.org/2003/06/sw-vocab-status/ns#,swrc:http://swrc.ontoware.org/ontology#,types:http://rdfs.org/sioc/types#,vann:http://purl.org/vocab/vann/,vcard:http://www.w3.org/2006/vcard/ns#,voaf:http://purl.org/vocommons/voaf#,wot:http://xmlns.com/wot/0.1/,xhtml:http://www.w3.org/1999/xhtml#,xsd:http://www.w3.org/2001/XMLSchema# > schema.ts

which results in the correct context

export type WithContext<T extends Thing> = T & {
    "@context": {
        "cc": "http://creativecommons.org/ns#";
        "cert": "http://www.w3.org/ns/auth/cert#";
        "dbp": "http://dbpedia.org/property/";
        "dc": "http://purl.org/dc/elements/1.1/";
        "dcterms": "http://purl.org/dc/elements/1.1/";
        "doap": "http://usefulinc.com/ns/doap#";
        "exif": "http://www.w3.org/2003/12/exif/ns#";
        "fn": "http://www.w3.org/2005/xpath-functions#";
        "foaf": "http://xmlns.com/foaf/0.1/";
        "geo": "http://www.w3.org/2003/01/geo/wgs84_pos#";
        "geonames": "http://www.geonames.org/ontology#";
        "gr": "http://purl.org/goodrelations/v1#";
        "gs1": "https://gs1.org/voc/";
        "log": "http://www.w3.org/2000/10/swap/log#";
        "owl": "http://www.w3.org/2002/07/owl#";
        "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
        "rdfs": "http://www.w3.org/2000/01/rdf-schema#";
        "rei": "http://www.w3.org/2004/06/rei#";
        "rsa": "http://www.w3.org/ns/auth/rsa#";
        "rss": "http://purl.org/rss/1.0/";
        "schema": "http://schema.org/";
        "sfn": "http://www.w3.org/ns/sparql#";
        "sioc": "http://rdfs.org/sioc/ns#";
        "skos": "http://www.w3.org/2004/02/skos/core#";
        "sw": "http://www.w3.org/2003/06/sw-vocab-status/ns#";
        "swrc": "http://swrc.ontoware.org/ontology#";
        "types": "http://rdfs.org/sioc/types#";
        "vann": "http://purl.org/vocab/vann/";
        "vcard": "http://www.w3.org/2006/vcard/ns#";
        "voaf": "http://purl.org/vocommons/voaf#";
        "wot": "http://xmlns.com/wot/0.1/";
        "xhtml": "http://www.w3.org/1999/xhtml#";
        "xsd": "http://www.w3.org/2001/XMLSchema#";
    };
};

but then I am not sure how to use

const product: WithContext<Product> 

I think I am missing something here. Any feedback is appreciated

LocalBusiness type does not recognise `@type: 'LocalBusiness'`

This code reports an error:

import { LocalBusiness } from 'schema-dts';

const localBusiness: LocalBusiness = {
  '@context': 'https://schema.org',
  "@id": 'someId',
  '@type': 'LocalBusiness',
  address: { '@type': 'PostalAddress', addressCountry: 'JP' },
  name: 'someName',
};

export default localBusiness;

The reported error:

Type '"LocalBusiness"' is not assignable to type '"TravelAgency"'. ts(2322)

Screenshot 2020-10-23 at 12 16 41

Feature Request: Add safeJsonLdReplacer() from react-schemaorg to schema-dts-gen generated code

The react-schemaorg project (also by the hard-working Eyas) has a useful function safeJsonLdReplacer() in:
https://github.com/google/react-schemaorg/blob/master/src/json-ld.tsx

safeJsonLdReplacer() is not React specific, but is general to any solution working with HTML and JSON-LD:
https://www.w3.org/TR/json-ld11/#restrictions-for-contents-of-json-ld-script-elements

For folks who do use schema-dts-gen but don't use React (e.g. those who use Angular 12) it would be handy if safeJsonLdReplacer() were added to the generated code created by schema-dts-gen, so all can use it when needed.

Person does not inherit correctly from interfaces PersonLeaf -> PersonBase

Not sure if this is a Typescript, bug or a schema issue, but here goes:

Importing:

import type { Person } from "schema-dts";

Throws the TypeScript error: Property 'familyName' does not exist on type 'Person'. Property 'familyName' does not exist on type 'string'.;

Clearly it is ignoring the logical 'or' in export declare type Person = PersonLeaf | Patient | string; and skipping directly to 'string'. Not sure why.

JavaScript heap out of memory

I'm getting a JavaScript heap out of memory error when trying to run tsc --noEmit.
Node version: v10.16.0
TypeScript: 3.4.3
ts-loader: 5.4.5
ts-node: 8.1.0

I guess the problem can be fixed by upgrading the dependencies to the latest versions and increasing max-old-space-size, but that's unfortunately not possible yet in my current project :(


<--- Last few GCs --->

[23026:0x4400980]    40880 ms: Scavenge 1384.8 (1423.9) -> 1384.4 (1424.4) MB, 12.3 / 0.0 ms  (average mu = 0.165, current mu = 0.085) allocation failure
[23026:0x4400980]    40893 ms: Scavenge 1385.1 (1424.4) -> 1384.7 (1424.9) MB, 7.9 / 0.0 ms  (average mu = 0.165, current mu = 0.085) allocation failure
[23026:0x4400980]    41493 ms: Mark-sweep 1385.4 (1424.9) -> 1384.9 (1424.9) MB, 595.0 / 0.0 ms  (average mu = 0.113, current mu = 0.056) allocation failure scavenge might not succeed


<--- JS stacktrace --->

==== JS stack trace =========================================

    0: ExitFrame [pc: 0xb91310dbe1d]
Security context: 0x1e0c9099e6e9 <JSObject>
    1: addPropertyToElementList(aka addPropertyToElementList) [0x21d642b90aa9] [/mnt/c/dev/node_modules/typescript/lib/tsc.js:~28448] [pc=0xb9131ad340a](this=0x0c2a182026f1 <undefined>,propertySymbol=0x16d1c4d04069 <Symbol map = 0x6cba608dd59>,context=0x262e61498bc1 <Object map = 0x15291fe33dc9>,typeElements=0x332e3ae4a389 <JSArray[0]>)
    2: createTy...

FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
 1: 0x8f9d10 node::Abort() [node]
 2: 0x8f9d5c  [node]
 3: 0xaffd0e v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, bool) [node]
 4: 0xafff44 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, bool) [node]
 5: 0xef4152  [node]
 6: 0xef4258 v8::internal::Heap::CheckIneffectiveMarkCompact(unsigned long, double) [node]
 7: 0xf00332 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [node]
 8: 0xf00c64 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
 9: 0xf038d1 v8::internal::Heap::AllocateRawWithRetryOrFail(int, v8::internal::AllocationSpace, v8::internal::AllocationAlignment) [node]
10: 0xeccd54 v8::internal::Factory::NewFillerObject(int, bool, v8::internal::AllocationSpace) [node]
11: 0x116cede v8::internal::Runtime_AllocateInNewSpace(int, v8::internal::Object**, v8::internal::Isolate*) [node]
12: 0xb91310dbe1d
[1]    23026 abort (core dumped)  npx tsc --noEmit

Cannot 'implement' Person from class

When I try to implement 'Person' on a class like:

import { Person as PersonSchema }  from 'schema-dts';
export class Person implements PersonSchema { ... }

TS errors with

A class can only implement an object type or intersection of object types with statically known members.

Which can be solved by editing this snippet:

export declare type Person = ({
    "@type": "Person";
} & PersonBase) | Patient;

to

export declare type Person = ({
    "@type": "Person";
} & PersonBase);

Obviously, this case is true for any type declaration in the pattern (...) | [TYPE]. The same applies to extending interfaces.
What is the reason for this pattern? Is it intended?

sameAs as an array

I see that sameAs is a string attribute and I was wondering if it also should be a string[] so it can accept a list of social networks, as explained here.

{
  "@context": "https://schema.org",
  "@type": "Organization",
  "name": "Company Name",
  "url": "company.com",
  "logo": "company.com/logo.png",
  "sameAs": [
    "https://facebook.com/",
    "https://twitter.com/",
  ]
}

Type errors against Google's recommended Schema JSON-LD's

Firstly, thank you for this lib and your maintenance of it.

After setting up the typings and using them against Google's recommended Schema markup. In this case I'm seeing errors against Product and it's nested aggregateRating can you help me understand how to use these typings with Google's recommended versions?

Error:

(property) "aggregateRating"?: SchemaValue<IdReference | AggregateRatingLeaf | EmployerAggregateRatingLeaf>
The overall rating, based on a collection of reviews or ratings, of the item.

Type '{ "@type": "AggregateRating"; ratingValue: string; reviewCount: string; }' is not assignable to type 'SchemaValue<IdReference | AggregateRatingLeaf | EmployerAggregateRatingLeaf>'.
  Types of property '"reviewCount"' are incompatible.
    Type 'string' is not assignable to type 'SchemaValue<number>'.ts(2322)
schema.d.ts(8042, 5): The expected type comes from property 'aggregateRating' which is declared here on type 'Product'

primitive string type disallows picking types from Organization

I have built some helper methods to help assemble instances in our common patterns. With the recent introduction of #47, and the fact that none of the Base types are exposed (related: #29 (comment)), I no longer have a way to access/reuse the types of the properties within OrganizationBase model.

With the latest release including #47, I get:

error TS2339: Property 'image' does not exist on type 'Organization'.

5   image: SchemaOrganizationNoRef['image'] | Identified

e.g.

import { Organization as SchemaOrganizationNoRef } from 'schema-dts'
import { Identified } from './Identified'

interface Reffed {
  image: SchemaOrganizationNoRef['image'] | Identified

  /**
   * URL of a logo that is representative of the organization.
   *
   * Additional image guidelines:
   *
   * The image must be 112x112px, at minimum.
   * The image URL must be crawlable and indexable.
   * The image must be in .jpg, .png, or. gif format.
   */
  logo: SchemaOrganizationNoRef['logo'] | Identified
}

/**
 * Allow given properties to be refs
 */
type SchemaOrganization = Omit<SchemaOrganizationNoRef, keyof Reffed> & Reffed

interface Required {
  address: SchemaOrganizationNoRef['address']
  legalName: SchemaOrganizationNoRef['legalName']
  name: SchemaOrganizationNoRef['name']
  /**
   * URL of the organization eg. https://google.com
   */
  url: SchemaOrganizationNoRef['url']
}

/**
 * Declare our `Organization` as a stricter set of properties
 *
 * @see https://schema.org/Organization
 */
export type Organization = Omit<SchemaOrganization, keyof Required> & Required & Identified

export const buildOrganization = (
  o: Omit<Organization, '@id' | '@type'>,
  uniqueName = 'organization',
): Organization => ({
  // '@context': 'https://schema.org',
  '@id': `${o.url}/#${uniqueName}`,
  '@type': 'Organization',
  ...o,
})

for completeness:

export interface Identified {
  /**
   * preferably url e.g. https://alienfast.com/#organization
   */
  '@id': string
}

export function ref<I extends Identified>(i: I): Identified {
  return { '@id': i['@id'] }
}

How should I be referencing the declared type of something like Organization['image']?

Docs: Extend exemplary usage

Although quite trivial afterwards, it took me quite a while to figure out how to use this library with react-helmet.
You might consider updating the docs if not, feel free to close this.

const script = [
    {
        type: "application/ld+json",
        innerHTML: `${JSON.stringify(p)}`,
    },
];
<Helmet script={script} />

[Question] Plans for this library

Hi Guys,

I am considering this library as a base for creating a tool that takes string DOM and validates structured data.

I was just wondering, your library looks really good. How serious this library is? is this seen as a long term commitment?

Error TS4023 when importing types

I have this piece of code:

import { SportsEvent, WithContext } from 'schema-dts';

const getStructuredData = (): WithContext<SportsEvent> => ({
  '@context': 'https://schema.org',
  '@type': 'SportsEvent',
  // ...
});

I have the error TS4023 on this:

Exported variable 'getStructuredData' has or is using name 'SportsEventLeaf' from external module 'myproject/node_modules/schema-dts/dist/schema' but cannot be named

How can I resolve this?

If I modify the schema.d.ts in my node_modules, and I export the SportsEventLeaf interface, it seems to solve this problem. But of course, it's not a real fix…

SearchAction's potentialAction doesn't expect target (and should)

The valid schema as defined here https://schema.org/SearchAction would not compile because target in potentialAction isn't properly specified. If you remove target it compiles.

{
    "@context": "http://schema.org",
    "@type": "WebSite",
    "url": "http://example.com/",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "http://example.com/search?&q={query}",
      "query": "required"
    }
}

potentialAction is of type Action which receives SearchAction as type, which has only @type = 'SearchAction' and SearchActionBase, which finaly has only query: Text as type (which is a string). Unfortunately target is nowhere to be found in any of those. Is this on purpose? Did anything change that I don't know?

Thanks in advance

Allow more primitives (boolean/number/string)

E.g. in ImageObject:

  • isAccessibleForFree should be allowed to be a boolean primitive
  • width and height should be allowed to be a number primitive
  • author and contentLocation should be allowed to be a string primitive

Related: #19

Installing as dependency (instead of devDependency) makes final bundle big

I noticed that this library lists typescript as a peer dependency in the package.json. At the same time, the README suggests installing this library by doing npm install schema-dts.

What happens then is that when I generate the bundle for my server, this library and also typescript are being bundled together with my server code, making the bundle quite big (typescript alone is 3MB minified).

Am I doing something wrong? Or should this library be installed as a devDependency instead?

Can you implement JSON output of schema.d.ts file?

Such as
--options
Specify a json option file that should be loaded. If not specified TypeDoc will look for 'schema.json' in the current directory.

--json <path/to/output.json>
Specifies the location and file name a json file describing the project is written to. When specified no documentation will be generated.

https://github.com/TypeStrong/typedoc repository is an example of json output.

TS4058: Return type of exported function has or is using name WebSiteLeaf from external module ... but cannot be named

When declaring an object to be a WebSite type, a TS4058 appears.

export function jsonld_WebSite_() { // TS4058
	return <WebSite>{
		'@type': 'WebSite',
		'@id': jsonld_WebSite_id,
		url: website,
		name: title,
		mainEntity: jsonld_Person_(),
	}
}

Looking at the source,

export type WebSite = WebSiteLeaf;

WebSiteLeaf is not in use anywhere else nor is it exported. It seems that WebSiteLeaf should be renamed to WebSite. The intermediate type is not necessary.

Allow Role to be used for use cases like defining dates

My use case is similar to the ones provided in the Example 2 for hasOccupation and in this use case for worksFor.

As stated in Schema.org hasOccupation definition: The Person's occupation. For past professions, use Role for expressing dates. In the case of worksFor is not stated explicitly but what I want is to represent additional information to a Person, as the original blog post suggests.

I'm working on a PR to solve this but in the meantime I wanted to see if the idea is right for this project.

Here is an example taken from the Role webpage:

{
    "@context": "https://schema.org",
    "@type": "Person",
    "name": "Delia Derbyshire",
    "sameAs": "http://en.wikipedia.org/wiki/Delia_Derbyshire",
    "alumniOf": {
        "@type": "OrganizationRole",
        "alumniOf": {
            "@type": "CollegeOrUniversity",
            "name": "University of Cambridge",
            "sameAs": "http://en.wikipedia.org/wiki/University_of_Cambridge"
        },
        "startDate": "1959"
    }
}

Document WithContext

I didn't understand why I couldn't add "@context": "https://schema.org" to my TypeScript object of type Product, until I realized it had to be of type WithContext<Product>. Seems necessary for Google Structured Data, so I think it should be in the README? If you agree, I can make the PR.

Startup errors when using schema generator

% node --version
v11.10.1

% npm --version
6.9.0

Installed it with npm i -S schema-dts-gen. Then:

% npx schema-dts-gen --help
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 1: use strict: command not found
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 2: /Applications: is a directory
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 3: ./LICENSE: Permission denied
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 4: ./LICENSE: Permission denied
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 5: syntax error near unexpected token `('
/Users/pelgi01/repos/personal/www.giladpeleg.com/node_modules/.bin/schema-dts-gen: line 5: ` * Licensed under the Apache License, Version 2.0 (the "License");'

It looks like this can be solved by adding shebang line on schema-dts-gen bin file:

#!/usr/bin/env node

That solves it for me

'@type' as array

Was wondering if it would be possible to use the @type in an array.
My use case would be in the context of utilizing two types like this:
'@type': (['Car', 'Product']
currently working around this by casting to one of the types
'@type': (['Car', 'Product'] as unknown as 'Car')

Would be keen to hear if this would be possible?

Wrong type picked on using WithContext

I defined a wrapper class to store data, like

export interface MyProduct {
  url: string;
  image?: string;
  name: string;
  sku?: string;
  keywords?: string;
  description?: string;
  schema?: WithContext<Product>;
  meta?: Meta;
}

But when I assign a Product object, it recognizes as Vehicle and throw type error.

const product: MyProduct = {
        "schema": {
            "offers": [
                {
                    "seller": {
                        "name": "XYZ",
                        "@type": "Organization"
                    },
                    "priceCurrency": "INR",
                    "availability": "http://schema.org/InStock",
                    "@type": "Offer",
                    "url": "https://www.xyz.com/en_in/productpage.0874876001.html",
                    "price": "1499.0"
                }
            ],
            "image": "//www.xyz.com/image.jpg",
            "color": "Pigeon blue/Floral",
            "@type": "Product",
            "name": "Fitted cotton sheet",
            "description": "Fitted sheet with an all-over print on fine-threaded, closely-woven cotton with a thread count of 144. Fits mattresses up to 23 cm deep.",
            "sku": "1234567",
            "category": {
                "name": "Sheets",
                "@type": "Thing"
            },
            "@context": "https://schema.org",
            "brand": {
                "name": "XYZ",
                "@type": "Brand"
            },
            "itemCondition": "https://schema.org/NewCondition"
        },
        "image": "//www.xyz.com/image.jpg",
        "meta": {
            "parser": "schema",
            "modifiedDate": "2022-09-14T14:09:18.639Z",
            "createdDate": "2022-09-14T14:09:18.639Z"
        },
        "name": "Fitted cotton sheet",
        "description": "Fitted sheet with an all-over print on fine-threaded, closely-woven cotton with a thread count of 144. Fits mattresses up to 23 cm deep.",
        "sku": "0874876001",
        "url": "https://www.xyz.com/en_in/productpage.0874876001.html"
      }

Error:

Type '"Product"' is not assignable to type '"MotorizedBicycle"'.ts(2322)

Any help or guidance would be appreciated. Thanks

Bundles to Webpack when not needed

I am using the library as a compile-time type checking with TypeScript, but the way that the exports are done, the root .js file is included anyway in the bundle. Is there any way to just add the types to my project without the runtime support?

Updating the schema

I tried to generate the types from the latest Schema.org Schema and noticed that schema.org has changed their location for the vocabulary definitions from:

https://schema.org/version/latest/all-layers.nt

to

https://schema.org/version/latest/schemaorg-all-https.nt

Simply updating the layer does not work because the new tuple file contains entries like:

<https://schema.org/aspect> <https://schema.org/isPartOf> <http://health-lifesci.schema.org> .

Which will give the following error when parsed.

Error: ParseError: Error: Unexpected URL http://health-lifesci.schema.org/ with no room for 'name'. while parsing line https://schema.org/aspect,https://schema.org/isPartOf,<http://health-lifesci.schema.org>.
Original Stack:
Error: Unexpected URL http://health-lifesci.schema.org/ with no room for 'name'.
    at Parse (schema-dts/built/src/triples/types.js:92:19)
    at schema-dts/built/src/triples/reader.js:31:20
    at object (schema-dts/built/src/triples/reader.js:43:38)
    at process (schema-dts/built/src/triples/reader.js:149:25)
    at process.next (<anonymous>)
    at IncomingMessage.<anonymous> (schema-dts/built/src/triples/reader.js:94:28)
    at IncomingMessage.emit (events.js:327:22)
    at endReadableNT (_stream_readable.js:1224:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:21)

Add support for custom attributes

Problem
Sometimes, we need to input a custom attribute in the Schema. For instance the sitelinks-searchbox structured data requires a query-input attribute that is not available in the schema.org representation. However, I can't add it manually, because the compiler will throw:

Object literal may only specify known properties, and '"query-input"' does not exist in type 'SearchActionLeaf'

potentialAction: {
    "@id":  `${process.env.NEXT_PUBLIC_WEBSITE_URL}/explore`,
    "@type": "SearchAction",
     target: `${process.env.NEXT_PUBLIC_WEBSITE_URL}/explore/results?q={search_term_string}`,
    "query-input": "required name=search_term_string"
}

Solution
Add an attribute that let's you input a custom key value pair.

declare type ThingBase = Partial<IdReference> & {
    /** An additional type for the item, typically used for adding more specific types from external vocabularies in microdata syntax. This is a relationship between something and a class that the thing is in. In RDFa syntax, it is better to use the native RDFa syntax - the 'typeof' attribute - for multiple types. Schema.org tools may have only weaker understanding of extra types, in particular those defined externally. */
    "additionalType"?: SchemaValue<URL>;
    /** An alias for the item. */
    "alternateName"?: SchemaValue<Text>;
    /** A description of the item. */
    "description"?: SchemaValue<Text>;
    /** A sub property of description. A short description of the item used to disambiguate from other, similar items. Information from other properties (in particular, name) may be necessary for the description to be useful for disambiguation. */
    "disambiguatingDescription"?: SchemaValue<Text>;
    /** The identifier property represents any kind of identifier for any kind of {@link http://schema.org/Thing Thing}, such as ISBNs, GTIN codes, UUIDs etc. Schema.org provides dedicated properties for representing many of these, either as textual strings or as URL (URI) links. See {@link /docs/datamodel.html#identifierBg background notes} for more details. */
    "identifier"?: SchemaValue<PropertyValue | Text | URL | IdReference>;
    /** An image of the item. This can be a {@link http://schema.org/URL URL} or a fully described {@link http://schema.org/ImageObject ImageObject}. */
    "image"?: SchemaValue<ImageObject | URL | IdReference>;
    /** Indicates a page (or other CreativeWork) for which this thing is the main entity being described. See {@link /docs/datamodel.html#mainEntityBackground background notes} for details. */
    "mainEntityOfPage"?: SchemaValue<CreativeWork | URL | IdReference>;
    /** The name of the item. */
    "name"?: SchemaValue<Text>;
    /** Indicates a potential Action, which describes an idealized action in which this thing would play an 'object' role. */
    "potentialAction"?: SchemaValue<Action | IdReference>;
    /** URL of a reference Web page that unambiguously indicates the item's identity. E.g. the URL of the item's Wikipedia page, Wikidata entry, or official website. */
    "sameAs"?: SchemaValue<URL>;
    /** A CreativeWork or Event about this Thing. */
    "subjectOf"?: SchemaValue<CreativeWork | Event | IdReference>;
    /** URL of the item. */
    "url"?: SchemaValue<URL>;
    [extra: string]: string | ThingBase<---------------------------------------
};

ThingBase is not exported

While trying to use this library with generics, I find most entities extend ThingBase, though it is not exported. I'm trying to extend/enforce our own pattern of use and the lack of export is causing some difficulty.

My suggestion would be to simply all created types, and allow the users to determine how they might want to utilize them.

Here's a short use case:

import { ThingBase } from 'schema-dts'

export type Identified = {
  /**
   * preferably url e.g. https://alienfast.com/#organization
   */
  '@id': string
}

export type WithId<T extends ThingBase> = T & Identified

export function ref<I extends Identified>(i: I): Identified {
  return { '@id': i['@id'] }
}

I figured I would file an issue before taking a look at a PR. Thoughts or concerns?

The WithContext type is invalid

The WithContext type accepts all Thing types:

/** Used at the top-level node to indicate the context for the JSON-LD objects used. The context provided in this type is compatible with the keys and URLs in the rest of this generated file. */
export declare type WithContext<T extends Thing> = T & {
    "@context": "https://schema.org";
};

However, Thing allows string values. For example:

export const thing: Thing = '';

It's not possible to intersect string and object, which makes the WithContext type invalid.

Why does SchemaValue generally allow arrays?

Hi,

I've just discovered schema.org and the schema-dts typescript typings and I am a bit confused:

I am reading/processing a JSON-LD for a recipe schema.
The url property of the recipe, for example, does not seem to be a an array in the schema definition, but the SchemaValue typing allows arrays. Therefore, when accessing the url property of the JSON-LD, I need to check if the value is a plain value or an array, even though it isn't allowed to be an array?

Is this for any specific reason?

Feature Request: schema-dts-gen --file=my-custom-schema-file.nt

Currently schema-dts-gen accepts a HTTPS parameter for the schema:
schema-dts-gen --ontology=https://schema.org/version/latest/schemaorg-all-https.nt

As an alternative, specifically for folks building external extensions who may wish to vary the contents of the ontology during automated builds (on devops machines, perhaps without network access), it would be useful if schema-dts-gen could instead accept the schema as a local file:
schema-dts-gen --file=my-custom-schema-file.nt

URL type definition

Can't asign string to type 'URL'.
 2019-05-30 10 43 28

Error Message

Type 'string' is not assignable to type 'URL | URL[] | undefined'.ts(2322)

I think it should be, but URL is defined as

{ "@type": "URL" } & string

 2019-05-30 10 48 11

I'm not so familiar with schema.org and don't know about { "@type": "URL" }, but

{ "@type": "URL" } | string
is probably right?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.