Unverified Commit 4ad16a23 authored by Hong Minhee's avatar Hong Minhee
Browse files

Improved runtime type error for Vocabulary API

parent 8587a096
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@ Version 0.11.0

To be released.

 -  Improved runtime type error messages for Activity Vocabulary API.  [[#79]]

 -  Added `Federation.setInboxDispatcher()` method.  [[#71]]

 -  Frequently used JSON-LD contexts are now preloaded.  [[74]]
@@ -30,6 +32,7 @@ To be released.
[#71]: https://github.com/dahlia/fedify/issues/71
[#74]: https://github.com/dahlia/fedify/issues/74
[#76]: https://github.com/dahlia/fedify/pull/76
[#79]: https://github.com/dahlia/fedify/issues/79


Version 0.10.0
+4130 −931

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ export async function* generateClasses(
  yield "// deno-lint-ignore-file ban-unused-ignore\n";
  yield "// @ts-ignore TS7016\n";
  yield 'import jsonld from "jsonld";\n';
  yield `import { type LanguageTag, parseLanguageTag }
  yield `import { LanguageTag, parseLanguageTag }
    from "@phensley/language-tag";\n`;
  yield `import { decode as decodeMultibase, encode as encodeMultibase }
    from "multibase";`;
+83 −7
Original line number Diff line number Diff line
import { getFieldName } from "./field.ts";
import type { PropertySchema, TypeSchema } from "./schema.ts";
import { areAllScalarTypes, getTypeNames } from "./type.ts";
import { areAllScalarTypes, getTypeGuards, getTypeNames } from "./type.ts";

function generateParameterType(
  property: PropertySchema,
@@ -25,7 +25,7 @@ function generateParameterType(
  if (!property.functional) {
    if (scalar) {
      code.push(
        `${property.pluralName}?: ${getTypeNames(range, types, true)}[];`,
        `${property.pluralName}?: (${getTypeNames(range, types, true)})[];`,
      );
    } else {
      code.push(
@@ -87,7 +87,11 @@ export async function* generateConstructor(
    yield `
    this.#documentLoader = documentLoader;
    this.#contextLoader = contextLoader;
    if (values.id == null || values.id instanceof URL) {
      this.id = values.id ?? null;
    } else {
      throw new TypeError("The id must be a URL.");
    }
    `;
  } else {
    yield "super(values, { documentLoader, contextLoader });";
@@ -95,14 +99,41 @@ export async function* generateConstructor(
  for (const property of type.properties) {
    const fieldName = await getFieldName(property.uri);
    if (property.functional || property.singularAccessor) {
      let typeGuards = getTypeGuards(
        property.range,
        types,
        `values.${property.singularName}`,
      );
      let typeNames = getTypeNames(property.range, types);
      const scalar = areAllScalarTypes(property.range, types);
      if (!scalar) {
        typeGuards =
          `${typeGuards} || values.${property.singularName} instanceof URL`;
        typeNames = `${typeNames} | URL`;
      }
      yield `
        if ("${property.singularName}" in values && \
            values.${property.singularName} != null) {
          if (${typeGuards}) {
            // @ts-ignore: type is checked above.
            this.${fieldName} = [values.${property.singularName}];
          } else {
            throw new TypeError(
              "The ${property.singularName} must be of type " +
              ${JSON.stringify(typeNames)} + ".",
            );
          }
        }
      `;
    }
    if (!property.functional) {
      let typeGuards = getTypeGuards(property.range, types, `v`);
      let typeNames = getTypeNames(property.range, types);
      const scalar = areAllScalarTypes(property.range, types);
      if (!scalar) {
        typeGuards = `${typeGuards} || v instanceof URL`;
        typeNames = `${typeNames} | URL`;
      }
      yield `
        if ("${property.pluralName}" in values && \
            values.${property.pluralName} != null) {
@@ -119,7 +150,16 @@ export async function* generateConstructor(
        `;
      }
      yield `
          if (Array.isArray(values.${property.pluralName}) &&
              values.${property.pluralName}.every(v => ${typeGuards})) {
            // @ts-ignore: type is checked above.
            this.${fieldName} = values.${property.pluralName};
          } else {
            throw new TypeError(
              "The ${property.pluralName} must be an array of type " +
              ${JSON.stringify(typeNames)} + ".",
            );
          }
        }
      `;
    }
@@ -166,14 +206,41 @@ export async function* generateCloner(
    const fieldName = await getFieldName(property.uri);
    yield `clone.${fieldName} = this.${fieldName};`;
    if (property.functional || property.singularAccessor) {
      let typeGuards = getTypeGuards(
        property.range,
        types,
        `values.${property.singularName}`,
      );
      let typeNames = getTypeNames(property.range, types);
      const scalar = areAllScalarTypes(property.range, types);
      if (!scalar) {
        typeGuards =
          `${typeGuards} || values.${property.singularName} instanceof URL`;
        typeNames = `${typeNames} | URL`;
      }
      yield `
        if ("${property.singularName}" in values && \
            values.${property.singularName} != null) {
          if (${typeGuards}) {
            // @ts-ignore: type is checked above.
            clone.${fieldName} = [values.${property.singularName}];
          } else {
            throw new TypeError(
              "The ${property.singularName} must be of type " +
              ${JSON.stringify(typeNames)} + ".",
            );
          }
        }
      `;
    }
    if (!property.functional) {
      let typeGuards = getTypeGuards(property.range, types, `v`);
      let typeNames = getTypeNames(property.range, types);
      const scalar = areAllScalarTypes(property.range, types);
      if (!scalar) {
        typeGuards = `${typeGuards} || v instanceof URL`;
        typeNames = `${typeNames} | URL`;
      }
      yield `
        if ("${property.pluralName}" in values && \
            values.${property.pluralName} != null) {
@@ -190,7 +257,16 @@ export async function* generateCloner(
        `;
      }
      yield `
          if (Array.isArray(values.${property.pluralName}) &&
              values.${property.pluralName}.every(v => ${typeGuards})) {
            // @ts-ignore: type is checked above.
            clone.${fieldName} = values.${property.pluralName};
          } else {
            throw new TypeError(
              "The ${property.pluralName} must be an array of type " +
              ${JSON.stringify(typeNames)} + ".",
            );
          }
        }
      `;
    }
+2 −2
Original line number Diff line number Diff line
@@ -20,9 +20,9 @@ export async function generateField(
): Promise<string> {
  const fieldName = await getFieldName(property.uri, prefix);
  if (areAllScalarTypes(property.range, types)) {
    return `${fieldName}: ${
    return `${fieldName}: (${
      getTypeNames(property.range, types, true)
    }[] = [];\n`;
    })[] = [];\n`;
  } else {
    return `${fieldName}: (${
      getTypeNames(property.range, types)
Loading