@fedify/vocab-runtime 2.0.0-dev.1908 → 2.0.0-dev.196

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.
Files changed (46) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -1
  3. package/deno.json +7 -1
  4. package/dist/chunk-DWy1uDak.cjs +39 -0
  5. package/dist/docloader.test.cjs +5851 -0
  6. package/dist/docloader.test.d.cts +1 -0
  7. package/dist/docloader.test.d.ts +1 -0
  8. package/dist/docloader.test.js +5877 -0
  9. package/dist/key.test.cjs +272 -0
  10. package/dist/key.test.d.cts +1 -0
  11. package/dist/key.test.d.ts +1 -0
  12. package/dist/key.test.js +271 -0
  13. package/dist/langstr.test.cjs +51 -0
  14. package/dist/langstr.test.d.cts +1 -0
  15. package/dist/langstr.test.d.ts +1 -0
  16. package/dist/langstr.test.js +50 -0
  17. package/dist/link-CdFPEo9O.cjs +189 -0
  18. package/dist/link-Ck2yj4dH.js +183 -0
  19. package/dist/link.test.cjs +56 -0
  20. package/dist/link.test.d.cts +1 -0
  21. package/dist/link.test.d.ts +1 -0
  22. package/dist/link.test.js +55 -0
  23. package/dist/mod.cjs +102 -63
  24. package/dist/mod.js +102 -63
  25. package/dist/multibase/multibase.test.cjs +346 -0
  26. package/dist/multibase/multibase.test.d.cts +1 -0
  27. package/dist/multibase/multibase.test.d.ts +1 -0
  28. package/dist/multibase/multibase.test.js +345 -0
  29. package/dist/multibase-BFbBiaPE.cjs +347 -0
  30. package/dist/multibase-DStmqni9.js +311 -0
  31. package/dist/request-BPQb2VYj.cjs +138 -0
  32. package/dist/request-SuYiIZUu.js +108 -0
  33. package/dist/request.test.cjs +44 -0
  34. package/dist/request.test.d.cts +1 -0
  35. package/dist/request.test.d.ts +1 -0
  36. package/dist/request.test.js +43 -0
  37. package/dist/url-C5Vs9nYh.cjs +93 -0
  38. package/dist/url-fW_DHbih.js +63 -0
  39. package/dist/url.test.cjs +37 -0
  40. package/dist/url.test.d.cts +1 -0
  41. package/dist/url.test.d.ts +1 -0
  42. package/dist/url.test.js +36 -0
  43. package/package.json +4 -3
  44. package/src/docloader.test.ts +29 -1
  45. package/src/docloader.ts +101 -45
  46. package/tsdown.config.ts +18 -7
package/dist/mod.cjs CHANGED
@@ -22,6 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
 
23
23
  //#endregion
24
24
  const __logtape_logtape = __toESM(require("@logtape/logtape"));
25
+ const __opentelemetry_api = __toESM(require("@opentelemetry/api"));
25
26
  const node_process = __toESM(require("node:process"));
26
27
  const node_dns_promises = __toESM(require("node:dns/promises"));
27
28
  const node_net = __toESM(require("node:net"));
@@ -4178,6 +4179,45 @@ const preloadedContexts = {
4178
4179
  };
4179
4180
  var contexts_default = preloadedContexts;
4180
4181
 
4182
+ //#endregion
4183
+ //#region deno.json
4184
+ var name = "@fedify/vocab-runtime";
4185
+ var version = "2.0.0-dev.196+c3cfc0a9";
4186
+ var license = "MIT";
4187
+ var exports$1 = { ".": "./src/mod.ts" };
4188
+ var description = "Runtime library for @fedify/vocab";
4189
+ var author = {
4190
+ "name": "Hong Minhee",
4191
+ "email": "hong@minhee.org",
4192
+ "url": "https://hongminhee.org/"
4193
+ };
4194
+ var imports = {
4195
+ "@multiformats/base-x": "npm:@multiformats/base-x@^4.0.1",
4196
+ "asn1js": "npm:asn1js@^3.0.6",
4197
+ "byte-encodings": "npm:byte-encodings@^1.0.11",
4198
+ "fetch-mock": "npm:fetch-mock@^12.5.4",
4199
+ "multicodec": "npm:multicodec@^3.2.1",
4200
+ "pkijs": "npm:pkijs@^3.2.5"
4201
+ };
4202
+ var exclude = ["dist", "node_modules"];
4203
+ var publish = { "exclude": ["**/*.test.ts"] };
4204
+ var tasks = {
4205
+ "check": "deno fmt --check && deno lint && deno check src/*.ts",
4206
+ "test": "deno test"
4207
+ };
4208
+ var deno_default = {
4209
+ name,
4210
+ version,
4211
+ license,
4212
+ exports: exports$1,
4213
+ description,
4214
+ author,
4215
+ imports,
4216
+ exclude,
4217
+ publish,
4218
+ tasks
4219
+ };
4220
+
4181
4221
  //#endregion
4182
4222
  //#region src/link.ts
4183
4223
  const parametersNeedLowerCase = ["rel", "type"];
@@ -4360,42 +4400,6 @@ var HttpHeaderLink = class HttpHeaderLink {
4360
4400
  }
4361
4401
  };
4362
4402
 
4363
- //#endregion
4364
- //#region deno.json
4365
- var name = "@fedify/vocab-runtime";
4366
- var version = "2.0.0-dev.1908+c31cc639";
4367
- var license = "MIT";
4368
- var exports$1 = { ".": "./src/mod.ts" };
4369
- var description = "Runtime library for @fedify/vocab";
4370
- var author = {
4371
- "name": "Hong Minhee",
4372
- "email": "hong@minhee.org",
4373
- "url": "https://hongminhee.org/"
4374
- };
4375
- var imports = {
4376
- "asn1js": "npm:asn1js@^3.0.6",
4377
- "byte-encodings": "npm:byte-encodings@^1.0.11",
4378
- "fetch-mock": "npm:fetch-mock@^12.5.4",
4379
- "multicodec": "npm:multicodec@^3.2.1",
4380
- "pkijs": "npm:pkijs@^3.2.5"
4381
- };
4382
- var exclude = ["dist", "node_modules"];
4383
- var tasks = {
4384
- "check": "deno fmt --check && deno lint && deno check src/*.ts",
4385
- "test": "deno test"
4386
- };
4387
- var deno_default = {
4388
- name,
4389
- version,
4390
- license,
4391
- exports: exports$1,
4392
- description,
4393
- author,
4394
- imports,
4395
- exclude,
4396
- tasks
4397
- };
4398
-
4399
4403
  //#endregion
4400
4404
  //#region src/request.ts
4401
4405
  /**
@@ -4582,29 +4586,38 @@ async function getRemoteDocument(url, response, fetch$1) {
4582
4586
  }
4583
4587
  let document;
4584
4588
  if (!jsonLd && (contentType === "text/html" || contentType?.startsWith("text/html;") || contentType === "application/xhtml+xml" || contentType?.startsWith("application/xhtml+xml;"))) {
4585
- const p = /<(a|link)((\s+[a-z][a-z:_-]*=("[^"]*"|'[^']*'|[^\s>]+))+)\s*\/?>/gi;
4586
- const p2 = /\s+([a-z][a-z:_-]*)=("([^"]*)"|'([^']*)'|([^\s>]+))/gi;
4589
+ const MAX_HTML_SIZE = 1024 * 1024;
4587
4590
  const html = await response.text();
4588
- let m;
4589
- const rawAttribs = [];
4590
- while ((m = p.exec(html)) !== null) rawAttribs.push(m[2]);
4591
- for (const rawAttrs of rawAttribs) {
4592
- let m2;
4593
- const attribs = {};
4594
- while ((m2 = p2.exec(rawAttrs)) !== null) {
4595
- const key = m2[1].toLowerCase();
4596
- const value = m2[3] ?? m2[4] ?? m2[5] ?? "";
4597
- attribs[key] = value;
4598
- }
4599
- if (attribs.rel === "alternate" && "type" in attribs && (attribs.type === "application/activity+json" || attribs.type === "application/ld+json" || attribs.type.startsWith("application/ld+json;")) && "href" in attribs && new URL(attribs.href, docUrl).href !== docUrl.href) {
4600
- logger.debug("Found alternate document: {alternateUrl} from {url}", {
4601
- alternateUrl: attribs.href,
4602
- url: documentUrl
4603
- });
4604
- return await fetch$1(new URL(attribs.href, docUrl).href);
4591
+ if (html.length > MAX_HTML_SIZE) {
4592
+ logger.warn("HTML response too large, skipping alternate link discovery: {url}", {
4593
+ url: documentUrl,
4594
+ size: html.length
4595
+ });
4596
+ document = JSON.parse(html);
4597
+ } else {
4598
+ const tagPattern = /<(a|link)\s+([^>]*?)\s*\/?>/gi;
4599
+ const attrPattern = /([a-z][a-z:_-]*)=(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi;
4600
+ let tagMatch;
4601
+ while ((tagMatch = tagPattern.exec(html)) !== null) {
4602
+ const tagContent = tagMatch[2];
4603
+ let attrMatch;
4604
+ const attribs = {};
4605
+ attrPattern.lastIndex = 0;
4606
+ while ((attrMatch = attrPattern.exec(tagContent)) !== null) {
4607
+ const key = attrMatch[1].toLowerCase();
4608
+ const value = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4] ?? "";
4609
+ attribs[key] = value;
4610
+ }
4611
+ if (attribs.rel === "alternate" && "type" in attribs && (attribs.type === "application/activity+json" || attribs.type === "application/ld+json" || attribs.type.startsWith("application/ld+json;")) && "href" in attribs && new URL(attribs.href, docUrl).href !== docUrl.href) {
4612
+ logger.debug("Found alternate document: {alternateUrl} from {url}", {
4613
+ alternateUrl: attribs.href,
4614
+ url: documentUrl
4615
+ });
4616
+ return await fetch$1(new URL(attribs.href, docUrl).href);
4617
+ }
4605
4618
  }
4619
+ document = JSON.parse(html);
4606
4620
  }
4607
- document = JSON.parse(html);
4608
4621
  } else document = await response.json();
4609
4622
  logger.debug("Fetched document: {status} {url} {headers}", {
4610
4623
  status: response.status,
@@ -4635,6 +4648,8 @@ async function getRemoteDocument(url, response, fetch$1) {
4635
4648
  * @since 1.3.0
4636
4649
  */
4637
4650
  function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAgent } = {}) {
4651
+ const tracerProvider = __opentelemetry_api.trace.getTracerProvider();
4652
+ const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
4638
4653
  async function load(url, options) {
4639
4654
  options?.signal?.throwIfAborted();
4640
4655
  if (!skipPreloadedContexts && url in contexts_default) {
@@ -4654,14 +4669,38 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
4654
4669
  });
4655
4670
  throw error;
4656
4671
  }
4657
- const request = createActivityPubRequest(url, { userAgent });
4658
- logRequest(logger, request);
4659
- const response = await fetch(request, {
4660
- redirect: "manual",
4661
- signal: options?.signal
4672
+ return await tracer.startActiveSpan("activitypub.fetch_document", {
4673
+ kind: __opentelemetry_api.SpanKind.CLIENT,
4674
+ attributes: { "url.full": url }
4675
+ }, async (span) => {
4676
+ try {
4677
+ const request = createActivityPubRequest(url, { userAgent });
4678
+ logRequest(logger, request);
4679
+ const response = await fetch(request, {
4680
+ redirect: "manual",
4681
+ signal: options?.signal
4682
+ });
4683
+ span.setAttribute("http.response.status_code", response.status);
4684
+ if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
4685
+ const redirectUrl = response.headers.get("Location");
4686
+ span.setAttribute("http.redirect.url", redirectUrl);
4687
+ return await load(redirectUrl, options);
4688
+ }
4689
+ const result = await getRemoteDocument(url, response, load);
4690
+ span.setAttribute("docloader.document_url", result.documentUrl);
4691
+ if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
4692
+ return result;
4693
+ } catch (error) {
4694
+ span.recordException(error);
4695
+ span.setStatus({
4696
+ code: __opentelemetry_api.SpanStatusCode.ERROR,
4697
+ message: String(error)
4698
+ });
4699
+ throw error;
4700
+ } finally {
4701
+ span.end();
4702
+ }
4662
4703
  });
4663
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) return load(response.headers.get("Location"), options);
4664
- return getRemoteDocument(url, response, load);
4665
4704
  }
4666
4705
  return load;
4667
4706
  }
package/dist/mod.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { getLogger } from "@logtape/logtape";
2
+ import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
2
3
  import process from "node:process";
3
4
  import { lookup } from "node:dns/promises";
4
5
  import { isIP } from "node:net";
@@ -4155,6 +4156,45 @@ const preloadedContexts = {
4155
4156
  };
4156
4157
  var contexts_default = preloadedContexts;
4157
4158
 
4159
+ //#endregion
4160
+ //#region deno.json
4161
+ var name = "@fedify/vocab-runtime";
4162
+ var version = "2.0.0-dev.196+c3cfc0a9";
4163
+ var license = "MIT";
4164
+ var exports = { ".": "./src/mod.ts" };
4165
+ var description = "Runtime library for @fedify/vocab";
4166
+ var author = {
4167
+ "name": "Hong Minhee",
4168
+ "email": "hong@minhee.org",
4169
+ "url": "https://hongminhee.org/"
4170
+ };
4171
+ var imports = {
4172
+ "@multiformats/base-x": "npm:@multiformats/base-x@^4.0.1",
4173
+ "asn1js": "npm:asn1js@^3.0.6",
4174
+ "byte-encodings": "npm:byte-encodings@^1.0.11",
4175
+ "fetch-mock": "npm:fetch-mock@^12.5.4",
4176
+ "multicodec": "npm:multicodec@^3.2.1",
4177
+ "pkijs": "npm:pkijs@^3.2.5"
4178
+ };
4179
+ var exclude = ["dist", "node_modules"];
4180
+ var publish = { "exclude": ["**/*.test.ts"] };
4181
+ var tasks = {
4182
+ "check": "deno fmt --check && deno lint && deno check src/*.ts",
4183
+ "test": "deno test"
4184
+ };
4185
+ var deno_default = {
4186
+ name,
4187
+ version,
4188
+ license,
4189
+ exports,
4190
+ description,
4191
+ author,
4192
+ imports,
4193
+ exclude,
4194
+ publish,
4195
+ tasks
4196
+ };
4197
+
4158
4198
  //#endregion
4159
4199
  //#region src/link.ts
4160
4200
  const parametersNeedLowerCase = ["rel", "type"];
@@ -4337,42 +4377,6 @@ var HttpHeaderLink = class HttpHeaderLink {
4337
4377
  }
4338
4378
  };
4339
4379
 
4340
- //#endregion
4341
- //#region deno.json
4342
- var name = "@fedify/vocab-runtime";
4343
- var version = "2.0.0-dev.1908+c31cc639";
4344
- var license = "MIT";
4345
- var exports = { ".": "./src/mod.ts" };
4346
- var description = "Runtime library for @fedify/vocab";
4347
- var author = {
4348
- "name": "Hong Minhee",
4349
- "email": "hong@minhee.org",
4350
- "url": "https://hongminhee.org/"
4351
- };
4352
- var imports = {
4353
- "asn1js": "npm:asn1js@^3.0.6",
4354
- "byte-encodings": "npm:byte-encodings@^1.0.11",
4355
- "fetch-mock": "npm:fetch-mock@^12.5.4",
4356
- "multicodec": "npm:multicodec@^3.2.1",
4357
- "pkijs": "npm:pkijs@^3.2.5"
4358
- };
4359
- var exclude = ["dist", "node_modules"];
4360
- var tasks = {
4361
- "check": "deno fmt --check && deno lint && deno check src/*.ts",
4362
- "test": "deno test"
4363
- };
4364
- var deno_default = {
4365
- name,
4366
- version,
4367
- license,
4368
- exports,
4369
- description,
4370
- author,
4371
- imports,
4372
- exclude,
4373
- tasks
4374
- };
4375
-
4376
4380
  //#endregion
4377
4381
  //#region src/request.ts
4378
4382
  /**
@@ -4559,29 +4563,38 @@ async function getRemoteDocument(url, response, fetch$1) {
4559
4563
  }
4560
4564
  let document;
4561
4565
  if (!jsonLd && (contentType === "text/html" || contentType?.startsWith("text/html;") || contentType === "application/xhtml+xml" || contentType?.startsWith("application/xhtml+xml;"))) {
4562
- const p = /<(a|link)((\s+[a-z][a-z:_-]*=("[^"]*"|'[^']*'|[^\s>]+))+)\s*\/?>/gi;
4563
- const p2 = /\s+([a-z][a-z:_-]*)=("([^"]*)"|'([^']*)'|([^\s>]+))/gi;
4566
+ const MAX_HTML_SIZE = 1024 * 1024;
4564
4567
  const html = await response.text();
4565
- let m;
4566
- const rawAttribs = [];
4567
- while ((m = p.exec(html)) !== null) rawAttribs.push(m[2]);
4568
- for (const rawAttrs of rawAttribs) {
4569
- let m2;
4570
- const attribs = {};
4571
- while ((m2 = p2.exec(rawAttrs)) !== null) {
4572
- const key = m2[1].toLowerCase();
4573
- const value = m2[3] ?? m2[4] ?? m2[5] ?? "";
4574
- attribs[key] = value;
4575
- }
4576
- if (attribs.rel === "alternate" && "type" in attribs && (attribs.type === "application/activity+json" || attribs.type === "application/ld+json" || attribs.type.startsWith("application/ld+json;")) && "href" in attribs && new URL(attribs.href, docUrl).href !== docUrl.href) {
4577
- logger.debug("Found alternate document: {alternateUrl} from {url}", {
4578
- alternateUrl: attribs.href,
4579
- url: documentUrl
4580
- });
4581
- return await fetch$1(new URL(attribs.href, docUrl).href);
4568
+ if (html.length > MAX_HTML_SIZE) {
4569
+ logger.warn("HTML response too large, skipping alternate link discovery: {url}", {
4570
+ url: documentUrl,
4571
+ size: html.length
4572
+ });
4573
+ document = JSON.parse(html);
4574
+ } else {
4575
+ const tagPattern = /<(a|link)\s+([^>]*?)\s*\/?>/gi;
4576
+ const attrPattern = /([a-z][a-z:_-]*)=(?:"([^"]*)"|'([^']*)'|([^\s>]+))/gi;
4577
+ let tagMatch;
4578
+ while ((tagMatch = tagPattern.exec(html)) !== null) {
4579
+ const tagContent = tagMatch[2];
4580
+ let attrMatch;
4581
+ const attribs = {};
4582
+ attrPattern.lastIndex = 0;
4583
+ while ((attrMatch = attrPattern.exec(tagContent)) !== null) {
4584
+ const key = attrMatch[1].toLowerCase();
4585
+ const value = attrMatch[2] ?? attrMatch[3] ?? attrMatch[4] ?? "";
4586
+ attribs[key] = value;
4587
+ }
4588
+ if (attribs.rel === "alternate" && "type" in attribs && (attribs.type === "application/activity+json" || attribs.type === "application/ld+json" || attribs.type.startsWith("application/ld+json;")) && "href" in attribs && new URL(attribs.href, docUrl).href !== docUrl.href) {
4589
+ logger.debug("Found alternate document: {alternateUrl} from {url}", {
4590
+ alternateUrl: attribs.href,
4591
+ url: documentUrl
4592
+ });
4593
+ return await fetch$1(new URL(attribs.href, docUrl).href);
4594
+ }
4582
4595
  }
4596
+ document = JSON.parse(html);
4583
4597
  }
4584
- document = JSON.parse(html);
4585
4598
  } else document = await response.json();
4586
4599
  logger.debug("Fetched document: {status} {url} {headers}", {
4587
4600
  status: response.status,
@@ -4612,6 +4625,8 @@ async function getRemoteDocument(url, response, fetch$1) {
4612
4625
  * @since 1.3.0
4613
4626
  */
4614
4627
  function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAgent } = {}) {
4628
+ const tracerProvider = trace.getTracerProvider();
4629
+ const tracer = tracerProvider.getTracer(deno_default.name, deno_default.version);
4615
4630
  async function load(url, options) {
4616
4631
  options?.signal?.throwIfAborted();
4617
4632
  if (!skipPreloadedContexts && url in contexts_default) {
@@ -4631,14 +4646,38 @@ function getDocumentLoader({ allowPrivateAddress, skipPreloadedContexts, userAge
4631
4646
  });
4632
4647
  throw error;
4633
4648
  }
4634
- const request = createActivityPubRequest(url, { userAgent });
4635
- logRequest(logger, request);
4636
- const response = await fetch(request, {
4637
- redirect: "manual",
4638
- signal: options?.signal
4649
+ return await tracer.startActiveSpan("activitypub.fetch_document", {
4650
+ kind: SpanKind.CLIENT,
4651
+ attributes: { "url.full": url }
4652
+ }, async (span) => {
4653
+ try {
4654
+ const request = createActivityPubRequest(url, { userAgent });
4655
+ logRequest(logger, request);
4656
+ const response = await fetch(request, {
4657
+ redirect: "manual",
4658
+ signal: options?.signal
4659
+ });
4660
+ span.setAttribute("http.response.status_code", response.status);
4661
+ if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
4662
+ const redirectUrl = response.headers.get("Location");
4663
+ span.setAttribute("http.redirect.url", redirectUrl);
4664
+ return await load(redirectUrl, options);
4665
+ }
4666
+ const result = await getRemoteDocument(url, response, load);
4667
+ span.setAttribute("docloader.document_url", result.documentUrl);
4668
+ if (result.contextUrl != null) span.setAttribute("docloader.context_url", result.contextUrl);
4669
+ return result;
4670
+ } catch (error) {
4671
+ span.recordException(error);
4672
+ span.setStatus({
4673
+ code: SpanStatusCode.ERROR,
4674
+ message: String(error)
4675
+ });
4676
+ throw error;
4677
+ } finally {
4678
+ span.end();
4679
+ }
4639
4680
  });
4640
- if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) return load(response.headers.get("Location"), options);
4641
- return getRemoteDocument(url, response, load);
4642
4681
  }
4643
4682
  return load;
4644
4683
  }