@apidevtools/json-schema-ref-parser 14.1.0 → 14.2.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.
@@ -104,8 +104,12 @@ function crawl(parent, key, path, pathFromRoot, indirections, inventory, $refs,
104
104
  else {
105
105
  crawl(obj, key, keyPath, keyPathFromRoot, indirections, inventory, $refs, options);
106
106
  }
107
- if (value["$ref"]) {
108
- bundleOptions?.onBundle?.(value["$ref"], obj[key], obj, key);
107
+ // We need to ensure that we have an object to work with here because we may be crawling
108
+ // an `examples` schema and `value` may be nullish.
109
+ if (value && typeof value === "object" && !Array.isArray(value)) {
110
+ if ("$ref" in value) {
111
+ bundleOptions?.onBundle?.(value["$ref"], obj[key], obj, key);
112
+ }
109
113
  }
110
114
  }
111
115
  }
@@ -61,7 +61,7 @@ export declare function isHttp(path: string): boolean;
61
61
  * @param path - The URL or path to check
62
62
  * @returns true if the URL is unsafe/internal, false otherwise
63
63
  */
64
- export declare function isUnsafeUrl(path: string): boolean;
64
+ export declare function isUnsafeUrl(path: string | unknown): boolean;
65
65
  /**
66
66
  * Determines whether the given path is a filesystem path.
67
67
  * This includes "file://" URLs.
@@ -140,7 +140,7 @@ function getProtocol(path) {
140
140
  function getExtension(path) {
141
141
  const lastDot = path.lastIndexOf(".");
142
142
  if (lastDot >= 0) {
143
- return stripQuery(path.substr(lastDot).toLowerCase());
143
+ return stripQuery(path.substring(lastDot).toLowerCase());
144
144
  }
145
145
  return "";
146
146
  }
@@ -153,7 +153,7 @@ function getExtension(path) {
153
153
  function stripQuery(path) {
154
154
  const queryIndex = path.indexOf("?");
155
155
  if (queryIndex >= 0) {
156
- path = path.substr(0, queryIndex);
156
+ path = path.substring(0, queryIndex);
157
157
  }
158
158
  return path;
159
159
  }
@@ -295,7 +295,7 @@ function isUnsafeUrl(path) {
295
295
  return true;
296
296
  }
297
297
  }
298
- catch (e) {
298
+ catch {
299
299
  // If URL parsing fails, check if it's a relative path or contains suspicious patterns
300
300
  // Relative paths starting with / are generally safe for same-origin
301
301
  if (normalizedPath.startsWith("/") && !normalizedPath.startsWith("//")) {
@@ -432,13 +432,13 @@ function toFileSystemPath(path, keepFileProtocol) {
432
432
  }
433
433
  // Step 3: If it's a "file://" URL, then format it consistently
434
434
  // or convert it to a local filesystem path
435
- let isFileUrl = path.substr(0, 7).toLowerCase() === "file://";
435
+ let isFileUrl = path.toLowerCase().startsWith("file://");
436
436
  if (isFileUrl) {
437
437
  // Strip-off the protocol, and the initial "/", if there is one
438
- path = path[7] === "/" ? path.substr(8) : path.substr(7);
438
+ path = path.replace(/^file:\/\//, "").replace(/^\//, "");
439
439
  // insert a colon (":") after the drive letter on Windows
440
440
  if ((0, is_windows_1.isWindows)() && path[1] === "/") {
441
- path = path[0] + ":" + path.substr(1);
441
+ path = `${path[0]}:${path.substring(1)}`;
442
442
  }
443
443
  if (keepFileProtocol) {
444
444
  // Return the consistently-formatted "file://" URL
@@ -457,8 +457,8 @@ function toFileSystemPath(path, keepFileProtocol) {
457
457
  // Replace forward slashes with backslashes
458
458
  path = path.replace(forwardSlashPattern, "\\");
459
459
  // Capitalize the drive letter
460
- if (path.substr(1, 2) === ":\\") {
461
- path = path[0].toUpperCase() + path.substr(1);
460
+ if (path.match(/^[a-z]:\\/i)) {
461
+ path = path[0].toUpperCase() + path.substring(1);
462
462
  }
463
463
  }
464
464
  return path;
package/lib/bundle.ts CHANGED
@@ -101,8 +101,12 @@ function crawl<S extends object = JSONSchema, O extends ParserOptions<S> = Parse
101
101
  crawl(obj, key, keyPath, keyPathFromRoot, indirections, inventory, $refs, options);
102
102
  }
103
103
 
104
- if (value["$ref"]) {
105
- bundleOptions?.onBundle?.(value["$ref"], obj[key], obj as any, key);
104
+ // We need to ensure that we have an object to work with here because we may be crawling
105
+ // an `examples` schema and `value` may be nullish.
106
+ if (value && typeof value === "object" && !Array.isArray(value)) {
107
+ if ("$ref" in value) {
108
+ bundleOptions?.onBundle?.(value["$ref"], obj[key], obj as any, key);
109
+ }
106
110
  }
107
111
  }
108
112
  }
package/lib/util/url.ts CHANGED
@@ -95,7 +95,7 @@ export function getProtocol(path: string | undefined) {
95
95
  export function getExtension(path: any) {
96
96
  const lastDot = path.lastIndexOf(".");
97
97
  if (lastDot >= 0) {
98
- return stripQuery(path.substr(lastDot).toLowerCase());
98
+ return stripQuery(path.substring(lastDot).toLowerCase());
99
99
  }
100
100
  return "";
101
101
  }
@@ -109,7 +109,7 @@ export function getExtension(path: any) {
109
109
  export function stripQuery(path: any) {
110
110
  const queryIndex = path.indexOf("?");
111
111
  if (queryIndex >= 0) {
112
- path = path.substr(0, queryIndex);
112
+ path = path.substring(0, queryIndex);
113
113
  }
114
114
  return path;
115
115
  }
@@ -173,7 +173,7 @@ export function isHttp(path: string) {
173
173
  * @param path - The URL or path to check
174
174
  * @returns true if the URL is unsafe/internal, false otherwise
175
175
  */
176
- export function isUnsafeUrl(path: string): boolean {
176
+ export function isUnsafeUrl(path: string | unknown): boolean {
177
177
  if (!path || typeof path !== "string") {
178
178
  return true;
179
179
  }
@@ -267,7 +267,7 @@ export function isUnsafeUrl(path: string): boolean {
267
267
  if (port && isInternalPort(parseInt(port))) {
268
268
  return true;
269
269
  }
270
- } catch (e) {
270
+ } catch {
271
271
  // If URL parsing fails, check if it's a relative path or contains suspicious patterns
272
272
 
273
273
  // Relative paths starting with / are generally safe for same-origin
@@ -425,14 +425,14 @@ export function toFileSystemPath(path: string | undefined, keepFileProtocol?: bo
425
425
 
426
426
  // Step 3: If it's a "file://" URL, then format it consistently
427
427
  // or convert it to a local filesystem path
428
- let isFileUrl = path.substr(0, 7).toLowerCase() === "file://";
428
+ let isFileUrl = path.toLowerCase().startsWith("file://");
429
429
  if (isFileUrl) {
430
430
  // Strip-off the protocol, and the initial "/", if there is one
431
- path = path[7] === "/" ? path.substr(8) : path.substr(7);
431
+ path = path.replace(/^file:\/\//, "").replace(/^\//, "");
432
432
 
433
433
  // insert a colon (":") after the drive letter on Windows
434
434
  if (isWindows() && path[1] === "/") {
435
- path = path[0] + ":" + path.substr(1);
435
+ path = `${path[0]}:${path.substring(1)}`;
436
436
  }
437
437
 
438
438
  if (keepFileProtocol) {
@@ -453,8 +453,8 @@ export function toFileSystemPath(path: string | undefined, keepFileProtocol?: bo
453
453
  path = path.replace(forwardSlashPattern, "\\");
454
454
 
455
455
  // Capitalize the drive letter
456
- if (path.substr(1, 2) === ":\\") {
457
- path = path[0].toUpperCase() + path.substr(1);
456
+ if (path.match(/^[a-z]:\\/i)) {
457
+ path = path[0].toUpperCase() + path.substring(1);
458
458
  }
459
459
  }
460
460
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apidevtools/json-schema-ref-parser",
3
- "version": "14.1.0",
3
+ "version": "14.2.0",
4
4
  "description": "Parse, Resolve, and Dereference JSON Schema $ref pointers",
5
5
  "scripts": {
6
6
  "prepublishOnly": "yarn build",
@@ -25,8 +25,9 @@
25
25
  "resolve"
26
26
  ],
27
27
  "author": {
28
- "name": "James Messinger",
29
- "url": "https://jamesmessinger.com"
28
+ "name": "JonLuca DeCaro",
29
+ "url": "https://jonlu.ca",
30
+ "email": "apis@jonlu.ca"
30
31
  },
31
32
  "contributors": [
32
33
  {
@@ -42,8 +43,8 @@
42
43
  "email": "jakub@stoplight.io"
43
44
  },
44
45
  {
45
- "name": "JonLuca DeCaro",
46
- "email": "apis@jonlu.ca"
46
+ "name": "James Messinger",
47
+ "url": "https://jamesmessinger.com"
47
48
  }
48
49
  ],
49
50
  "homepage": "https://apidevtools.com/json-schema-ref-parser/",
@@ -65,35 +66,37 @@
65
66
  "lib",
66
67
  "dist"
67
68
  ],
69
+ "peerDependencies": {
70
+ "@types/json-schema": "^7.0.15"
71
+ },
72
+ "dependencies": {
73
+ "js-yaml": "^4.1.0"
74
+ },
68
75
  "devDependencies": {
69
- "@eslint/compat": "^1.3.1",
70
- "@eslint/js": "^9.30.0",
76
+ "@eslint/compat": "^1.3.2",
77
+ "@eslint/js": "^9.33.0",
71
78
  "@types/eslint": "^9.6.1",
72
79
  "@types/js-yaml": "^4.0.9",
80
+ "@types/json-schema": "^7.0.15",
73
81
  "@types/node": "^24",
74
- "@typescript-eslint/eslint-plugin": "^8.35.1",
75
- "@typescript-eslint/parser": "^8.35.1",
82
+ "@typescript-eslint/eslint-plugin": "^8.39.1",
83
+ "@typescript-eslint/parser": "^8.39.1",
76
84
  "@vitest/coverage-v8": "^3.2.4",
77
- "cross-env": "^7.0.3",
78
- "eslint": "^9.30.0",
79
- "eslint-config-prettier": "^10.1.5",
80
- "eslint-config-standard": "^17.1.0",
85
+ "cross-env": "^10.0.0",
86
+ "eslint": "^9.33.0",
87
+ "eslint-config-prettier": "^10.1.8",
81
88
  "eslint-plugin-import": "^2.32.0",
82
- "eslint-plugin-prettier": "^5.5.1",
89
+ "eslint-plugin-prettier": "^5.5.4",
83
90
  "eslint-plugin-promise": "^7.2.1",
84
- "eslint-plugin-unused-imports": "^4.1.4",
85
- "globals": "^16.2.0",
91
+ "eslint-plugin-unused-imports": "^4.2.0",
92
+ "globals": "^16.3.0",
86
93
  "jsdom": "^26.1.0",
87
94
  "prettier": "^3.6.2",
88
95
  "rimraf": "^6.0.1",
89
- "typescript": "^5.8.3",
90
- "typescript-eslint": "^8.35.1",
96
+ "typescript": "^5.9.2",
97
+ "typescript-eslint": "^8.39.1",
91
98
  "vitest": "^3.2.4"
92
99
  },
93
- "dependencies": {
94
- "@types/json-schema": "^7.0.15",
95
- "js-yaml": "^4.1.0"
96
- },
97
100
  "release": {
98
101
  "branches": [
99
102
  "main"
@@ -105,5 +108,5 @@
105
108
  "@semantic-release/github"
106
109
  ]
107
110
  },
108
- "packageManager": "yarn@4.9.1"
111
+ "packageManager": "yarn@4.9.2"
109
112
  }