@speclynx/apidom-reference 2.12.3 → 2.13.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@speclynx/apidom-reference",
3
- "version": "2.12.3",
3
+ "version": "2.13.0",
4
4
  "description": "Advanced algorithms for semantic ApiDOM manipulations like dereferencing or resolution.",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -231,31 +231,31 @@
231
231
  "license": "Apache-2.0",
232
232
  "dependencies": {
233
233
  "@babel/runtime-corejs3": "^7.28.4",
234
- "@speclynx/apidom-core": "2.12.3",
235
- "@speclynx/apidom-datamodel": "2.12.3",
236
- "@speclynx/apidom-error": "2.12.3",
237
- "@speclynx/apidom-json-pointer": "2.12.3",
238
- "@speclynx/apidom-ns-arazzo-1": "2.12.3",
239
- "@speclynx/apidom-ns-asyncapi-2": "2.12.3",
240
- "@speclynx/apidom-ns-json-schema-2020-12": "2.12.3",
241
- "@speclynx/apidom-ns-openapi-2": "2.12.3",
242
- "@speclynx/apidom-ns-openapi-3-0": "2.12.3",
243
- "@speclynx/apidom-ns-openapi-3-1": "2.12.3",
244
- "@speclynx/apidom-parser-adapter-arazzo-json-1": "2.12.3",
245
- "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "2.12.3",
246
- "@speclynx/apidom-parser-adapter-asyncapi-json-2": "2.12.3",
247
- "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "2.12.3",
248
- "@speclynx/apidom-parser-adapter-json": "2.12.3",
249
- "@speclynx/apidom-parser-adapter-openapi-json-2": "2.12.3",
250
- "@speclynx/apidom-parser-adapter-openapi-json-3-0": "2.12.3",
251
- "@speclynx/apidom-parser-adapter-openapi-json-3-1": "2.12.3",
252
- "@speclynx/apidom-parser-adapter-openapi-yaml-2": "2.12.3",
253
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "2.12.3",
254
- "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "2.12.3",
255
- "@speclynx/apidom-parser-adapter-yaml-1-2": "2.12.3",
256
- "@speclynx/apidom-traverse": "2.12.3",
234
+ "@speclynx/apidom-core": "2.13.0",
235
+ "@speclynx/apidom-datamodel": "2.13.0",
236
+ "@speclynx/apidom-error": "2.13.0",
237
+ "@speclynx/apidom-json-pointer": "2.13.0",
238
+ "@speclynx/apidom-ns-arazzo-1": "2.13.0",
239
+ "@speclynx/apidom-ns-asyncapi-2": "2.13.0",
240
+ "@speclynx/apidom-ns-json-schema-2020-12": "2.13.0",
241
+ "@speclynx/apidom-ns-openapi-2": "2.13.0",
242
+ "@speclynx/apidom-ns-openapi-3-0": "2.13.0",
243
+ "@speclynx/apidom-ns-openapi-3-1": "2.13.0",
244
+ "@speclynx/apidom-parser-adapter-arazzo-json-1": "2.13.0",
245
+ "@speclynx/apidom-parser-adapter-arazzo-yaml-1": "2.13.0",
246
+ "@speclynx/apidom-parser-adapter-asyncapi-json-2": "2.13.0",
247
+ "@speclynx/apidom-parser-adapter-asyncapi-yaml-2": "2.13.0",
248
+ "@speclynx/apidom-parser-adapter-json": "2.13.0",
249
+ "@speclynx/apidom-parser-adapter-openapi-json-2": "2.13.0",
250
+ "@speclynx/apidom-parser-adapter-openapi-json-3-0": "2.13.0",
251
+ "@speclynx/apidom-parser-adapter-openapi-json-3-1": "2.13.0",
252
+ "@speclynx/apidom-parser-adapter-openapi-yaml-2": "2.13.0",
253
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-0": "2.13.0",
254
+ "@speclynx/apidom-parser-adapter-openapi-yaml-3-1": "2.13.0",
255
+ "@speclynx/apidom-parser-adapter-yaml-1-2": "2.13.0",
256
+ "@speclynx/apidom-traverse": "2.13.0",
257
257
  "@swaggerexpert/arazzo-runtime-expression": "^2.0.3",
258
- "axios": "^1.13.0",
258
+ "axios": "^1.13.5",
259
259
  "picomatch": "^4.0.3",
260
260
  "process": "^0.11.10",
261
261
  "ramda": "~0.32.0",
@@ -275,5 +275,5 @@
275
275
  "README.md",
276
276
  "CHANGELOG.md"
277
277
  ],
278
- "gitHead": "d2fa8fd38db1ab53534fef4d812d261cf92945ab"
278
+ "gitHead": "3c92eda7e227426c3a40c918c418c14dc20fca7e"
279
279
  }
@@ -10,6 +10,10 @@ var url = _interopRequireWildcard(require("../../util/url.cjs"));
10
10
  * @public
11
11
  */
12
12
 
13
+ /**
14
+ * @public
15
+ */
16
+
13
17
  /**
14
18
  * @public
15
19
  */
@@ -17,12 +21,14 @@ class HTTPResolver extends _Resolver.default {
17
21
  timeout;
18
22
  redirects;
19
23
  withCredentials;
24
+ cache;
20
25
  constructor(options) {
21
26
  const {
22
27
  name = 'http-resolver',
23
28
  timeout = 5000,
24
29
  redirects = 5,
25
- withCredentials = false
30
+ withCredentials = false,
31
+ cache = false
26
32
  } = options ?? {};
27
33
  super({
28
34
  name
@@ -30,6 +36,7 @@ class HTTPResolver extends _Resolver.default {
30
36
  this.timeout = timeout;
31
37
  this.redirects = redirects;
32
38
  this.withCredentials = withCredentials;
39
+ this.cache = cache;
33
40
  }
34
41
  canRead(file) {
35
42
  return url.isHttpUrl(file.uri);
@@ -6,16 +6,21 @@ import * as url from "../../util/url.mjs";
6
6
  /**
7
7
  * @public
8
8
  */
9
+ /**
10
+ * @public
11
+ */
9
12
  class HTTPResolver extends Resolver {
10
13
  timeout;
11
14
  redirects;
12
15
  withCredentials;
16
+ cache;
13
17
  constructor(options) {
14
18
  const {
15
19
  name = 'http-resolver',
16
20
  timeout = 5000,
17
21
  redirects = 5,
18
- withCredentials = false
22
+ withCredentials = false,
23
+ cache = false
19
24
  } = options ?? {};
20
25
  super({
21
26
  name
@@ -23,6 +28,7 @@ class HTTPResolver extends Resolver {
23
28
  this.timeout = timeout;
24
29
  this.redirects = redirects;
25
30
  this.withCredentials = withCredentials;
31
+ this.cache = cache;
26
32
  }
27
33
  canRead(file) {
28
34
  return url.isHttpUrl(file.uri);
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ /**
6
+ * @public
7
+ */
8
+ class MemoryCache {
9
+ maxEntries;
10
+ maxStaleAge;
11
+ store = new Map();
12
+ constructor(options = {}) {
13
+ const {
14
+ maxEntries = 1024,
15
+ maxStaleAge = 3_600_000
16
+ } = options;
17
+ this.maxEntries = maxEntries;
18
+ this.maxStaleAge = maxStaleAge;
19
+ }
20
+ get(key) {
21
+ const entry = this.store.get(key);
22
+ if (entry === undefined) return undefined;
23
+
24
+ // evict if entry has exceeded maxStaleAge
25
+ if (this.maxStaleAge !== false && Date.now() - entry.createdAt > this.maxStaleAge) {
26
+ this.store.delete(key);
27
+ return undefined;
28
+ }
29
+ return entry.value;
30
+ }
31
+ set(key, value) {
32
+ this.store.set(key, {
33
+ value,
34
+ createdAt: Date.now()
35
+ });
36
+
37
+ // evict oldest entries if maxEntries exceeded
38
+ if (this.maxEntries !== false && this.store.size > this.maxEntries) {
39
+ const firstKey = this.store.keys().next().value;
40
+ this.store.delete(firstKey);
41
+ }
42
+ }
43
+ }
44
+ var _default = exports.default = MemoryCache;
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @public
3
+ */
4
+ class MemoryCache {
5
+ maxEntries;
6
+ maxStaleAge;
7
+ store = new Map();
8
+ constructor(options = {}) {
9
+ const {
10
+ maxEntries = 1024,
11
+ maxStaleAge = 3_600_000
12
+ } = options;
13
+ this.maxEntries = maxEntries;
14
+ this.maxStaleAge = maxStaleAge;
15
+ }
16
+ get(key) {
17
+ const entry = this.store.get(key);
18
+ if (entry === undefined) return undefined;
19
+
20
+ // evict if entry has exceeded maxStaleAge
21
+ if (this.maxStaleAge !== false && Date.now() - entry.createdAt > this.maxStaleAge) {
22
+ this.store.delete(key);
23
+ return undefined;
24
+ }
25
+ return entry.value;
26
+ }
27
+ set(key, value) {
28
+ this.store.set(key, {
29
+ value,
30
+ createdAt: Date.now()
31
+ });
32
+
33
+ // evict oldest entries if maxEntries exceeded
34
+ if (this.maxEntries !== false && this.store.size > this.maxEntries) {
35
+ const firstKey = this.store.keys().next().value;
36
+ this.store.delete(firstKey);
37
+ }
38
+ }
39
+ }
40
+ export default MemoryCache;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireWildcard = require("@babel/runtime-corejs3/helpers/interopRequireWildcard").default;
3
4
  var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault").default;
4
5
  exports.__esModule = true;
5
6
  exports.default = void 0;
@@ -7,7 +8,9 @@ var _ramda = require("ramda");
7
8
  var _ramdaAdjunct = require("ramda-adjunct");
8
9
  var _axios = _interopRequireDefault(require("axios"));
9
10
  var _HTTPResolver = _interopRequireDefault(require("../HTTPResolver.cjs"));
11
+ var _MemoryCache = _interopRequireDefault(require("./cache/MemoryCache.cjs"));
10
12
  var _ResolverError = _interopRequireDefault(require("../../../errors/ResolverError.cjs"));
13
+ var url = _interopRequireWildcard(require("../../../util/url.cjs"));
11
14
  /**
12
15
  * @public
13
16
  */
@@ -23,6 +26,8 @@ class HTTPResolverAxios extends _HTTPResolver.default {
23
26
  axiosConfig = {};
24
27
  axiosInstance;
25
28
  previousAxiosConfig;
29
+ cacheStore;
30
+ previousCache;
26
31
  constructor(options) {
27
32
  const {
28
33
  axiosConfig = {},
@@ -33,6 +38,7 @@ class HTTPResolverAxios extends _HTTPResolver.default {
33
38
  name: 'http-axios'
34
39
  });
35
40
  this.axiosConfig = axiosConfig;
41
+ this.cacheStore = new _MemoryCache.default((0, _ramdaAdjunct.isPlainObject)(this.cache) ? this.cache : {});
36
42
  }
37
43
  getHttpClient() {
38
44
  if (this.axiosInstance === undefined || this.previousAxiosConfig !== this.axiosConfig) {
@@ -65,10 +71,37 @@ class HTTPResolverAxios extends _HTTPResolver.default {
65
71
  }
66
72
  return this.axiosInstance;
67
73
  }
74
+
75
+ /**
76
+ * Ensures cacheStore is config-isolated for cloned resolvers.
77
+ * When a resolver is cloned via Object.create (in readFile), the clone inherits
78
+ * cacheStore from the prototype. Object.create(cacheStore) creates a view that
79
+ * shares the underlying store Map but allows isolated config (maxEntries, maxStaleAge)
80
+ * via own properties set by Object.assign.
81
+ */
82
+ getCacheStore() {
83
+ if (this.previousCache !== this.cache) {
84
+ if (!Object.hasOwn(this, 'cacheStore')) {
85
+ this.cacheStore = Object.create(this.cacheStore);
86
+ }
87
+ if ((0, _ramdaAdjunct.isPlainObject)(this.cache)) {
88
+ Object.assign(this.cacheStore, this.cache);
89
+ }
90
+ this.previousCache = this.cache;
91
+ }
92
+ return this.cacheStore;
93
+ }
68
94
  async read(file) {
95
+ const uri = url.stripHash(file.uri);
96
+ const cacheStore = this.cache ? this.getCacheStore() : undefined;
97
+
98
+ // return cached content if available
99
+ const cached = cacheStore?.get(uri);
100
+ if (cached !== undefined) return cached;
69
101
  const client = this.getHttpClient();
70
102
  try {
71
- const response = await client.get(file.uri);
103
+ const response = await client.get(uri);
104
+ cacheStore?.set(uri, response.data);
72
105
  return response.data;
73
106
  } catch (error) {
74
107
  throw new _ResolverError.default(`Error downloading "${file.uri}"`, {
@@ -1,8 +1,10 @@
1
1
  import { omit } from 'ramda';
2
- import { ensureArray } from 'ramda-adjunct';
2
+ import { ensureArray, isPlainObject } from 'ramda-adjunct';
3
3
  import axios from 'axios';
4
4
  import HTTPResolver from "../HTTPResolver.mjs";
5
+ import MemoryCache from "./cache/MemoryCache.mjs";
5
6
  import ResolverError from "../../../errors/ResolverError.mjs";
7
+ import * as url from "../../../util/url.mjs";
6
8
  /**
7
9
  * @public
8
10
  */
@@ -16,6 +18,8 @@ class HTTPResolverAxios extends HTTPResolver {
16
18
  axiosConfig = {};
17
19
  axiosInstance;
18
20
  previousAxiosConfig;
21
+ cacheStore;
22
+ previousCache;
19
23
  constructor(options) {
20
24
  const {
21
25
  axiosConfig = {},
@@ -26,6 +30,7 @@ class HTTPResolverAxios extends HTTPResolver {
26
30
  name: 'http-axios'
27
31
  });
28
32
  this.axiosConfig = axiosConfig;
33
+ this.cacheStore = new MemoryCache(isPlainObject(this.cache) ? this.cache : {});
29
34
  }
30
35
  getHttpClient() {
31
36
  if (this.axiosInstance === undefined || this.previousAxiosConfig !== this.axiosConfig) {
@@ -58,10 +63,37 @@ class HTTPResolverAxios extends HTTPResolver {
58
63
  }
59
64
  return this.axiosInstance;
60
65
  }
66
+
67
+ /**
68
+ * Ensures cacheStore is config-isolated for cloned resolvers.
69
+ * When a resolver is cloned via Object.create (in readFile), the clone inherits
70
+ * cacheStore from the prototype. Object.create(cacheStore) creates a view that
71
+ * shares the underlying store Map but allows isolated config (maxEntries, maxStaleAge)
72
+ * via own properties set by Object.assign.
73
+ */
74
+ getCacheStore() {
75
+ if (this.previousCache !== this.cache) {
76
+ if (!Object.hasOwn(this, 'cacheStore')) {
77
+ this.cacheStore = Object.create(this.cacheStore);
78
+ }
79
+ if (isPlainObject(this.cache)) {
80
+ Object.assign(this.cacheStore, this.cache);
81
+ }
82
+ this.previousCache = this.cache;
83
+ }
84
+ return this.cacheStore;
85
+ }
61
86
  async read(file) {
87
+ const uri = url.stripHash(file.uri);
88
+ const cacheStore = this.cache ? this.getCacheStore() : undefined;
89
+
90
+ // return cached content if available
91
+ const cached = cacheStore?.get(uri);
92
+ if (cached !== undefined) return cached;
62
93
  const client = this.getHttpClient();
63
94
  try {
64
- const response = await client.get(file.uri);
95
+ const response = await client.get(uri);
96
+ cacheStore?.set(uri, response.data);
65
97
  return response.data;
66
98
  } catch (error) {
67
99
  throw new ResolverError(`Error downloading "${file.uri}"`, {
@@ -86,6 +86,14 @@ export declare interface BundleStrategyOptions {
86
86
  readonly name: string;
87
87
  }
88
88
 
89
+ /**
90
+ * @public
91
+ */
92
+ declare interface CacheOptions {
93
+ readonly maxEntries?: number | false;
94
+ readonly maxStaleAge?: number | false;
95
+ }
96
+
89
97
  /**
90
98
  * Returns the current working directory (in Node) or the current page URL (in browsers).
91
99
  * @public
@@ -227,6 +235,7 @@ export declare abstract class HTTPResolver extends Resolver {
227
235
  protected readonly timeout: number;
228
236
  protected readonly redirects: number;
229
237
  protected readonly withCredentials: boolean;
238
+ protected readonly cache: boolean | CacheOptions;
230
239
  constructor(options?: HTTPResolverOptions);
231
240
  canRead(file: File_2): boolean;
232
241
  abstract getHttpClient(): unknown;
@@ -239,6 +248,7 @@ export declare interface HTTPResolverOptions extends ResolverOptions {
239
248
  readonly timeout?: number;
240
249
  readonly redirects?: number;
241
250
  readonly withCredentials?: boolean;
251
+ readonly cache?: boolean | CacheOptions;
242
252
  }
243
253
 
244
254
  /**
@@ -1,5 +1,12 @@
1
1
  import Resolver, { ResolverOptions } from './Resolver.ts';
2
2
  import File from '../../File.ts';
3
+ /**
4
+ * @public
5
+ */
6
+ export interface CacheOptions {
7
+ readonly maxEntries?: number | false;
8
+ readonly maxStaleAge?: number | false;
9
+ }
3
10
  /**
4
11
  * @public
5
12
  */
@@ -7,6 +14,7 @@ export interface HTTPResolverOptions extends ResolverOptions {
7
14
  readonly timeout?: number;
8
15
  readonly redirects?: number;
9
16
  readonly withCredentials?: boolean;
17
+ readonly cache?: boolean | CacheOptions;
10
18
  }
11
19
  /**
12
20
  * @public
@@ -15,6 +23,7 @@ declare abstract class HTTPResolver extends Resolver {
15
23
  protected readonly timeout: number;
16
24
  protected readonly redirects: number;
17
25
  protected readonly withCredentials: boolean;
26
+ protected readonly cache: boolean | CacheOptions;
18
27
  constructor(options?: HTTPResolverOptions);
19
28
  canRead(file: File): boolean;
20
29
  abstract getHttpClient(): unknown;
@@ -0,0 +1,17 @@
1
+ import type { CacheOptions } from '../../HTTPResolver.ts';
2
+ interface CacheEntry<T> {
3
+ value: T;
4
+ createdAt: number;
5
+ }
6
+ /**
7
+ * @public
8
+ */
9
+ declare class MemoryCache<T> {
10
+ protected maxEntries: number | false;
11
+ protected maxStaleAge: number | false;
12
+ protected readonly store: Map<string, CacheEntry<T>>;
13
+ constructor(options?: CacheOptions);
14
+ get(key: string): T | undefined;
15
+ set(key: string, value: T): void;
16
+ }
17
+ export default MemoryCache;
@@ -1,7 +1,8 @@
1
1
  import { Axios, AxiosInstance, CreateAxiosDefaults } from 'axios';
2
2
  import HTTPResolver, { HTTPResolverOptions } from '../HTTPResolver.ts';
3
+ import MemoryCache from './cache/MemoryCache.ts';
3
4
  import File from '../../../File.ts';
4
- export type { default as HTTPResolver, HTTPResolverOptions } from '../HTTPResolver.ts';
5
+ export type { default as HTTPResolver, HTTPResolverOptions, CacheOptions, } from '../HTTPResolver.ts';
5
6
  export type { default as Resolver, ResolverOptions } from '../Resolver.ts';
6
7
  export type { default as File, FileOptions } from '../../../File.ts';
7
8
  /**
@@ -23,8 +24,18 @@ declare class HTTPResolverAxios extends HTTPResolver {
23
24
  axiosConfig: HTTPResolverAxiosConfig;
24
25
  protected axiosInstance: AxiosInstance;
25
26
  protected previousAxiosConfig: HTTPResolverAxiosConfig;
27
+ protected cacheStore: MemoryCache<Buffer>;
28
+ protected previousCache: typeof this.cache;
26
29
  constructor(options?: HTTPResolverAxiosOptions);
27
30
  getHttpClient(): AxiosInstance;
31
+ /**
32
+ * Ensures cacheStore is config-isolated for cloned resolvers.
33
+ * When a resolver is cloned via Object.create (in readFile), the clone inherits
34
+ * cacheStore from the prototype. Object.create(cacheStore) creates a view that
35
+ * shares the underlying store Map but allows isolated config (maxEntries, maxStaleAge)
36
+ * via own properties set by Object.assign.
37
+ */
38
+ protected getCacheStore(): MemoryCache<Buffer>;
28
39
  read(file: File): Promise<Buffer>;
29
40
  }
30
41
  export default HTTPResolverAxios;