@flex-development/mlly 1.0.0-alpha.16 → 1.0.0-alpha.18
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/CHANGELOG.md +61 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +0 -2
- package/dist/index.mjs.map +5 -6
- package/dist/internal/dequote.mjs +1 -0
- package/dist/internal/dequote.mjs.map +8 -0
- package/dist/internal/format-type-map.mjs +1 -0
- package/dist/internal/format-type-map.mjs.map +8 -0
- package/dist/internal/get-specifier-kind.mjs +1 -0
- package/dist/internal/get-specifier-kind.mjs.map +8 -0
- package/dist/internal/get-subpaths.mjs +1 -0
- package/dist/internal/get-subpaths.mjs.map +8 -0
- package/dist/internal/regex-encoded-sep.mjs +1 -0
- package/dist/internal/regex-encoded-sep.mjs.map +8 -0
- package/dist/internal/regex-internal-specifier.mjs +1 -0
- package/dist/internal/regex-internal-specifier.mjs.map +8 -0
- package/dist/internal/regex-invalid-segment.mjs +1 -0
- package/dist/internal/regex-invalid-segment.mjs.map +8 -0
- package/dist/internal/regex-package-name.mjs +1 -0
- package/dist/internal/regex-package-name.mjs.map +8 -0
- package/dist/internal/regex-package-path.mjs +1 -0
- package/dist/internal/regex-package-path.mjs.map +8 -0
- package/dist/internal/resolver.mjs +1 -0
- package/dist/internal/resolver.mjs.map +8 -0
- package/dist/internal/validate-array-set.mjs +1 -0
- package/dist/internal/validate-array-set.mjs.map +8 -0
- package/dist/internal/validate-boolean.mjs +1 -0
- package/dist/internal/validate-boolean.mjs.map +8 -0
- package/dist/internal/validate-map.mjs +1 -0
- package/dist/internal/validate-map.mjs.map +8 -0
- package/dist/internal/validate-object.mjs +1 -0
- package/dist/internal/validate-object.mjs.map +8 -0
- package/dist/internal/validate-set.mjs +1 -0
- package/dist/internal/validate-set.mjs.map +8 -0
- package/dist/internal/validate-string.mjs +1 -0
- package/dist/internal/validate-string.mjs.map +8 -0
- package/dist/internal/validate-url-string.mjs +1 -0
- package/dist/internal/validate-url-string.mjs.map +8 -0
- package/dist/utils/compare-subpaths.mjs.map +4 -5
- package/dist/utils/conditions.mjs.map +4 -5
- package/dist/utils/detect-syntax.mjs.map +4 -5
- package/dist/utils/extension-format-map.mjs.map +4 -5
- package/dist/utils/extract-statements.mjs.map +4 -5
- package/dist/utils/fill-modules.mjs.map +5 -8
- package/dist/utils/find-dynamic-imports.mjs.map +5 -8
- package/dist/utils/find-exports.mjs.map +5 -8
- package/dist/utils/find-requires.mjs.map +5 -8
- package/dist/utils/find-static-imports.mjs.map +5 -8
- package/dist/utils/find-subpath.mjs.map +5 -9
- package/dist/utils/get-format.mjs.map +5 -8
- package/dist/utils/get-source.mjs.map +4 -5
- package/dist/utils/has-cjs-syntax.mjs.map +4 -5
- package/dist/utils/has-esm-syntax.mjs.map +4 -5
- package/dist/utils/index.mjs.map +5 -8
- package/dist/utils/is-absolute-specifier.mjs.map +4 -5
- package/dist/utils/is-bare-specifier.mjs.map +4 -5
- package/dist/utils/is-directory.mjs.map +4 -5
- package/dist/utils/is-exports-sugar.mjs.map +4 -5
- package/dist/utils/is-file.mjs.map +4 -5
- package/dist/utils/is-relative-specifier.mjs.map +4 -5
- package/dist/utils/lookup-package-scope.mjs.map +4 -5
- package/dist/utils/parse-data-url.mjs.map +4 -5
- package/dist/utils/parse-module-id.mjs.map +5 -9
- package/dist/utils/parse-subpath.mjs.map +5 -8
- package/dist/utils/pattern-character.mjs.map +4 -5
- package/dist/utils/read-package-json.mjs.map +4 -5
- package/dist/utils/resolve-alias.mjs.map +5 -9
- package/dist/utils/resolve-aliases.mjs.map +4 -5
- package/dist/utils/resolve-extensions.mjs.map +4 -5
- package/dist/utils/resolve-module.d.mts +1 -1
- package/dist/utils/resolve-module.mjs.map +4 -5
- package/dist/utils/resolve-modules.mjs.map +4 -5
- package/dist/utils/to-absolute-specifier.mjs.map +4 -5
- package/dist/utils/to-bare-specifier.mjs +8 -1
- package/dist/utils/to-bare-specifier.mjs.map +5 -6
- package/dist/utils/to-data-url.mjs.map +4 -5
- package/dist/utils/to-node-url.mjs.map +4 -5
- package/dist/utils/to-relative-specifier.mjs.map +4 -5
- package/dist/utils/to-url.mjs.map +4 -5
- package/dist/utils/validate-assertions.mjs.map +5 -8
- package/dist/utils/validate-exports.mjs.map +4 -5
- package/package.json +16 -17
- package/dist/interfaces/index.mjs +0 -0
- package/dist/types/index.mjs +0 -0
- package/src/enums/assert-type.ts +0 -23
- package/src/enums/format.ts +0 -19
- package/src/enums/index.ts +0 -11
- package/src/enums/kind-specifier-syntax.ts +0 -16
- package/src/enums/kind-specifier.ts +0 -19
- package/src/enums/kind-statement-syntax.ts +0 -24
- package/src/enums/kind-statement.ts +0 -17
- package/src/index.ts +0 -9
- package/src/interfaces/import-assertions.ts +0 -24
- package/src/interfaces/import-dynamic.ts +0 -46
- package/src/interfaces/import-static.ts +0 -46
- package/src/interfaces/index.ts +0 -25
- package/src/interfaces/options-fill-module.ts +0 -26
- package/src/interfaces/options-find-subpath.ts +0 -57
- package/src/interfaces/options-get-format.ts +0 -80
- package/src/interfaces/options-get-source.ts +0 -59
- package/src/interfaces/options-parse-module-id.ts +0 -39
- package/src/interfaces/options-parse-subpath.ts +0 -57
- package/src/interfaces/options-resolve-alias.ts +0 -59
- package/src/interfaces/options-resolve-module.ts +0 -72
- package/src/interfaces/options-resolve.ts +0 -17
- package/src/interfaces/package-scope.ts +0 -30
- package/src/interfaces/parsed-data-url.ts +0 -63
- package/src/interfaces/parsed-module-id.ts +0 -90
- package/src/interfaces/parsed-subpath.ts +0 -56
- package/src/interfaces/statement-export.ts +0 -52
- package/src/interfaces/statement-import.ts +0 -45
- package/src/interfaces/statement-require.ts +0 -45
- package/src/interfaces/statement.ts +0 -64
- package/src/internal/dequote.ts +0 -18
- package/src/internal/format-type-map.ts +0 -28
- package/src/internal/get-specifier-kind.ts +0 -41
- package/src/internal/get-subpaths.ts +0 -43
- package/src/internal/regex-encoded-sep.ts +0 -17
- package/src/internal/regex-internal-specifier.ts +0 -19
- package/src/internal/regex-invalid-segment.ts +0 -25
- package/src/internal/regex-package-name.ts +0 -18
- package/src/internal/regex-package-path.ts +0 -20
- package/src/internal/resolver.ts +0 -790
- package/src/internal/validate-array-set.ts +0 -35
- package/src/internal/validate-boolean.ts +0 -30
- package/src/internal/validate-map.ts +0 -36
- package/src/internal/validate-object.ts +0 -30
- package/src/internal/validate-set.ts +0 -32
- package/src/internal/validate-string.ts +0 -31
- package/src/internal/validate-url-string.ts +0 -34
- package/src/types/declaration.ts +0 -22
- package/src/types/fn-change-ext.ts +0 -33
- package/src/types/index.ts +0 -14
- package/src/types/mime-type.ts +0 -19
- package/src/types/module-id.ts +0 -15
- package/src/types/module-specifier-type.ts +0 -13
- package/src/types/protocol.ts +0 -40
- package/src/types/syntax-kind-export.ts +0 -20
- package/src/types/syntax-kind-import.ts +0 -22
- package/src/types/syntax-kind-require.ts +0 -15
- package/src/utils/compare-subpaths.ts +0 -100
- package/src/utils/conditions.ts +0 -15
- package/src/utils/detect-syntax.ts +0 -40
- package/src/utils/extension-format-map.ts +0 -34
- package/src/utils/extract-statements.ts +0 -46
- package/src/utils/fill-modules.ts +0 -133
- package/src/utils/find-dynamic-imports.ts +0 -75
- package/src/utils/find-exports.ts +0 -156
- package/src/utils/find-requires.ts +0 -75
- package/src/utils/find-static-imports.ts +0 -86
- package/src/utils/find-subpath.ts +0 -251
- package/src/utils/get-format.ts +0 -249
- package/src/utils/get-source.ts +0 -144
- package/src/utils/has-cjs-syntax.ts +0 -44
- package/src/utils/has-esm-syntax.ts +0 -40
- package/src/utils/index.ts +0 -45
- package/src/utils/is-absolute-specifier.ts +0 -53
- package/src/utils/is-bare-specifier.ts +0 -36
- package/src/utils/is-directory.ts +0 -25
- package/src/utils/is-exports-sugar.ts +0 -81
- package/src/utils/is-file.ts +0 -25
- package/src/utils/is-relative-specifier.ts +0 -34
- package/src/utils/lookup-package-scope.ts +0 -97
- package/src/utils/parse-data-url.ts +0 -71
- package/src/utils/parse-module-id.ts +0 -197
- package/src/utils/parse-subpath.ts +0 -331
- package/src/utils/pattern-character.ts +0 -13
- package/src/utils/read-package-json.ts +0 -113
- package/src/utils/resolve-alias.ts +0 -224
- package/src/utils/resolve-aliases.ts +0 -58
- package/src/utils/resolve-extensions.ts +0 -33
- package/src/utils/resolve-module.ts +0 -181
- package/src/utils/resolve-modules.ts +0 -60
- package/src/utils/to-absolute-specifier.ts +0 -30
- package/src/utils/to-bare-specifier.ts +0 -211
- package/src/utils/to-data-url.ts +0 -42
- package/src/utils/to-node-url.ts +0 -27
- package/src/utils/to-relative-specifier.ts +0 -55
- package/src/utils/to-url.ts +0 -30
- package/src/utils/validate-assertions.ts +0 -126
- package/src/utils/validate-exports.ts +0 -131
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file parseModuleId
|
|
3
|
-
* @module mlly/lib/parseModuleId
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { ParseModuleIdOptions, ParsedModuleId } from '#src/interfaces'
|
|
7
|
-
import ENCODED_SEP_REGEX from '#src/internal/regex-encoded-sep'
|
|
8
|
-
import INTERNAL_SPECIFIER_REGEX from '#src/internal/regex-internal-specifier'
|
|
9
|
-
import PACKAGE_PATH_REGEX from '#src/internal/regex-package-path'
|
|
10
|
-
import validateBoolean from '#src/internal/validate-boolean'
|
|
11
|
-
import validateURLString from '#src/internal/validate-url-string'
|
|
12
|
-
import type { ModuleId } from '#src/types'
|
|
13
|
-
import {
|
|
14
|
-
ERR_INVALID_MODULE_SPECIFIER,
|
|
15
|
-
type NodeError
|
|
16
|
-
} from '@flex-development/errnode'
|
|
17
|
-
import { isBuiltin } from '@flex-development/is-builtin'
|
|
18
|
-
import pathe from '@flex-development/pathe'
|
|
19
|
-
import {
|
|
20
|
-
DOT,
|
|
21
|
-
cast,
|
|
22
|
-
isString,
|
|
23
|
-
isUndefined,
|
|
24
|
-
trim,
|
|
25
|
-
type Optional
|
|
26
|
-
} from '@flex-development/tutils'
|
|
27
|
-
import { URL, fileURLToPath } from 'node:url'
|
|
28
|
-
import isBareSpecifier from './is-bare-specifier'
|
|
29
|
-
import isRelativeSpecifier from './is-relative-specifier'
|
|
30
|
-
import toNodeURL from './to-node-url'
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Creates an object representation the given module `id`.
|
|
34
|
-
*
|
|
35
|
-
* @see {@linkcode ModuleId}
|
|
36
|
-
* @see {@linkcode ParseModuleIdOptions}
|
|
37
|
-
* @see {@linkcode ParsedModuleId}
|
|
38
|
-
*
|
|
39
|
-
* @param {ModuleId} id - Module id to parse
|
|
40
|
-
* @param {ParseModuleIdOptions?} [options={}] - Parsing options
|
|
41
|
-
* @return {ParsedModuleId} Object representing `id`
|
|
42
|
-
* @throws {NodeError<TypeError>}
|
|
43
|
-
*/
|
|
44
|
-
const parseModuleId = (
|
|
45
|
-
id: ModuleId,
|
|
46
|
-
options: ParseModuleIdOptions = {}
|
|
47
|
-
): ParsedModuleId => {
|
|
48
|
-
const {
|
|
49
|
-
internal = id instanceof URL ? false : id.startsWith('#'),
|
|
50
|
-
pkgname = false
|
|
51
|
-
} = options
|
|
52
|
-
|
|
53
|
-
// ensure id is an instance of URL or a string
|
|
54
|
-
validateURLString(id, 'id')
|
|
55
|
-
|
|
56
|
-
// ensure option schemas
|
|
57
|
-
validateBoolean(internal, 'options.internal')
|
|
58
|
-
validateBoolean(pkgname, 'options.pkgname')
|
|
59
|
-
|
|
60
|
-
// ensure id a string without leading and trailing spaces
|
|
61
|
-
id = id instanceof URL ? id.href : trim(id)
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Reason for [`ERR_INVALID_MODULE_SPECIFIER`][1], if any.
|
|
65
|
-
*
|
|
66
|
-
* [1]: https://nodejs.org/api/errors.html#err_invalid_module_specifier
|
|
67
|
-
*
|
|
68
|
-
* @const {Optional<string>} error
|
|
69
|
-
*/
|
|
70
|
-
let error: Optional<string>
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Object representing `id`.
|
|
74
|
-
*
|
|
75
|
-
* @var {ParsedModuleId} parsed
|
|
76
|
-
*/
|
|
77
|
-
let parsed: ParsedModuleId = {
|
|
78
|
-
internal: false,
|
|
79
|
-
path: id,
|
|
80
|
-
pkg: '',
|
|
81
|
-
protocol: '',
|
|
82
|
-
raw: id,
|
|
83
|
-
scope: '',
|
|
84
|
-
version: '',
|
|
85
|
-
version_prefix: ''
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// try parsing module id
|
|
89
|
-
switch (true) {
|
|
90
|
-
case ENCODED_SEP_REGEX.test(id):
|
|
91
|
-
error = `must not include encoded '${pathe.sep}' or '\\' characters`
|
|
92
|
-
break
|
|
93
|
-
case isBuiltin(id):
|
|
94
|
-
const { href, protocol, pathname } = new URL(toNodeURL(id))
|
|
95
|
-
|
|
96
|
-
parsed = {
|
|
97
|
-
internal: false,
|
|
98
|
-
path: pathname.replace(/^\S+?(?=\/|$)/, ''),
|
|
99
|
-
pkg: href.replace(/\/.*$/, ''),
|
|
100
|
-
protocol: id.startsWith('node:') ? protocol : '',
|
|
101
|
-
raw: id,
|
|
102
|
-
scope: '',
|
|
103
|
-
version: '',
|
|
104
|
-
version_prefix: ''
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
break
|
|
108
|
-
case INTERNAL_SPECIFIER_REGEX.test(id):
|
|
109
|
-
const [, root = ''] = INTERNAL_SPECIFIER_REGEX.exec(id)!
|
|
110
|
-
|
|
111
|
-
parsed = {
|
|
112
|
-
internal: true,
|
|
113
|
-
path: id,
|
|
114
|
-
pkg: root,
|
|
115
|
-
protocol: '',
|
|
116
|
-
raw: id,
|
|
117
|
-
scope: '',
|
|
118
|
-
version: '',
|
|
119
|
-
version_prefix: ''
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
break
|
|
123
|
-
case PACKAGE_PATH_REGEX.test(id):
|
|
124
|
-
const [
|
|
125
|
-
,
|
|
126
|
-
pkg = '',
|
|
127
|
-
scope = '',
|
|
128
|
-
version_prefix = '',
|
|
129
|
-
version = '',
|
|
130
|
-
subpath = ''
|
|
131
|
-
] = PACKAGE_PATH_REGEX.exec(id)!
|
|
132
|
-
|
|
133
|
-
parsed = {
|
|
134
|
-
internal: false,
|
|
135
|
-
path: DOT + subpath,
|
|
136
|
-
pkg,
|
|
137
|
-
protocol: '',
|
|
138
|
-
raw: id,
|
|
139
|
-
scope,
|
|
140
|
-
version,
|
|
141
|
-
version_prefix
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
break
|
|
145
|
-
case /^[\w-]{2,}:/.test(id):
|
|
146
|
-
try {
|
|
147
|
-
const { host, protocol, pathname } = new URL(id)
|
|
148
|
-
|
|
149
|
-
parsed = {
|
|
150
|
-
internal: false,
|
|
151
|
-
path: host + pathname,
|
|
152
|
-
pkg: '',
|
|
153
|
-
protocol,
|
|
154
|
-
raw: id,
|
|
155
|
-
scope: '',
|
|
156
|
-
version: '',
|
|
157
|
-
version_prefix: ''
|
|
158
|
-
}
|
|
159
|
-
} catch {
|
|
160
|
-
error = 'is not a valid URL'
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
break
|
|
164
|
-
case isBareSpecifier(cast(id)):
|
|
165
|
-
case isRelativeSpecifier(cast(id)):
|
|
166
|
-
case pathe.isAbsolute(id):
|
|
167
|
-
break
|
|
168
|
-
default:
|
|
169
|
-
error = ''
|
|
170
|
-
break
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// reset error reason
|
|
174
|
-
error = ENCODED_SEP_REGEX.test(id)
|
|
175
|
-
? error
|
|
176
|
-
: internal && !INTERNAL_SPECIFIER_REGEX.test(id)
|
|
177
|
-
? 'is not a valid internal imports specifier name'
|
|
178
|
-
: pkgname && !PACKAGE_PATH_REGEX.test(id)
|
|
179
|
-
? 'does not start with a valid package name'
|
|
180
|
-
: error
|
|
181
|
-
|
|
182
|
-
// throw if module specifier is invalid
|
|
183
|
-
if (isString(error)) {
|
|
184
|
-
let { parent } = options
|
|
185
|
-
|
|
186
|
-
if (!isUndefined(parent)) {
|
|
187
|
-
validateURLString(parent, 'options.parent')
|
|
188
|
-
parent = fileURLToPath(parent)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
throw new ERR_INVALID_MODULE_SPECIFIER(id, error, parent)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
return parsed
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
export default parseModuleId
|
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file parseSubpath
|
|
3
|
-
* @module mlly/utils/parseSubpath
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type {
|
|
7
|
-
ParseSubpathOptions,
|
|
8
|
-
ParsedModuleId,
|
|
9
|
-
ParsedSubpath
|
|
10
|
-
} from '#src/interfaces'
|
|
11
|
-
import getSubpaths from '#src/internal/get-subpaths'
|
|
12
|
-
import invalidSegmentRegex from '#src/internal/regex-invalid-segment'
|
|
13
|
-
import PACKAGE_NAME_REGEX from '#src/internal/regex-package-name'
|
|
14
|
-
import validateArraySet from '#src/internal/validate-array-set'
|
|
15
|
-
import validateBoolean from '#src/internal/validate-boolean'
|
|
16
|
-
import validateString from '#src/internal/validate-string'
|
|
17
|
-
import validateURLString from '#src/internal/validate-url-string'
|
|
18
|
-
import {
|
|
19
|
-
ERR_INVALID_PACKAGE_CONFIG,
|
|
20
|
-
ERR_INVALID_PACKAGE_TARGET,
|
|
21
|
-
ERR_PACKAGE_IMPORT_NOT_DEFINED,
|
|
22
|
-
ERR_PACKAGE_PATH_NOT_EXPORTED,
|
|
23
|
-
ErrorCode,
|
|
24
|
-
type NodeError
|
|
25
|
-
} from '@flex-development/errnode'
|
|
26
|
-
import pathe from '@flex-development/pathe'
|
|
27
|
-
import type { Exports, Imports } from '@flex-development/pkg-types'
|
|
28
|
-
import {
|
|
29
|
-
CompareResult,
|
|
30
|
-
DOT,
|
|
31
|
-
cast,
|
|
32
|
-
get,
|
|
33
|
-
isArray,
|
|
34
|
-
isArrayIndex,
|
|
35
|
-
isNIL,
|
|
36
|
-
isNull,
|
|
37
|
-
isObjectCurly,
|
|
38
|
-
isString,
|
|
39
|
-
type Dot,
|
|
40
|
-
type Nullable,
|
|
41
|
-
type Optional
|
|
42
|
-
} from '@flex-development/tutils'
|
|
43
|
-
import { URL, fileURLToPath, pathToFileURL } from 'node:url'
|
|
44
|
-
import compareSubpaths from './compare-subpaths'
|
|
45
|
-
import CONDITIONS from './conditions'
|
|
46
|
-
import isExportsSugar from './is-exports-sugar'
|
|
47
|
-
import parseModuleId from './parse-module-id'
|
|
48
|
-
import PATTERN_CHARACTER from './pattern-character'
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Creates an object representation of a subpath export or import from the given
|
|
52
|
-
* module `specifier` after ensuring the subpath defined in `specifier` is also
|
|
53
|
-
* defined in the given package `context`, a `package.json` [`exports`][1] or
|
|
54
|
-
* [`imports`][2] field.
|
|
55
|
-
*
|
|
56
|
-
* ::: warning
|
|
57
|
-
* Does **not** guarantee `specifier` resolves to an existing module.
|
|
58
|
-
* :::
|
|
59
|
-
*
|
|
60
|
-
* [1]: https://nodejs.org/api/packages.html#exports
|
|
61
|
-
* [2]: https://nodejs.org/api/packages.html#imports
|
|
62
|
-
*
|
|
63
|
-
* @see {@linkcode Exports}
|
|
64
|
-
* @see {@linkcode Imports}
|
|
65
|
-
* @see {@linkcode ParseSubpathOptions}
|
|
66
|
-
* @see {@linkcode ParsedSubpath}
|
|
67
|
-
* @see https://nodejs.org/api/packages.html#subpath-exports
|
|
68
|
-
* @see https://nodejs.org/api/packages.html#subpath-imports
|
|
69
|
-
*
|
|
70
|
-
* @param {string} specifier - Module specifier to evaluate
|
|
71
|
-
* @param {Optional<Exports | Imports>} context - Package context
|
|
72
|
-
* @param {ParseSubpathOptions} options - Parsing options
|
|
73
|
-
* @return {ParsedSubpath} Object representing package subpath
|
|
74
|
-
* @throws {NodeError<Error | TypeError>}
|
|
75
|
-
*/
|
|
76
|
-
const parseSubpath = (
|
|
77
|
-
specifier: string,
|
|
78
|
-
context: Optional<Exports | Imports>,
|
|
79
|
-
options: ParseSubpathOptions
|
|
80
|
-
): ParsedSubpath => {
|
|
81
|
-
const {
|
|
82
|
-
condition = 'default',
|
|
83
|
-
conditions = CONDITIONS,
|
|
84
|
-
dir,
|
|
85
|
-
internal = specifier.startsWith('#'),
|
|
86
|
-
parent
|
|
87
|
-
} = options
|
|
88
|
-
|
|
89
|
-
// ensure specifier is a string
|
|
90
|
-
validateString(specifier, 'specifier')
|
|
91
|
-
|
|
92
|
-
// ensure option schemas
|
|
93
|
-
validateString(condition, 'options.condition')
|
|
94
|
-
validateArraySet(conditions, 'options.conditions')
|
|
95
|
-
validateURLString(dir, 'options.dir')
|
|
96
|
-
validateBoolean(internal, 'options.internal')
|
|
97
|
-
validateURLString(parent, 'options.parent')
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* Parsed module id.
|
|
101
|
-
*
|
|
102
|
-
* **Note**: Ensures {@linkcode specifier} begins with a valid package name or
|
|
103
|
-
* is a valid [subpath import][1].
|
|
104
|
-
*
|
|
105
|
-
* [1]: https://nodejs.org/api/packages.html#subpath-imports
|
|
106
|
-
*
|
|
107
|
-
* @const {ParsedModuleId} id
|
|
108
|
-
*/
|
|
109
|
-
const id: ParsedModuleId = parseModuleId(specifier, {
|
|
110
|
-
internal,
|
|
111
|
-
parent,
|
|
112
|
-
pkgname: !internal
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Absolute path to directory containing relevant `package.json` file.
|
|
117
|
-
*
|
|
118
|
-
* @const {string} pkgdir
|
|
119
|
-
*/
|
|
120
|
-
const pkgdir: string = fileURLToPath(dir).replace(/\/$/, '') + pathe.sep
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* URL of relevant `package.json` file.
|
|
124
|
-
*
|
|
125
|
-
* @const {URL} pkg
|
|
126
|
-
*/
|
|
127
|
-
const pkg: URL = new URL('package.json', pathToFileURL(pkgdir))
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Subpaths defined in {@linkcode context}.
|
|
131
|
-
*
|
|
132
|
-
* @const {string[]} keys
|
|
133
|
-
*/
|
|
134
|
-
const keys: string[] = getSubpaths(context, id.internal, pkg, parent)
|
|
135
|
-
|
|
136
|
-
/**
|
|
137
|
-
* Subpath defined in {@linkcode context} that maps to {@linkcode specifier}.
|
|
138
|
-
*
|
|
139
|
-
* @var {Nullable<string>} key
|
|
140
|
-
*/
|
|
141
|
-
let key: Nullable<string> = null
|
|
142
|
-
|
|
143
|
-
/**
|
|
144
|
-
* Subpath without entry prefix ({@linkcode key}).
|
|
145
|
-
*
|
|
146
|
-
* @var {string} base
|
|
147
|
-
*/
|
|
148
|
-
let base: string = ''
|
|
149
|
-
|
|
150
|
-
// match specifier to subpath defined in context
|
|
151
|
-
for (const pkgsubpath of keys) {
|
|
152
|
-
/**
|
|
153
|
-
* Index of {@linkcode PATTERN_CHARACTER} in {@linkcode pkgsubpath}.
|
|
154
|
-
*
|
|
155
|
-
* @const {number} pattern
|
|
156
|
-
*/
|
|
157
|
-
const pattern: number = pkgsubpath.indexOf(PATTERN_CHARACTER)
|
|
158
|
-
|
|
159
|
-
// no pattern character => subpath must be exact match
|
|
160
|
-
if (pattern === -1 && pkgsubpath === id.path) {
|
|
161
|
-
key = pkgsubpath
|
|
162
|
-
break
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
// pattern character => try finding best match for subpath
|
|
166
|
-
if (pattern !== -1 && id.path.startsWith(pkgsubpath.slice(0, pattern))) {
|
|
167
|
-
/**
|
|
168
|
-
* Everything after pattern character (`*`) in {@linkcode pkgsubpath}.
|
|
169
|
-
*
|
|
170
|
-
* @const {string} trailer
|
|
171
|
-
*/
|
|
172
|
-
const trailer: string = pkgsubpath.slice(pattern + 1)
|
|
173
|
-
|
|
174
|
-
// best match found => reset key and base of subpath
|
|
175
|
-
if (
|
|
176
|
-
id.path.length >= pkgsubpath.length &&
|
|
177
|
-
id.path.endsWith(trailer) &&
|
|
178
|
-
compareSubpaths(key ?? '', pkgsubpath) === CompareResult.GREATER_THAN &&
|
|
179
|
-
pkgsubpath.lastIndexOf(PATTERN_CHARACTER) === pattern
|
|
180
|
-
) {
|
|
181
|
-
key = pkgsubpath
|
|
182
|
-
base = id.path.slice(pattern, id.path.length - trailer.length)
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// throw if defined subpath was not found
|
|
188
|
-
if (isNull(key)) {
|
|
189
|
-
let { parent } = options
|
|
190
|
-
|
|
191
|
-
// ensure parent is a path
|
|
192
|
-
parent = fileURLToPath(parent)
|
|
193
|
-
|
|
194
|
-
throw internal
|
|
195
|
-
? new ERR_PACKAGE_IMPORT_NOT_DEFINED(id.path, parent, pkgdir)
|
|
196
|
-
: new ERR_PACKAGE_PATH_NOT_EXPORTED(pkgdir, id.path, parent)
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Finds the package target string specified by {@linkcode key}.
|
|
201
|
-
*
|
|
202
|
-
* @param {Optional<Exports>} data - Initial package target
|
|
203
|
-
* @return {Nullable<string>} Package target string or `null`
|
|
204
|
-
* @throws {NodeError<Error | TypeError>}
|
|
205
|
-
*/
|
|
206
|
-
const findPackageTarget = (data: Optional<Exports>): Nullable<string> => {
|
|
207
|
-
/**
|
|
208
|
-
* Package target.
|
|
209
|
-
*
|
|
210
|
-
* @var {Nullable<string>} target
|
|
211
|
-
*/
|
|
212
|
-
let target: Nullable<string> = null
|
|
213
|
-
|
|
214
|
-
switch (true) {
|
|
215
|
-
case isNIL(data):
|
|
216
|
-
target = null
|
|
217
|
-
break
|
|
218
|
-
case isArray(data):
|
|
219
|
-
/**
|
|
220
|
-
* Possible package target search error.
|
|
221
|
-
*
|
|
222
|
-
* @var {Optional<NodeError>} error
|
|
223
|
-
*/
|
|
224
|
-
let error: Optional<NodeError>
|
|
225
|
-
|
|
226
|
-
// try finding package target based on first match in search context
|
|
227
|
-
for (const item of cast<string[]>(data)) {
|
|
228
|
-
try {
|
|
229
|
-
target = findPackageTarget(item)
|
|
230
|
-
} catch (e: unknown) {
|
|
231
|
-
error = cast<NodeError>(e)
|
|
232
|
-
|
|
233
|
-
/* c8 ignore next */
|
|
234
|
-
if (error.code !== ErrorCode.ERR_INVALID_PACKAGE_TARGET) throw error
|
|
235
|
-
|
|
236
|
-
continue
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// stop search attempts if target was found
|
|
240
|
-
if (target) {
|
|
241
|
-
error = undefined
|
|
242
|
-
break
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
// throw if error was encountered
|
|
247
|
-
if (error) throw error
|
|
248
|
-
|
|
249
|
-
break
|
|
250
|
-
case isObjectCurly(data):
|
|
251
|
-
data = cast<Record<string, Exports>>(data)
|
|
252
|
-
|
|
253
|
-
// try finding package target based on condition
|
|
254
|
-
for (const property of Object.getOwnPropertyNames(data)) {
|
|
255
|
-
if (isArrayIndex(property)) {
|
|
256
|
-
throw new ERR_INVALID_PACKAGE_CONFIG(
|
|
257
|
-
fileURLToPath(pkg),
|
|
258
|
-
fileURLToPath(parent),
|
|
259
|
-
'"exports" cannot contain numeric property keys'
|
|
260
|
-
)
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// check conditions
|
|
264
|
-
if (property === condition || new Set(conditions).has(property)) {
|
|
265
|
-
target = findPackageTarget(data[property])
|
|
266
|
-
if (target) break
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
break
|
|
271
|
-
case isString(data):
|
|
272
|
-
target = cast<string>(data)
|
|
273
|
-
|
|
274
|
-
switch (true) {
|
|
275
|
-
case internal && PACKAGE_NAME_REGEX.test(target):
|
|
276
|
-
break
|
|
277
|
-
case target.startsWith(DOT + pathe.sep):
|
|
278
|
-
// check target for invalid segments
|
|
279
|
-
if (invalidSegmentRegex().test(target.slice(2))) {
|
|
280
|
-
if (invalidSegmentRegex('deprecated').test(target.slice(2))) {
|
|
281
|
-
throw new ERR_INVALID_PACKAGE_TARGET(
|
|
282
|
-
fileURLToPath(dir),
|
|
283
|
-
key!,
|
|
284
|
-
target,
|
|
285
|
-
internal,
|
|
286
|
-
fileURLToPath(parent)
|
|
287
|
-
)
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
break
|
|
292
|
-
default:
|
|
293
|
-
throw new ERR_INVALID_PACKAGE_TARGET(
|
|
294
|
-
fileURLToPath(dir),
|
|
295
|
-
key!,
|
|
296
|
-
target,
|
|
297
|
-
internal,
|
|
298
|
-
fileURLToPath(parent)
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
break
|
|
303
|
-
default:
|
|
304
|
-
throw new ERR_INVALID_PACKAGE_TARGET(
|
|
305
|
-
fileURLToPath(dir),
|
|
306
|
-
key!,
|
|
307
|
-
data,
|
|
308
|
-
internal,
|
|
309
|
-
fileURLToPath(parent)
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return target
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// convert exports to object if using exports main sugar
|
|
317
|
-
if (!internal && isExportsSugar(context, pkg, parent)) {
|
|
318
|
-
context = cast<Record<Dot, Exports>>({ [DOT]: context })
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
return {
|
|
322
|
-
base,
|
|
323
|
-
internal,
|
|
324
|
-
key,
|
|
325
|
-
raw: id.path,
|
|
326
|
-
specifier: id.raw,
|
|
327
|
-
target: findPackageTarget(get(context, key))
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export default parseSubpath
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file PATTERN_CHARACTER
|
|
3
|
-
* @module mlly/utils/PATTERN_CHARACTER
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Character representing a subpath pattern.
|
|
8
|
-
*
|
|
9
|
-
* @const {string} PATTERN_CHARACTER
|
|
10
|
-
*/
|
|
11
|
-
const PATTERN_CHARACTER: string = '*'
|
|
12
|
-
|
|
13
|
-
export default PATTERN_CHARACTER
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @file readPackageJson
|
|
3
|
-
* @module mlly/utils/readPackageJson
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import validateString from '#src/internal/validate-string'
|
|
7
|
-
import validateURLString from '#src/internal/validate-url-string'
|
|
8
|
-
import type { ModuleId } from '#src/types'
|
|
9
|
-
import {
|
|
10
|
-
ERR_INVALID_PACKAGE_CONFIG,
|
|
11
|
-
type NodeError
|
|
12
|
-
} from '@flex-development/errnode'
|
|
13
|
-
import pathe from '@flex-development/pathe'
|
|
14
|
-
import type { PackageJson } from '@flex-development/pkg-types'
|
|
15
|
-
import {
|
|
16
|
-
DOT,
|
|
17
|
-
cast,
|
|
18
|
-
isEmptyString,
|
|
19
|
-
isNIL,
|
|
20
|
-
isUndefined,
|
|
21
|
-
type Nullable,
|
|
22
|
-
type Optional
|
|
23
|
-
} from '@flex-development/tutils'
|
|
24
|
-
import fs from 'node:fs'
|
|
25
|
-
import { fileURLToPath } from 'node:url'
|
|
26
|
-
import isFile from './is-file'
|
|
27
|
-
import toURL from './to-url'
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Reads a `package.json` file from the given directory.
|
|
31
|
-
*
|
|
32
|
-
* Returns `null` if a file is not found.
|
|
33
|
-
*
|
|
34
|
-
* @see {@linkcode ModuleId}
|
|
35
|
-
* @see {@linkcode PackageJson}
|
|
36
|
-
*
|
|
37
|
-
* @param {ModuleId} [dir='.'] - Id of directory containing `package.json` file
|
|
38
|
-
* @param {string?} [specifier] - Module specifier passed by user to initiate
|
|
39
|
-
* reading of `package.json` file
|
|
40
|
-
* @param {ModuleId?} [parent] - Id of module to resolve from
|
|
41
|
-
* @return {?PackageJson} `package.json` object or `null` if file is not found
|
|
42
|
-
* @throws {NodeError<Error | TypeError>} If `dir` is not a string or instance
|
|
43
|
-
* of {@linkcode URL}, if `specifier` is not a string, if `parent` is not a
|
|
44
|
-
* string, or if a `package.json` is file found and does not contain valid JSON
|
|
45
|
-
*/
|
|
46
|
-
const readPackageJson = (
|
|
47
|
-
dir: ModuleId = DOT,
|
|
48
|
-
specifier?: string,
|
|
49
|
-
parent?: ModuleId
|
|
50
|
-
): Nullable<PackageJson> => {
|
|
51
|
-
// ensure dir is an instance of URL or a string
|
|
52
|
-
validateURLString(dir, 'dir')
|
|
53
|
-
|
|
54
|
-
// ensure specifier is a string
|
|
55
|
-
!isUndefined(specifier) && validateString(specifier, 'specifier')
|
|
56
|
-
|
|
57
|
-
// ensure parent is an instance of URL or a string
|
|
58
|
-
!isUndefined(parent) && validateURLString(parent, 'parent')
|
|
59
|
-
|
|
60
|
-
// ensure dir is a path
|
|
61
|
-
dir = fileURLToPath(toURL(dir))
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Absolute path to `package.json` file.
|
|
65
|
-
*
|
|
66
|
-
* @const {string} path
|
|
67
|
-
*/
|
|
68
|
-
const path: string = pathe.toNamespacedPath(pathe.join(dir, 'package.json'))
|
|
69
|
-
|
|
70
|
-
// return null if package.json file does not exist
|
|
71
|
-
if (!isFile(path)) return null
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Possible `package.json` object.
|
|
75
|
-
*
|
|
76
|
-
* @var {PackageJson} pkg
|
|
77
|
-
*/
|
|
78
|
-
let pkg: PackageJson
|
|
79
|
-
|
|
80
|
-
// try parsing package.json file
|
|
81
|
-
try {
|
|
82
|
-
pkg = JSON.parse(fs.readFileSync(path, 'utf8'))
|
|
83
|
-
} catch (e: unknown) {
|
|
84
|
-
/**
|
|
85
|
-
* String containing module specifier passed by user to initiate reading of
|
|
86
|
-
* `package.json` file and the location the module specifier was imported
|
|
87
|
-
* from.
|
|
88
|
-
*
|
|
89
|
-
* @var {Optional<string>} base
|
|
90
|
-
*/
|
|
91
|
-
let base: Optional<string>
|
|
92
|
-
|
|
93
|
-
// get base
|
|
94
|
-
switch (true) {
|
|
95
|
-
case specifier && !isNIL(parent) && !isEmptyString(parent):
|
|
96
|
-
base = `'${specifier}' from ${fileURLToPath(toURL(parent!))}`
|
|
97
|
-
break
|
|
98
|
-
case specifier?.startsWith('file:'):
|
|
99
|
-
base = fileURLToPath(specifier!)
|
|
100
|
-
break
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
throw new ERR_INVALID_PACKAGE_CONFIG(
|
|
104
|
-
path,
|
|
105
|
-
base,
|
|
106
|
-
cast<SyntaxError>(e).message
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return pkg
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export default readPackageJson
|