@speclynx/apidom-reference 4.0.3 → 4.0.5

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 (95) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/apidom-reference.browser.js +43 -19
  3. package/dist/apidom-reference.browser.min.js +1 -1
  4. package/package.json +27 -26
  5. package/src/File.ts +0 -63
  6. package/src/Reference.ts +0 -38
  7. package/src/ReferenceSet.ts +0 -73
  8. package/src/bundle/index.ts +0 -57
  9. package/src/bundle/strategies/BundleStrategy.ts +0 -27
  10. package/src/bundle/strategies/openapi-3-1/index.ts +0 -57
  11. package/src/configuration/empty.ts +0 -1
  12. package/src/configuration/saturated.ts +0 -72
  13. package/src/dereference/index.ts +0 -96
  14. package/src/dereference/strategies/DereferenceStrategy.ts +0 -27
  15. package/src/dereference/strategies/apidom/index.ts +0 -128
  16. package/src/dereference/strategies/apidom/selectors/element-id.ts +0 -48
  17. package/src/dereference/strategies/apidom/visitor.ts +0 -316
  18. package/src/dereference/strategies/arazzo-1/index.ts +0 -158
  19. package/src/dereference/strategies/arazzo-1/selectors/$anchor.ts +0 -9
  20. package/src/dereference/strategies/arazzo-1/selectors/uri.ts +0 -5
  21. package/src/dereference/strategies/arazzo-1/source-descriptions.ts +0 -317
  22. package/src/dereference/strategies/arazzo-1/util.ts +0 -33
  23. package/src/dereference/strategies/arazzo-1/visitor.ts +0 -574
  24. package/src/dereference/strategies/asyncapi-2/index.ts +0 -133
  25. package/src/dereference/strategies/asyncapi-2/visitor.ts +0 -589
  26. package/src/dereference/strategies/openapi-2/index.ts +0 -136
  27. package/src/dereference/strategies/openapi-2/visitor.ts +0 -745
  28. package/src/dereference/strategies/openapi-3-0/index.ts +0 -134
  29. package/src/dereference/strategies/openapi-3-0/visitor.ts +0 -760
  30. package/src/dereference/strategies/openapi-3-1/index.ts +0 -141
  31. package/src/dereference/strategies/openapi-3-1/selectors/$anchor.ts +0 -64
  32. package/src/dereference/strategies/openapi-3-1/selectors/uri.ts +0 -54
  33. package/src/dereference/strategies/openapi-3-1/util.ts +0 -83
  34. package/src/dereference/strategies/openapi-3-1/visitor.ts +0 -1053
  35. package/src/dereference/util.ts +0 -29
  36. package/src/errors/BundleError.ts +0 -8
  37. package/src/errors/DereferenceError.ts +0 -8
  38. package/src/errors/EvaluationElementIdError.ts +0 -8
  39. package/src/errors/EvaluationJsonSchema$anchorError.ts +0 -8
  40. package/src/errors/EvaluationJsonSchemaUriError.ts +0 -8
  41. package/src/errors/InvalidJsonSchema$anchorError.ts +0 -12
  42. package/src/errors/JsonSchema$anchorError.ts +0 -8
  43. package/src/errors/JsonSchemaUriError.ts +0 -8
  44. package/src/errors/MaximumBundleDepthError.ts +0 -8
  45. package/src/errors/MaximumDereferenceDepthError.ts +0 -8
  46. package/src/errors/MaximumResolveDepthError.ts +0 -8
  47. package/src/errors/ParseError.ts +0 -8
  48. package/src/errors/ParserError.ts +0 -8
  49. package/src/errors/PluginError.ts +0 -15
  50. package/src/errors/ResolveError.ts +0 -8
  51. package/src/errors/ResolverError.ts +0 -8
  52. package/src/errors/UnmatchedBundleStrategyError.ts +0 -8
  53. package/src/errors/UnmatchedDereferenceStrategyError.ts +0 -8
  54. package/src/errors/UnmatchedParserError.ts +0 -8
  55. package/src/errors/UnmatchedResolveStrategyError.ts +0 -8
  56. package/src/errors/UnmatchedResolverError.ts +0 -8
  57. package/src/errors/UnresolvableReferenceError.ts +0 -8
  58. package/src/index.ts +0 -135
  59. package/src/options/index.ts +0 -239
  60. package/src/options/util.ts +0 -22
  61. package/src/parse/index.ts +0 -67
  62. package/src/parse/parsers/Parser.ts +0 -80
  63. package/src/parse/parsers/apidom-json/index.ts +0 -78
  64. package/src/parse/parsers/arazzo-json-1/index.ts +0 -76
  65. package/src/parse/parsers/arazzo-json-1/source-descriptions.ts +0 -280
  66. package/src/parse/parsers/arazzo-yaml-1/index.ts +0 -77
  67. package/src/parse/parsers/arazzo-yaml-1/source-descriptions.ts +0 -16
  68. package/src/parse/parsers/asyncapi-json-2/index.ts +0 -58
  69. package/src/parse/parsers/asyncapi-yaml-2/index.ts +0 -58
  70. package/src/parse/parsers/binary/index-browser.ts +0 -60
  71. package/src/parse/parsers/binary/index-node.ts +0 -57
  72. package/src/parse/parsers/json/index.ts +0 -52
  73. package/src/parse/parsers/openapi-json-2/index.ts +0 -58
  74. package/src/parse/parsers/openapi-json-3-0/index.ts +0 -59
  75. package/src/parse/parsers/openapi-json-3-1/index.ts +0 -59
  76. package/src/parse/parsers/openapi-yaml-2/index.ts +0 -58
  77. package/src/parse/parsers/openapi-yaml-3-0/index.ts +0 -59
  78. package/src/parse/parsers/openapi-yaml-3-1/index.ts +0 -59
  79. package/src/parse/parsers/yaml-1-2/index.ts +0 -60
  80. package/src/resolve/index.ts +0 -75
  81. package/src/resolve/resolvers/HTTPResolver.ts +0 -58
  82. package/src/resolve/resolvers/Resolver.ts +0 -25
  83. package/src/resolve/resolvers/file/index-browser.ts +0 -24
  84. package/src/resolve/resolvers/file/index-node.ts +0 -55
  85. package/src/resolve/resolvers/http-axios/cache/MemoryCache.ts +0 -46
  86. package/src/resolve/resolvers/http-axios/index.ts +0 -130
  87. package/src/resolve/strategies/ResolveStrategy.ts +0 -26
  88. package/src/resolve/strategies/apidom/index.ts +0 -78
  89. package/src/resolve/strategies/asyncapi-2/index.ts +0 -78
  90. package/src/resolve/strategies/openapi-2/index.ts +0 -78
  91. package/src/resolve/strategies/openapi-3-0/index.ts +0 -78
  92. package/src/resolve/strategies/openapi-3-1/index.ts +0 -78
  93. package/src/resolve/util.ts +0 -39
  94. package/src/util/plugins.ts +0 -37
  95. package/src/util/url.ts +0 -285
@@ -1,78 +0,0 @@
1
- import ResolveStrategy, { ResolveStrategyOptions } from '../ResolveStrategy.ts';
2
- import ReferenceSet from '../../../ReferenceSet.ts';
3
- import File from '../../../File.ts';
4
- import { merge as mergeOptions } from '../../../options/util.ts';
5
- import UnmatchedDereferenceStrategyError from '../../../errors/UnmatchedDereferenceStrategyError.ts';
6
- import type { ReferenceOptions } from '../../../options/index.ts';
7
-
8
- export type { default as ResolveStrategy, ResolveStrategyOptions } from '../ResolveStrategy.ts';
9
- export type { default as ReferenceSet, ReferenceSetOptions } from '../../../ReferenceSet.ts';
10
- export type { default as File, FileOptions } from '../../../File.ts';
11
- export type {
12
- ReferenceOptions as ApiDOMReferenceOptions,
13
- ReferenceBundleOptions as ApiDOMReferenceBundleOptions,
14
- ReferenceDereferenceOptions as ApiDOMReferenceDereferenceOptions,
15
- ReferenceParseOptions as ApiDOMReferenceParseOptions,
16
- ReferenceResolveOptions as ApiDOMReferenceResolveOptions,
17
- } from '../../../options/index.ts';
18
- export type { default as Parser, ParserOptions } from '../../../parse/parsers/Parser.ts';
19
- export type { default as Resolver, ResolverOptions } from '../../resolvers/Resolver.ts';
20
- export type {
21
- default as DereferenceStrategy,
22
- DereferenceStrategyOptions,
23
- } from '../../../dereference/strategies/DereferenceStrategy.ts';
24
- export type {
25
- default as BundleStrategy,
26
- BundleStrategyOptions,
27
- } from '../../../bundle/strategies/BundleStrategy.ts';
28
- export type { default as Reference, ReferenceOptions } from '../../../Reference.ts';
29
-
30
- /**
31
- * @public
32
- */
33
- export interface OpenAPI2ResolveStrategyOptions extends Omit<ResolveStrategyOptions, 'name'> {}
34
-
35
- /**
36
- * @public
37
- */
38
- class OpenAPI2ResolveStrategy extends ResolveStrategy {
39
- constructor(options?: OpenAPI2ResolveStrategyOptions) {
40
- super({ ...(options ?? {}), name: 'openapi-2' });
41
- }
42
-
43
- canResolve(file: File, options: ReferenceOptions) {
44
- const dereferenceStrategy = options.dereference.strategies.find(
45
- (strategy) => strategy.name === 'openapi-2',
46
- );
47
-
48
- if (dereferenceStrategy === undefined) {
49
- return false;
50
- }
51
-
52
- return dereferenceStrategy.canDereference(file, options);
53
- }
54
-
55
- async resolve(file: File, options: ReferenceOptions) {
56
- const dereferenceStrategy = options.dereference.strategies.find(
57
- (strategy) => strategy.name === 'openapi-2',
58
- );
59
-
60
- if (dereferenceStrategy === undefined) {
61
- throw new UnmatchedDereferenceStrategyError(
62
- `"openapi-2" resolve strategy requires "openapi-2" dereference strategy to be configured for file "${file.uri}"`,
63
- );
64
- }
65
-
66
- const refSet = new ReferenceSet();
67
- const mergedOptions = mergeOptions(options, {
68
- resolve: { internal: false },
69
- dereference: { refSet },
70
- });
71
-
72
- await dereferenceStrategy.dereference(file, mergedOptions);
73
-
74
- return refSet;
75
- }
76
- }
77
-
78
- export default OpenAPI2ResolveStrategy;
@@ -1,78 +0,0 @@
1
- import ResolveStrategy, { ResolveStrategyOptions } from '../ResolveStrategy.ts';
2
- import ReferenceSet from '../../../ReferenceSet.ts';
3
- import File from '../../../File.ts';
4
- import { merge as mergeOptions } from '../../../options/util.ts';
5
- import UnmatchedDereferenceStrategyError from '../../../errors/UnmatchedDereferenceStrategyError.ts';
6
- import type { ReferenceOptions } from '../../../options/index.ts';
7
-
8
- export type { default as ResolveStrategy, ResolveStrategyOptions } from '../ResolveStrategy.ts';
9
- export type { default as ReferenceSet, ReferenceSetOptions } from '../../../ReferenceSet.ts';
10
- export type { default as File, FileOptions } from '../../../File.ts';
11
- export type {
12
- ReferenceOptions as ApiDOMReferenceOptions,
13
- ReferenceBundleOptions as ApiDOMReferenceBundleOptions,
14
- ReferenceDereferenceOptions as ApiDOMReferenceDereferenceOptions,
15
- ReferenceParseOptions as ApiDOMReferenceParseOptions,
16
- ReferenceResolveOptions as ApiDOMReferenceResolveOptions,
17
- } from '../../../options/index.ts';
18
- export type { default as Parser, ParserOptions } from '../../../parse/parsers/Parser.ts';
19
- export type { default as Resolver, ResolverOptions } from '../../resolvers/Resolver.ts';
20
- export type {
21
- default as DereferenceStrategy,
22
- DereferenceStrategyOptions,
23
- } from '../../../dereference/strategies/DereferenceStrategy.ts';
24
- export type {
25
- default as BundleStrategy,
26
- BundleStrategyOptions,
27
- } from '../../../bundle/strategies/BundleStrategy.ts';
28
- export type { default as Reference, ReferenceOptions } from '../../../Reference.ts';
29
-
30
- /**
31
- * @public
32
- */
33
- export interface OpenAPI3_0ResolveStrategyOptions extends Omit<ResolveStrategyOptions, 'name'> {}
34
-
35
- /**
36
- * @public
37
- */
38
- class OpenAPI3_0ResolveStrategy extends ResolveStrategy {
39
- constructor(options?: OpenAPI3_0ResolveStrategyOptions) {
40
- super({ ...(options ?? {}), name: 'openapi-3-0' });
41
- }
42
-
43
- canResolve(file: File, options: ReferenceOptions): boolean {
44
- const dereferenceStrategy = options.dereference.strategies.find(
45
- (strategy) => strategy.name === 'openapi-3-0',
46
- );
47
-
48
- if (dereferenceStrategy === undefined) {
49
- return false;
50
- }
51
-
52
- return dereferenceStrategy.canDereference(file, options);
53
- }
54
-
55
- async resolve(file: File, options: ReferenceOptions) {
56
- const dereferenceStrategy = options.dereference.strategies.find(
57
- (strategy) => strategy.name === 'openapi-3-0',
58
- );
59
-
60
- if (dereferenceStrategy === undefined) {
61
- throw new UnmatchedDereferenceStrategyError(
62
- `"openapi-3-0" resolve strategy requires "openapi-3-0" dereference strategy to be configured for file "${file.uri}"`,
63
- );
64
- }
65
-
66
- const refSet = new ReferenceSet();
67
- const mergedOptions = mergeOptions(options, {
68
- resolve: { internal: false },
69
- dereference: { refSet },
70
- });
71
-
72
- await dereferenceStrategy.dereference(file, mergedOptions);
73
-
74
- return refSet;
75
- }
76
- }
77
-
78
- export default OpenAPI3_0ResolveStrategy;
@@ -1,78 +0,0 @@
1
- import ResolveStrategy, { ResolveStrategyOptions } from '../ResolveStrategy.ts';
2
- import ReferenceSet from '../../../ReferenceSet.ts';
3
- import File from '../../../File.ts';
4
- import { merge as mergeOptions } from '../../../options/util.ts';
5
- import UnmatchedDereferenceStrategyError from '../../../errors/UnmatchedDereferenceStrategyError.ts';
6
- import type { ReferenceOptions } from '../../../options/index.ts';
7
-
8
- export type { default as ResolveStrategy, ResolveStrategyOptions } from '../ResolveStrategy.ts';
9
- export type { default as ReferenceSet, ReferenceSetOptions } from '../../../ReferenceSet.ts';
10
- export type { default as File, FileOptions } from '../../../File.ts';
11
- export type {
12
- ReferenceOptions as ApiDOMReferenceOptions,
13
- ReferenceBundleOptions as ApiDOMReferenceBundleOptions,
14
- ReferenceDereferenceOptions as ApiDOMReferenceDereferenceOptions,
15
- ReferenceParseOptions as ApiDOMReferenceParseOptions,
16
- ReferenceResolveOptions as ApiDOMReferenceResolveOptions,
17
- } from '../../../options/index.ts';
18
- export type { default as Parser, ParserOptions } from '../../../parse/parsers/Parser.ts';
19
- export type { default as Resolver, ResolverOptions } from '../../resolvers/Resolver.ts';
20
- export type {
21
- default as DereferenceStrategy,
22
- DereferenceStrategyOptions,
23
- } from '../../../dereference/strategies/DereferenceStrategy.ts';
24
- export type {
25
- default as BundleStrategy,
26
- BundleStrategyOptions,
27
- } from '../../../bundle/strategies/BundleStrategy.ts';
28
- export type { default as Reference, ReferenceOptions } from '../../../Reference.ts';
29
-
30
- /**
31
- * @public
32
- */
33
- export interface OpenAPI3_1ResolveStrategyOptions extends Omit<ResolveStrategyOptions, 'name'> {}
34
-
35
- /**
36
- * @public
37
- */
38
- class OpenAPI3_1ResolveStrategy extends ResolveStrategy {
39
- constructor(options?: OpenAPI3_1ResolveStrategyOptions) {
40
- super({ ...(options ?? {}), name: 'openapi-3-1' });
41
- }
42
-
43
- canResolve(file: File, options: ReferenceOptions): boolean {
44
- const dereferenceStrategy = options.dereference.strategies.find(
45
- (strategy) => strategy.name === 'openapi-3-1',
46
- );
47
-
48
- if (dereferenceStrategy === undefined) {
49
- return false;
50
- }
51
-
52
- return dereferenceStrategy.canDereference(file, options);
53
- }
54
-
55
- async resolve(file: File, options: ReferenceOptions) {
56
- const dereferenceStrategy = options.dereference.strategies.find(
57
- (strategy) => strategy.name === 'openapi-3-1',
58
- );
59
-
60
- if (dereferenceStrategy === undefined) {
61
- throw new UnmatchedDereferenceStrategyError(
62
- `"openapi-3-1" resolve strategy requires "openapi-3-1" dereference strategy to be configured for file "${file.uri}"`,
63
- );
64
- }
65
-
66
- const refSet = new ReferenceSet();
67
- const mergedOptions = mergeOptions(options, {
68
- resolve: { internal: false },
69
- dereference: { refSet },
70
- });
71
-
72
- await dereferenceStrategy.dereference(file, mergedOptions);
73
-
74
- return refSet;
75
- }
76
- }
77
-
78
- export default OpenAPI3_1ResolveStrategy;
@@ -1,39 +0,0 @@
1
- import { isEmpty } from 'ramda';
2
-
3
- import File from '../File.ts';
4
- import Resolver from './resolvers/Resolver.ts';
5
- import * as plugins from '../util/plugins.ts';
6
- import ResolveError from '../errors/ResolveError.ts';
7
- import UnmatchedResolverError from '../errors/UnmatchedResolverError.ts';
8
- import type { ReferenceOptions } from '../options/index.ts';
9
-
10
- /**
11
- * Reads the given file, using the configured resolver plugins.
12
- */
13
-
14
- export const readFile = async (file: File, options: ReferenceOptions): Promise<Buffer> => {
15
- const optsBoundResolvers: Resolver[] = options.resolve.resolvers.map((resolver) => {
16
- const clonedResolver = Object.create(resolver);
17
- return Object.assign(clonedResolver, options.resolve.resolverOpts);
18
- });
19
-
20
- const resolvers: Resolver[] = await plugins.filter(
21
- 'canRead',
22
- [file, options],
23
- optsBoundResolvers,
24
- );
25
-
26
- // we couldn't find any resolver for this File
27
- if (isEmpty(resolvers)) {
28
- throw new UnmatchedResolverError(
29
- `Could not find a resolver that can read the file "${file.uri}"`,
30
- );
31
- }
32
-
33
- try {
34
- const { result } = await plugins.run('read', [file, options], resolvers);
35
- return result;
36
- } catch (error: any) {
37
- throw new ResolveError(`Error while reading file "${file.uri}"`, { cause: error });
38
- }
39
- };
@@ -1,37 +0,0 @@
1
- import { invokeArgs } from 'ramda-adjunct';
2
-
3
- /**
4
- * Filters the given plugins, returning only the ones return `true` for the given method.
5
- */
6
- export const filter = async (
7
- method: string,
8
- parameters: any[],
9
- plugins: Array<any>,
10
- ): Promise<Array<any>> => {
11
- const pluginResults = await Promise.all(plugins.map(invokeArgs([method], parameters)));
12
- return plugins.filter((plugin, index) => pluginResults[index]);
13
- };
14
-
15
- /**
16
- * Runs the specified method of the given plugins, in order,
17
- * until one of them returns a successful result.
18
- * Each method can return a synchronous value or a Promise.
19
- * If the promise resolves successfully then the result
20
- * is immediately returned and no further plugins are called.
21
- * If the promise rejects then the next plugin is called.
22
- * If ALL plugins fail, then the last error is thrown.
23
- */
24
- export const run = async (method: string, parameters: any[], plugins: any[]): Promise<any> => {
25
- let lastError;
26
-
27
- for (const plugin of plugins) {
28
- try {
29
- const result = await plugin[method].call(plugin, ...parameters);
30
- return { plugin, result };
31
- } catch (error: unknown) {
32
- lastError = error;
33
- }
34
- }
35
-
36
- return Promise.reject(lastError);
37
- };
package/src/util/url.ts DELETED
@@ -1,285 +0,0 @@
1
- import process from 'process';
2
- import { pathSatisfies, propOr, pipe, test, last } from 'ramda';
3
- import { isUndefined, replaceAll, isNotUndefined, trimCharsEnd } from 'ramda-adjunct';
4
-
5
- /**
6
- * SPDX-FileCopyrightText: Copyright (c) 2015 James Messinger
7
- *
8
- * SPDX-License-Identifier: MIT
9
- */
10
-
11
- /**
12
- * @public
13
- */
14
- export type WindowsPredicate = () => boolean;
15
-
16
- const isWindows: WindowsPredicate = () => pathSatisfies(test(/^win/), ['platform'], process);
17
-
18
- /**
19
- * Returns the protocol of the given URL, or `undefined` if it has no protocol.
20
- * @public
21
- */
22
- export const getProtocol = (url: string): string | undefined => {
23
- try {
24
- const parsedUrl = new URL(url);
25
- return trimCharsEnd(':', parsedUrl.protocol);
26
- } catch {
27
- return undefined;
28
- }
29
- };
30
-
31
- /**
32
- * Returns true if given URL has protocol.
33
- * @public
34
- */
35
- export const hasProtocol = pipe(getProtocol, isNotUndefined);
36
-
37
- /**
38
- * Returns the lower-cased file extension of the given URL,
39
- * or an empty string if it has no extension.
40
- * @public
41
- */
42
- export const getExtension = (url: string): string => {
43
- const lastDotPosition = url.lastIndexOf('.');
44
- if (lastDotPosition >= 0) {
45
- return url.substring(lastDotPosition).toLowerCase();
46
- }
47
- return '';
48
- };
49
-
50
- /**
51
- * Determines whether the given path is a filesystem path.
52
- * This includes "file://" URLs.
53
- * @public
54
- */
55
- export const isFileSystemPath = (uri: string): boolean => {
56
- const protocol = getProtocol(uri);
57
- return isUndefined(protocol) || protocol === 'file' || /^[a-zA-Z]$/.test(protocol);
58
- };
59
-
60
- /**
61
- * Determines whether the given URI is an HTTP(S) URL.
62
- * @public
63
- */
64
- export const isHttpUrl = (url: string): boolean => {
65
- const protocol = getProtocol(url);
66
- return protocol === 'http' || protocol === 'https';
67
- };
68
-
69
- /**
70
- * Determines whether the given URI
71
- * @public
72
- */
73
- export const isURI = (uri: string): boolean => {
74
- try {
75
- new URL(uri);
76
- return true;
77
- } catch {
78
- return false;
79
- }
80
- };
81
-
82
- /**
83
- * @public
84
- */
85
- export interface ToFileSystemPathOptions {
86
- keepFileProtocol?: boolean;
87
- isWindows?: WindowsPredicate;
88
- }
89
-
90
- /**
91
- * Converts a URL to a local filesystem path.
92
- * @public
93
- */
94
- export const toFileSystemPath = (uri: string, options?: ToFileSystemPathOptions): string => {
95
- // RegExp patterns to URL-decode special characters for local filesystem paths
96
- const urlDecodePatterns = [/%23/g, '#', /%24/g, '$', /%26/g, '&', /%2C/g, ',', /%40/g, '@'];
97
-
98
- const keepFileProtocol = propOr(false, 'keepFileProtocol', options);
99
- const isWindowsPredicate: WindowsPredicate = propOr(isWindows, 'isWindows', options);
100
-
101
- // Step 1: `decodeURI` will decode characters such as Cyrillic characters, spaces, etc.
102
- let path = decodeURI(uri);
103
-
104
- // Step 2: Manually decode characters that are not decoded by `decodeURI`.
105
- // This includes characters such as "#" and "?", which have special meaning in URLs,
106
- // but are just normal characters in a filesystem path.
107
- for (let i = 0; i < urlDecodePatterns.length; i += 2) {
108
- // @ts-ignore
109
- path = path.replace(urlDecodePatterns[i], urlDecodePatterns[i + 1]);
110
- }
111
-
112
- // Step 3: If it's a "file://" URL, then format it consistently
113
- // or convert it to a local filesystem path
114
- let isFileUrl = path.substring(0, 7).toLowerCase() === 'file://';
115
- if (isFileUrl) {
116
- // Strip-off the protocol, and the initial "/", if there is one
117
- path = path[7] === '/' ? path.substring(8) : path.substring(7);
118
-
119
- // insert a colon (":") after the drive letter on Windows
120
- if (isWindowsPredicate() && path[1] === '/') {
121
- path = `${path[0]}:${path.substring(1)}`;
122
- }
123
-
124
- if (keepFileProtocol) {
125
- // Return the consistently-formatted "file://" URL
126
- path = `file:///${path}`;
127
- } else {
128
- // Convert the "file://" URL to a local filesystem path.
129
- // On Windows, it will start with something like "C:/".
130
- // On Posix, it will start with "/"
131
- isFileUrl = false;
132
- path = isWindowsPredicate() ? path : `/${path}`;
133
- }
134
- }
135
-
136
- // Step 4: Normalize Windows paths (unless it's a "file://" URL)
137
- if (isWindowsPredicate() && !isFileUrl) {
138
- // Replace forward slashes with backslashes
139
- path = replaceAll('/', '\\', path);
140
-
141
- // Capitalize the drive letter
142
- if (path.substring(1, 3) === ':\\') {
143
- path = path[0].toUpperCase() + path.substring(1);
144
- }
145
- }
146
-
147
- return path;
148
- };
149
-
150
- /**
151
- * Converts a filesystem path to a properly-encoded URL.
152
- *
153
- * This is intended to handle situations where resolver is called
154
- * with a filesystem path that contains characters which are not allowed in URLs.
155
- *
156
- * @example
157
- * The following filesystem paths would be converted to the following URLs:
158
- *```
159
- * <"!@#$%^&*+=?'>.json ==> %3C%22!@%23$%25%5E&*+=%3F\'%3E.json
160
- * C:\\My Documents\\File (1).json ==> C:/My%20Documents/File%20(1).json
161
- * file://Project #42/file.json ==> file://Project%20%2342/file.json
162
- * ```
163
- * @public
164
- */
165
- export const fromFileSystemPath = (uri: string): string => {
166
- const urlEncodePatterns = [/\?/g, '%3F', /#/g, '%23'];
167
- let path = uri;
168
-
169
- // Step 1: On Windows, replace backslashes with forward slashes,
170
- // rather than encoding them as "%5C"
171
- if (isWindows()) {
172
- path = path.replace(/\\/g, '/');
173
- }
174
-
175
- // Step 2: `encodeURI` will take care of MOST characters
176
- path = encodeURI(path);
177
-
178
- // Step 3: Manually encode characters that are not encoded by `encodeURI`.
179
- // This includes characters such as "#" and "?", which have special meaning in URLs,
180
- // but are just normal characters in a filesystem path.
181
- for (let i = 0; i < urlEncodePatterns.length; i += 2) {
182
- // @ts-ignore
183
- path = path.replace(urlEncodePatterns[i], urlEncodePatterns[i + 1]);
184
- }
185
-
186
- return path;
187
- };
188
-
189
- /**
190
- * Returns the hash (URL fragment), of the given path.
191
- * If there is no hash, then the root hash ("#") is returned.
192
- * @public
193
- */
194
- export const getHash = (uri: string): string => {
195
- const hashIndex = uri.indexOf('#');
196
- if (hashIndex !== -1) {
197
- return uri.substring(hashIndex);
198
- }
199
- return '#';
200
- };
201
-
202
- /**
203
- * Removes the hash (URL fragment), if any, from the given path.
204
- * @public
205
- */
206
- export const stripHash = (uri: string): string => {
207
- const hashIndex = uri.indexOf('#');
208
- let hashStrippedUri = uri;
209
- if (hashIndex >= 0) {
210
- hashStrippedUri = uri.substring(0, hashIndex);
211
- }
212
- return hashStrippedUri;
213
- };
214
-
215
- /**
216
- * Returns the current working directory (in Node) or the current page URL (in browsers).
217
- * @public
218
- */
219
- export const cwd = (): string => {
220
- // @ts-ignore
221
- if (process.browser) {
222
- return stripHash(globalThis.location.href);
223
- }
224
-
225
- const path = process.cwd();
226
-
227
- const lastChar = last(path)!;
228
- if (['/', '\\'].includes(lastChar)) {
229
- return path;
230
- }
231
-
232
- return path + (isWindows() ? '\\' : '/');
233
- };
234
-
235
- /**
236
- * Resolves a target URI relative to a base URI in a manner similar to that of a Web browser resolving an anchor tag HREF.
237
- * @public
238
- */
239
- export const resolve = (from: string, to: string): string => {
240
- const resolvedUrl = new URL(to, new URL(from, 'resolve://'));
241
-
242
- if (resolvedUrl.protocol === 'resolve:') {
243
- // `from` is a relative URL.
244
- const { pathname, search, hash } = resolvedUrl;
245
- return pathname + search + hash;
246
- }
247
- return resolvedUrl.toString();
248
- };
249
-
250
- /**
251
- * Sanitizes/Encodes URI to it's url encoded form.
252
- *
253
- * The functional will compensate with the usecase when
254
- * already sanitized URI is passed to it,
255
- * by first unsatizing it and then performing sanitization again.
256
- * @public
257
- */
258
-
259
- export const sanitize = (uri: string) => {
260
- if (isFileSystemPath(uri)) {
261
- return fromFileSystemPath(toFileSystemPath(uri));
262
- }
263
-
264
- try {
265
- return new URL(uri).toString();
266
- } catch {
267
- // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI#encoding_for_ipv6
268
- return encodeURI(decodeURI(uri)).replace(/%5B/g, '[').replace(/%5D/g, ']');
269
- }
270
- };
271
-
272
- /**
273
- * Unsanitizes/Decodes URI to it's url encoded form.
274
- * This function already assumes that hash part of the URI
275
- * has been removed prior to transforming it to it's sanitized form.
276
- * @public
277
- */
278
-
279
- export const unsanitize = (uri: string): string => {
280
- if (isFileSystemPath(uri)) {
281
- return toFileSystemPath(uri);
282
- }
283
-
284
- return decodeURI(uri);
285
- };