@fedify/vocab-tools 2.4.0-dev.2155 → 2.4.0-dev.2159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/deno.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-tools",
3
- "version": "2.4.0-dev.2155+2ccc5085",
3
+ "version": "2.4.0-dev.2159+bb072eda",
4
4
  "license": "MIT",
5
5
  "exports": {
6
6
  ".": "./src/mod.ts"
package/dist/mod.cjs CHANGED
@@ -8,7 +8,7 @@ let yaml = require("yaml");
8
8
  let es_toolkit = require("es-toolkit");
9
9
  //#region deno.json
10
10
  var name = "@fedify/vocab-tools";
11
- var version = "2.4.0-dev.2155+2ccc5085";
11
+ var version = "2.4.0-dev.2159+bb072eda";
12
12
  //#endregion
13
13
  //#region src/type.ts
14
14
  const HEURISTICS_CONTEXTS = [
@@ -318,13 +318,14 @@ const scalarTypes = {
318
318
  return `formatIri(${v})`;
319
319
  },
320
320
  dataCheck(v) {
321
- return `typeof ${v} === "object" && "@value" in ${v}
322
- && typeof ${v}["@value"] === "string"
323
- && ${v}["@value"] !== "" && ${v}["@value"] !== "/"`;
321
+ return `typeof ${v} === "object" &&
322
+ ((typeof ${v}["@id"] === "string" && canDecodeIri(${v}["@id"])) ||
323
+ (typeof ${v}["@value"] === "string" && canDecodeIri(${v}["@value"])))`;
324
324
  },
325
325
  decoder(v) {
326
- return `parseIri(${v}["@value"])`;
327
- }
326
+ return `decodeIri(typeof ${v}["@id"] === "string" ? ${v}["@id"] : ${v}["@value"])`;
327
+ },
328
+ skipUnparsable: true
328
329
  },
329
330
  "fedify:gatewayUrl": {
330
331
  name: "URL",
@@ -558,6 +559,9 @@ function getDecoder(typeUri, types, variable, optionsVariable, baseUrlVariable)
558
559
  )`;
559
560
  throw new Error(`Unknown type: ${typeUri}`);
560
561
  }
562
+ function skipsUnparsable(typeUri) {
563
+ return scalarTypes[typeUri]?.skipUnparsable ?? false;
564
+ }
561
565
  function getDataCheck(typeUri, types, variable) {
562
566
  if (typeUri in scalarTypes) return scalarTypes[typeUri].dataCheck(variable);
563
567
  if (typeUri in types) {
@@ -1198,8 +1202,15 @@ async function* generateDecoder(typeUri, types, moduleVarNames) {
1198
1202
  yield `
1199
1203
  const decoded =
1200
1204
  `;
1201
- if (property.range.length == 1) yield getDecoder(property.range[0], types, "v", "options", propertyBaseUrl);
1202
- else {
1205
+ const lenient = property.range.length == 1 && skipsUnparsable(property.range[0]);
1206
+ if (property.range.length == 1) {
1207
+ if (lenient) {
1208
+ yield getDataCheck(property.range[0], types, "v");
1209
+ yield " ? ";
1210
+ }
1211
+ yield getDecoder(property.range[0], types, "v", "options", propertyBaseUrl);
1212
+ if (lenient) yield " : undefined";
1213
+ } else {
1203
1214
  const decoders = getDecoders(property.range, types, "v", "options", propertyBaseUrl);
1204
1215
  for (const code of decoders) yield code;
1205
1216
  }
@@ -2041,8 +2052,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2041
2052
  return fetched;
2042
2053
  }
2043
2054
  `;
2044
- if (property.compactName != null) {
2045
- yield `
2055
+ if (property.compactName != null) yield `
2046
2056
  if (
2047
2057
  this._cachedJsonLd != null &&
2048
2058
  typeof this._cachedJsonLd === "object" &&
@@ -2053,22 +2063,24 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2053
2063
  ${JSON.stringify(property.compactName)}];
2054
2064
  const doc = Array.isArray(prop) ? prop[0] : prop;
2055
2065
  if (doc != null && typeof doc === "object" && "@context" in doc) {
2056
- `;
2057
- yield `
2058
- v = await this.#${property.singularName}_fromJsonLd(doc, {
2059
- ...options,
2060
- // Embedded objects get this object's own default, whether or
2061
- // not they carry their own @context, as when this object was
2062
- // parsed:
2063
- verifyPortableObject: this._verifyPortableObject,
2064
- baseUrl: ${cachedPropertyBaseUrl},
2065
- });
2066
- `;
2067
- yield `
2066
+ try {
2067
+ v = await this.#${property.singularName}_fromJsonLd(doc, {
2068
+ ...options,
2069
+ // Keep the parent default for embedded objects.
2070
+ verifyPortableObject: this._verifyPortableObject,
2071
+ baseUrl: ${cachedPropertyBaseUrl},
2072
+ });
2073
+ } catch (error) {
2074
+ if (!options.suppressError) throw error;
2075
+ getLogger(["fedify", "vocab"]).debug(
2076
+ "Failed to parse embedded value of {property}: {error}",
2077
+ { property: ${JSON.stringify(property.uri)}, error },
2078
+ );
2079
+ return null;
2080
+ }
2068
2081
  }
2069
2082
  }
2070
2083
  `;
2071
- }
2072
2084
  yield `
2073
2085
  if (v?.id != null &&
2074
2086
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
@@ -2197,8 +2209,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2197
2209
  continue;
2198
2210
  }
2199
2211
  `;
2200
- if (property.compactName != null) {
2201
- yield `
2212
+ if (property.compactName != null) yield `
2202
2213
  if (
2203
2214
  this._cachedJsonLd != null &&
2204
2215
  typeof this._cachedJsonLd === "object" &&
@@ -2209,22 +2220,24 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2209
2220
  ${JSON.stringify(property.compactName)}];
2210
2221
  const obj = Array.isArray(prop) ? prop[i] : prop;
2211
2222
  if (obj != null && typeof obj === "object" && "@context" in obj) {
2212
- `;
2213
- yield `
2214
- v = await this.#${property.singularName}_fromJsonLd(obj, {
2215
- ...options,
2216
- // Embedded objects get this object's own default, whether or
2217
- // not they carry their own @context, as when this object was
2218
- // parsed:
2223
+ try {
2224
+ v = await this.#${property.singularName}_fromJsonLd(obj, {
2225
+ ...options,
2226
+ // Keep the parent default for embedded objects.
2219
2227
  verifyPortableObject: this._verifyPortableObject,
2220
- baseUrl: ${cachedPropertyBaseUrl},
2221
- });
2222
- `;
2223
- yield `
2228
+ baseUrl: ${cachedPropertyBaseUrl},
2229
+ });
2230
+ } catch (error) {
2231
+ if (!options.suppressError) throw error;
2232
+ getLogger(["fedify", "vocab"]).debug(
2233
+ "Failed to parse embedded value of {property} at index {index}: {error}",
2234
+ { property: ${JSON.stringify(property.uri)}, index: i, error },
2235
+ );
2236
+ continue;
2237
+ }
2224
2238
  }
2225
2239
  }
2226
2240
  `;
2227
- }
2228
2241
  yield `
2229
2242
  if (v?.id != null &&
2230
2243
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
@@ -2505,6 +2518,17 @@ async function* generateClasses(types) {
2505
2518
  isTemporalInstant,
2506
2519
  } from "@fedify/vocab-runtime/temporal";\n`;
2507
2520
  yield `
2521
+ function canDecodeIri(iri: string): boolean {
2522
+ try { parseIri(iri); return true; } catch { return iri.startsWith("at://"); }
2523
+ }
2524
+
2525
+ function decodeIri(iri: string): URL {
2526
+ return !URL.canParse(iri) && iri.startsWith("at://")
2527
+ ? new URL("at://" + encodeURIComponent(iri.substring(5)))
2528
+ : parseIri(iri);
2529
+ }
2530
+ `;
2531
+ yield `
2508
2532
  function isValidLanguageTag(language: string): boolean {
2509
2533
  try {
2510
2534
  new Intl.Locale(language);
package/dist/mod.js CHANGED
@@ -7,7 +7,7 @@ import { parse } from "yaml";
7
7
  import { pascalCase } from "es-toolkit";
8
8
  //#region deno.json
9
9
  var name = "@fedify/vocab-tools";
10
- var version = "2.4.0-dev.2155+2ccc5085";
10
+ var version = "2.4.0-dev.2159+bb072eda";
11
11
  //#endregion
12
12
  //#region src/type.ts
13
13
  const HEURISTICS_CONTEXTS = [
@@ -317,13 +317,14 @@ const scalarTypes = {
317
317
  return `formatIri(${v})`;
318
318
  },
319
319
  dataCheck(v) {
320
- return `typeof ${v} === "object" && "@value" in ${v}
321
- && typeof ${v}["@value"] === "string"
322
- && ${v}["@value"] !== "" && ${v}["@value"] !== "/"`;
320
+ return `typeof ${v} === "object" &&
321
+ ((typeof ${v}["@id"] === "string" && canDecodeIri(${v}["@id"])) ||
322
+ (typeof ${v}["@value"] === "string" && canDecodeIri(${v}["@value"])))`;
323
323
  },
324
324
  decoder(v) {
325
- return `parseIri(${v}["@value"])`;
326
- }
325
+ return `decodeIri(typeof ${v}["@id"] === "string" ? ${v}["@id"] : ${v}["@value"])`;
326
+ },
327
+ skipUnparsable: true
327
328
  },
328
329
  "fedify:gatewayUrl": {
329
330
  name: "URL",
@@ -557,6 +558,9 @@ function getDecoder(typeUri, types, variable, optionsVariable, baseUrlVariable)
557
558
  )`;
558
559
  throw new Error(`Unknown type: ${typeUri}`);
559
560
  }
561
+ function skipsUnparsable(typeUri) {
562
+ return scalarTypes[typeUri]?.skipUnparsable ?? false;
563
+ }
560
564
  function getDataCheck(typeUri, types, variable) {
561
565
  if (typeUri in scalarTypes) return scalarTypes[typeUri].dataCheck(variable);
562
566
  if (typeUri in types) {
@@ -1197,8 +1201,15 @@ async function* generateDecoder(typeUri, types, moduleVarNames) {
1197
1201
  yield `
1198
1202
  const decoded =
1199
1203
  `;
1200
- if (property.range.length == 1) yield getDecoder(property.range[0], types, "v", "options", propertyBaseUrl);
1201
- else {
1204
+ const lenient = property.range.length == 1 && skipsUnparsable(property.range[0]);
1205
+ if (property.range.length == 1) {
1206
+ if (lenient) {
1207
+ yield getDataCheck(property.range[0], types, "v");
1208
+ yield " ? ";
1209
+ }
1210
+ yield getDecoder(property.range[0], types, "v", "options", propertyBaseUrl);
1211
+ if (lenient) yield " : undefined";
1212
+ } else {
1202
1213
  const decoders = getDecoders(property.range, types, "v", "options", propertyBaseUrl);
1203
1214
  for (const code of decoders) yield code;
1204
1215
  }
@@ -2040,8 +2051,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2040
2051
  return fetched;
2041
2052
  }
2042
2053
  `;
2043
- if (property.compactName != null) {
2044
- yield `
2054
+ if (property.compactName != null) yield `
2045
2055
  if (
2046
2056
  this._cachedJsonLd != null &&
2047
2057
  typeof this._cachedJsonLd === "object" &&
@@ -2052,22 +2062,24 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2052
2062
  ${JSON.stringify(property.compactName)}];
2053
2063
  const doc = Array.isArray(prop) ? prop[0] : prop;
2054
2064
  if (doc != null && typeof doc === "object" && "@context" in doc) {
2055
- `;
2056
- yield `
2057
- v = await this.#${property.singularName}_fromJsonLd(doc, {
2058
- ...options,
2059
- // Embedded objects get this object's own default, whether or
2060
- // not they carry their own @context, as when this object was
2061
- // parsed:
2062
- verifyPortableObject: this._verifyPortableObject,
2063
- baseUrl: ${cachedPropertyBaseUrl},
2064
- });
2065
- `;
2066
- yield `
2065
+ try {
2066
+ v = await this.#${property.singularName}_fromJsonLd(doc, {
2067
+ ...options,
2068
+ // Keep the parent default for embedded objects.
2069
+ verifyPortableObject: this._verifyPortableObject,
2070
+ baseUrl: ${cachedPropertyBaseUrl},
2071
+ });
2072
+ } catch (error) {
2073
+ if (!options.suppressError) throw error;
2074
+ getLogger(["fedify", "vocab"]).debug(
2075
+ "Failed to parse embedded value of {property}: {error}",
2076
+ { property: ${JSON.stringify(property.uri)}, error },
2077
+ );
2078
+ return null;
2079
+ }
2067
2080
  }
2068
2081
  }
2069
2082
  `;
2070
- }
2071
2083
  yield `
2072
2084
  if (v?.id != null &&
2073
2085
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
@@ -2196,8 +2208,7 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2196
2208
  continue;
2197
2209
  }
2198
2210
  `;
2199
- if (property.compactName != null) {
2200
- yield `
2211
+ if (property.compactName != null) yield `
2201
2212
  if (
2202
2213
  this._cachedJsonLd != null &&
2203
2214
  typeof this._cachedJsonLd === "object" &&
@@ -2208,22 +2219,24 @@ async function* generateProperty(type, property, types, moduleVarNames) {
2208
2219
  ${JSON.stringify(property.compactName)}];
2209
2220
  const obj = Array.isArray(prop) ? prop[i] : prop;
2210
2221
  if (obj != null && typeof obj === "object" && "@context" in obj) {
2211
- `;
2212
- yield `
2213
- v = await this.#${property.singularName}_fromJsonLd(obj, {
2214
- ...options,
2215
- // Embedded objects get this object's own default, whether or
2216
- // not they carry their own @context, as when this object was
2217
- // parsed:
2222
+ try {
2223
+ v = await this.#${property.singularName}_fromJsonLd(obj, {
2224
+ ...options,
2225
+ // Keep the parent default for embedded objects.
2218
2226
  verifyPortableObject: this._verifyPortableObject,
2219
- baseUrl: ${cachedPropertyBaseUrl},
2220
- });
2221
- `;
2222
- yield `
2227
+ baseUrl: ${cachedPropertyBaseUrl},
2228
+ });
2229
+ } catch (error) {
2230
+ if (!options.suppressError) throw error;
2231
+ getLogger(["fedify", "vocab"]).debug(
2232
+ "Failed to parse embedded value of {property} at index {index}: {error}",
2233
+ { property: ${JSON.stringify(property.uri)}, index: i, error },
2234
+ );
2235
+ continue;
2236
+ }
2223
2237
  }
2224
2238
  }
2225
2239
  `;
2226
- }
2227
2240
  yield `
2228
2241
  if (v?.id != null &&
2229
2242
  ((${type.trustEmbeddedObjects === false ? "" : "this.id != null && "}!isTrustedIriOrigin(options, v.id, ${trustOwner})) ||
@@ -2504,6 +2517,17 @@ async function* generateClasses(types) {
2504
2517
  isTemporalInstant,
2505
2518
  } from "@fedify/vocab-runtime/temporal";\n`;
2506
2519
  yield `
2520
+ function canDecodeIri(iri: string): boolean {
2521
+ try { parseIri(iri); return true; } catch { return iri.startsWith("at://"); }
2522
+ }
2523
+
2524
+ function decodeIri(iri: string): URL {
2525
+ return !URL.canParse(iri) && iri.startsWith("at://")
2526
+ ? new URL("at://" + encodeURIComponent(iri.substring(5)))
2527
+ : parseIri(iri);
2528
+ }
2529
+ `;
2530
+ yield `
2507
2531
  function isValidLanguageTag(language: string): boolean {
2508
2532
  try {
2509
2533
  new Intl.Locale(language);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fedify/vocab-tools",
3
- "version": "2.4.0-dev.2155+2ccc5085",
3
+ "version": "2.4.0-dev.2159+bb072eda",
4
4
  "description": "Code generator for Activity Vocabulary APIs",
5
5
  "homepage": "https://fedify.dev/",
6
6
  "repository": {