UNPKG

schema-dts-gen

Version:

Generate TypeScript Definitions for Schema.org Schema

129 lines 5.63 kB
/** * Copyright 2023 Google LLC * * 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. */ import { Log } from '../logging/index.js'; import { IsDirectlyNamedClass, IsDataType, ClassIsDataType, IsSubclass, } from '../triples/wellKnown.js'; import { AliasBuiltin, Class, DataTypeUnion, RoleBuiltin, } from '../ts/class.js'; import { assert, assertIs } from '../util/assert.js'; import { NamedNode } from 'n3'; import { shortStr } from '../index.js'; function toClass(cls, topic, map) { const rest = []; for (const value of topic.quads) { const added = cls.add(value, map); if (!added) rest.push(value); } if (rest.length > 0) { Log(`Class ${shortStr(cls.subject)}: Did not add [${rest .map(r => `(${shortStr(r.predicate)} ${shortStr(r.object)})`) .join(',')}]`); } return cls; } function buildAlias(name, alias) { return [ new AliasBuiltin(new NamedNode(`http://schema.org/${name}`), AliasBuiltin.Alias(alias)), new AliasBuiltin(new NamedNode(`https://schema.org/${name}`), AliasBuiltin.Alias(alias)), ]; } const wellKnownTypes = [ ...buildAlias('Text', 'string'), // IMPORTANT: In the future, if possible, we should have: `${number}` in Float only, // an integer string literal in Integer only, and Number becomes simply Float|Integer. new AliasBuiltin(new NamedNode('http://schema.org/Number'), AliasBuiltin.Alias('number'), AliasBuiltin.NumberStringLiteral()), new AliasBuiltin(new NamedNode('https://schema.org/Number'), AliasBuiltin.Alias('number'), AliasBuiltin.NumberStringLiteral()), ...buildAlias('Time', 'string'), ...buildAlias('Date', 'string'), ...buildAlias('DateTime', 'string'), ...buildAlias('Boolean', 'boolean'), ...buildAlias('Quantity', 'string'), new RoleBuiltin(new NamedNode('http://schema.org/Role')), new RoleBuiltin(new NamedNode('http://schema.org/OrganizationRole')), new RoleBuiltin(new NamedNode('http://schema.org/EmployeeRole')), new RoleBuiltin(new NamedNode('http://schema.org/LinkRole')), new RoleBuiltin(new NamedNode('http://schema.org/PerformanceRole')), new RoleBuiltin(new NamedNode('https://schema.org/Role')), new RoleBuiltin(new NamedNode('https://schema.org/OrganizationRole')), new RoleBuiltin(new NamedNode('https://schema.org/EmployeeRole')), new RoleBuiltin(new NamedNode('https://schema.org/LinkRole')), new RoleBuiltin(new NamedNode('https://schema.org/PerformanceRole')), ]; // Should we allow 'string' to be a valid type for all values of this type? const wellKnownStrings = [ new NamedNode('http://schema.org/Quantity'), new NamedNode('http://schema.org/EntryPoint'), new NamedNode('http://schema.org/Organization'), new NamedNode('http://schema.org/Person'), new NamedNode('http://schema.org/Place'), new NamedNode('https://schema.org/Quantity'), new NamedNode('https://schema.org/EntryPoint'), new NamedNode('https://schema.org/Organization'), new NamedNode('https://schema.org/Person'), new NamedNode('https://schema.org/Place'), ]; function ForwardDeclareClasses(topics) { const classes = new Map(); const dataType = new DataTypeUnion(new NamedNode('http://schema.org/DataType'), []); for (const topic of topics) { if (IsDataType(topic.subject)) { classes.set(topic.subject.value, dataType); continue; } else if (!IsDirectlyNamedClass(topic) && !IsSubclass(topic)) continue; const wk = wellKnownTypes.find(wk => wk.subject.equals(topic.subject)); if (ClassIsDataType(topic)) { assert(wk, `${topic.subject.value} must have corresponding well-known type.`); dataType.wk.push(wk); wk['_isDataType'] = true; } assertIs(topic.subject, (s) => s.termType === 'NamedNode'); const cls = wk || new Class(topic.subject); const allowString = wellKnownStrings.some(wks => wks.equals(topic.subject)); if (allowString) cls.addTypedef(AliasBuiltin.Alias('string')); if (IsDirectlyNamedClass(topic)) cls.markAsExplicitClass(); classes.set(topic.subject.value, cls); } return classes; } function BuildClasses(topics, classes) { for (const topic of topics) { if (!IsDirectlyNamedClass(topic) && !IsSubclass(topic)) continue; const cls = classes.get(topic.subject.value); assert(cls); toClass(cls, topic, classes); } for (const cls of classes.values()) { cls.validateClass(); } } /** * Produce a mapping of all Classes within the Ontology. The resulting classes * are empty and only describes their names, comments, and inheritance * relations. * * @param topics a sequence of processed triples describing an Ontology. * @returns ClassMap Mapping fully qualified ID of each type to a Class. */ export function ProcessClasses(topics) { const classes = ForwardDeclareClasses(topics); BuildClasses(topics, classes); return classes; } //# sourceMappingURL=toClass.js.map