limina 0.0.4 → 0.0.6
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/LICENSE.md +1348 -0
- package/README.md +16 -373
- package/README.zh-CN.md +29 -0
- package/bin/limina.js +32 -21
- package/chunks/dep-BPK-6PAr.js +114 -0
- package/chunks/dep-COZNKoxO.js +15582 -0
- package/chunks/dep-Ce6cDHmw.js +4901 -0
- package/chunks/dep-esXeyN9I.js +194 -0
- package/cli.js +22266 -1125
- package/config.d.ts +300 -58
- package/config.js +2 -3
- package/index.d.ts +22 -2
- package/index.js +3 -4
- package/package.json +27 -13
- package/schemas/tsconfig-schema.json +42 -0
- package/chunks/dep-DzYrmtQJ.js +0 -360
- package/chunks/dep-ZRIm_-Zk.js +0 -2401
- package/chunks/dep-lkQg1P9Q.js +0 -3
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { a as __toESM, t as require_picocolors } from "./dep-BPK-6PAr.js";
|
|
2
|
+
|
|
3
|
+
//#region ../../node_modules/.pnpm/publint@0.3.17/node_modules/publint/src/shared/utils.js
|
|
4
|
+
/**
|
|
5
|
+
* @param {string[]} path
|
|
6
|
+
* @returns {string}
|
|
7
|
+
*/
|
|
8
|
+
function formatMessagePath(path) {
|
|
9
|
+
let formatted = "pkg";
|
|
10
|
+
for (const part of path) if (/^\d+$/.test(part)) formatted += `[${part}]`;
|
|
11
|
+
else if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(part)) formatted += `["${part}"]`;
|
|
12
|
+
else formatted += "." + part;
|
|
13
|
+
return formatted;
|
|
14
|
+
}
|
|
15
|
+
/** @type {import('../utils.d.ts').getPkgPathValue} */
|
|
16
|
+
function getPkgPathValue(pkg, path) {
|
|
17
|
+
let v = pkg;
|
|
18
|
+
for (const p of path) v = v[p];
|
|
19
|
+
return v;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} str
|
|
23
|
+
* @param {string} search
|
|
24
|
+
* @param {string} replace
|
|
25
|
+
*/
|
|
26
|
+
function replaceLast(str, search, replace) {
|
|
27
|
+
const index = str.lastIndexOf(search);
|
|
28
|
+
if (index === -1) return str;
|
|
29
|
+
return str.slice(0, index) + replace + str.slice(index + search.length);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region ../../node_modules/.pnpm/publint@0.3.17/node_modules/publint/src/shared/message.js
|
|
34
|
+
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
35
|
+
const EMPTY_MSG = "<empty>";
|
|
36
|
+
/** @type {import('../utils.d.ts').formatMessage} */
|
|
37
|
+
function formatMessage(m, pkg, opts = {}) {
|
|
38
|
+
const h = getHighlighter(opts.color);
|
|
39
|
+
/** @param {string[]} path */
|
|
40
|
+
const pv = (path) => {
|
|
41
|
+
try {
|
|
42
|
+
const str = String(getPkgPathValue(pkg, path));
|
|
43
|
+
return str === "" ? EMPTY_MSG : str;
|
|
44
|
+
} catch {
|
|
45
|
+
return "undefined";
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
switch (m.code) {
|
|
49
|
+
case "IMPLICIT_INDEX_JS_INVALID_FORMAT": return `index.js should be ${m.args.expectFormat} but it is ${m.args.actualFormat}`;
|
|
50
|
+
case "FILE_INVALID_FORMAT": {
|
|
51
|
+
const relativePath = m.args.actualFilePath ?? pv(m.path);
|
|
52
|
+
let start = "";
|
|
53
|
+
if (opts.reference || m.path[0] === "name") start = h.bold(relativePath);
|
|
54
|
+
else {
|
|
55
|
+
const is = pv(m.path).includes("*") ? "matches" : "is";
|
|
56
|
+
start = `${h.bold(formatMessagePath(m.path))} ${is} ${h.bold(relativePath)} and`;
|
|
57
|
+
}
|
|
58
|
+
return `${start} is written in ${h.warn(m.args.actualFormat)}, but is interpreted as ${h.warn(m.args.expectFormat)}. Consider using the ${h.warn(m.args.expectExtension)} extension, e.g. ${h.bold(replaceLast(relativePath, ".js", m.args.expectExtension))}`;
|
|
59
|
+
}
|
|
60
|
+
case "FILE_INVALID_EXPLICIT_FORMAT": {
|
|
61
|
+
const relativePath = m.args.actualFilePath ?? pv(m.path);
|
|
62
|
+
let start = "";
|
|
63
|
+
if (opts.reference || m.path[0] === "name") start = h.bold(relativePath);
|
|
64
|
+
else {
|
|
65
|
+
const is = pv(m.path).includes("*") ? "matches" : "is";
|
|
66
|
+
start = `${h.bold(formatMessagePath(m.path))} ${is} ${h.bold(relativePath)} and`;
|
|
67
|
+
}
|
|
68
|
+
return `${start} ends with the ${h.warn(m.args.actualExtension)} extension, but the code is written in ${h.warn(m.args.actualFormat)}. Consider using the ${h.warn(m.args.expectExtension)} extension, e.g. ${h.bold(replaceLast(relativePath, m.args.actualExtension, m.args.expectExtension))}`;
|
|
69
|
+
}
|
|
70
|
+
case "FILE_INVALID_JSX_EXTENSION": {
|
|
71
|
+
const relativePath = m.args.globbedFilePath ?? pv(m.path);
|
|
72
|
+
let start = "";
|
|
73
|
+
if (opts.reference || m.path[0] === "name") start = h.bold(relativePath);
|
|
74
|
+
else {
|
|
75
|
+
const is = m.args.globbedFilePath ? "matches" : "is";
|
|
76
|
+
start = `${h.bold(formatMessagePath(m.path))} ${is} ${h.bold(relativePath)} and`;
|
|
77
|
+
}
|
|
78
|
+
return `${start} uses an invalid ${h.bold(m.args.actualExtension)} extension. You don't need to split ESM and CJS formats for JSX. You should write a single file in ESM with the ${h.bold(".jsx")} extension instead, e.g. ${h.bold(replaceLast(pv(m.path), m.args.actualExtension, ".jsx"))}`;
|
|
79
|
+
}
|
|
80
|
+
case "FILE_DOES_NOT_EXIST": if (opts.reference) return `File does not exist`;
|
|
81
|
+
else {
|
|
82
|
+
let value = pv(m.path);
|
|
83
|
+
if (value === EMPTY_MSG && m.path[0] === "main") value += " (implies index.js)";
|
|
84
|
+
return `${h.bold(formatMessagePath(m.path))} is ${h.bold(value)} but the file does not exist.`;
|
|
85
|
+
}
|
|
86
|
+
case "FILE_NOT_PUBLISHED": if (opts.reference) return `File is not published. Is it specified in ${h.bold("pkg.files")}?`;
|
|
87
|
+
else return `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} but the file is not published. Is it specified in ${h.bold("pkg.files")}?`;
|
|
88
|
+
case "HAS_ESM_MAIN_BUT_NO_EXPORTS": return `${h.bold("pkg.main")} is an ESM file, but it is usually better to use ${h.bold("pkg.exports")} instead. If you don't support Node.js 12.6 and below, you can also remove ${h.bold("pkg.main")}. (This will be a breaking change)`;
|
|
89
|
+
case "HAS_MODULE_BUT_NO_EXPORTS": return `${h.bold("pkg.module")} is used to output ESM, but ${h.bold("pkg.exports")} is not defined. As Node.js doesn't read ${h.bold("pkg.module")}, the ESM output may be skipped. Consider adding ${h.bold("pkg.exports")} to export the ESM output. ${h.bold("pkg.module")} can usually be removed alongside too. (This will be a breaking change)`;
|
|
90
|
+
case "MODULE_SHOULD_BE_ESM":
|
|
91
|
+
case "EXPORTS_MODULE_SHOULD_BE_ESM":
|
|
92
|
+
case "IMPORTS_MODULE_SHOULD_BE_ESM": return `${opts.reference ? "Should" : `${h.bold(formatMessagePath(m.path))} should`} be ESM, but the code is written in CJS.`;
|
|
93
|
+
case "EXPORTS_GLOB_NO_MATCHED_FILES":
|
|
94
|
+
case "IMPORTS_GLOB_NO_MATCHED_FILES": return `${opts.reference ? "Does" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} but does`} not match any files.`;
|
|
95
|
+
case "EXPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING":
|
|
96
|
+
case "IMPORTS_GLOB_NO_DEPRECATED_SUBPATH_MAPPING": return `${h.bold(formatMessagePath(m.path))} maps to a path that ends with ${h.bold("/")} which is a removed feature. Use ${h.bold(formatMessagePath(m.args.expectPath))}: "${h.bold(m.args.expectValue)}" instead.`;
|
|
97
|
+
case "EXPORTS_TYPES_SHOULD_BE_FIRST": return `${opts.reference ? "Should" : `${h.bold(formatMessagePath(m.path))} should`} be the first in the object as conditions are order-sensitive so it can be resolved by TypeScript.`;
|
|
98
|
+
case "EXPORTS_MODULE_SHOULD_PRECEDE_REQUIRE":
|
|
99
|
+
case "IMPORTS_MODULE_SHOULD_PRECEDE_REQUIRE": return `${opts.reference ? "Should" : `${h.bold(formatMessagePath(m.path))} should`} come before the "require" condition so it can take precedence when used by a bundler.`;
|
|
100
|
+
case "EXPORTS_DEFAULT_SHOULD_BE_LAST":
|
|
101
|
+
case "IMPORTS_DEFAULT_SHOULD_BE_LAST": return `${opts.reference ? "Should" : `${h.bold(formatMessagePath(m.path))} should`} be the last in the object so it doesn't take precedence over the keys following it.`;
|
|
102
|
+
case "EXPORTS_VALUE_INVALID":
|
|
103
|
+
case "IMPORTS_VALUE_INVALID": return `${opts.reference ? h.bold(pv(m.path)) : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} but`} is invalid as it does not start with "${h.bold("./")}". Use ${h.bold(m.args.suggestValue)} instead.`;
|
|
104
|
+
case "EXPORTS_FALLBACK_ARRAY_USE":
|
|
105
|
+
case "IMPORTS_FALLBACK_ARRAY_USE": return `${opts.reference ? "The value" : h.bold(formatMessagePath(m.path))} uses fallback arrays which is not recommended. It picks the first value that can be parsed and does not have a use case in Node.js currently. It also works differently in some tools and may face inconsistent behaviors.`;
|
|
106
|
+
case "EXPORTS_MISSING_ROOT_ENTRYPOINT": {
|
|
107
|
+
const mainField = m.args.mainFields[0];
|
|
108
|
+
return `${opts.reference ? "The root entrypoint is missing" : `${h.bold(formatMessagePath(m.path))} is missing the root entrypoint export`}, which is defined in ${h.bold("pkg." + mainField)}. Environments that support the ${h.bold("\"exports\"")} field will ignore ${h.bold("pkg." + mainField)} as ${h.bold("\"exports\"")} takes the highest priority. Consider adding ${h.bold(formatMessagePath(m.path.concat(".")))}: "${h.bold(pv([mainField]))}".`;
|
|
109
|
+
}
|
|
110
|
+
case "USE_EXPORTS_BROWSER": return `${h.bold("pkg.browser")} with a string value can be refactored to use ${h.bold("pkg.exports")} and the ${h.bold("\"browser\"")} condition to declare browser-specific exports. e.g. ${h.bold("pkg.exports[\".\"].browser")}: "${h.bold(pv(m.path))}". (This will be a breaking change)`;
|
|
111
|
+
case "USE_EXPORTS_OR_IMPORTS_BROWSER": return `${h.bold("pkg.browser")} with an object value can be refactored to use ${h.bold("pkg.exports")}/${h.bold("pkg.imports")} and the ${h.bold("\"browser\"")} condition to declare browser-specific exports. (This will be a breaking change)`;
|
|
112
|
+
case "USE_FILES": return `The package ${h.bold("publishes internal tests or config files")}. You can use ${h.bold("pkg.files")} to only publish certain files and save user bandwidth.`;
|
|
113
|
+
case "USE_TYPE": return `The package does not specify the ${h.bold("\"type\"")} field. Node.js may attempt to detect the package type causing a small performance hit. Consider adding ${h.bold("\"type\"")}: "${h.bold("commonjs")}".`;
|
|
114
|
+
case "USE_LICENSE": return `The package does not specify the ${h.bold("\"license\"")} field but a license file was detected at ${h.bold(m.args.licenseFilePath)}. Consider adding a ${h.bold("\"license\"")} field so it's displayed on npm.`;
|
|
115
|
+
case "TYPES_NOT_EXPORTED": {
|
|
116
|
+
const typesFilePath = exportsRel(m.args.typesFilePath);
|
|
117
|
+
const start = opts.reference ? "The" : h.bold(formatMessagePath(m.path));
|
|
118
|
+
if (m.args.actualExtension && m.args.expectExtension) return `${start} types is not exported. Consider adding ${h.bold(formatMessagePath(m.path) + ".types")} to be compatible with TypeScript's ${h.bold("\"moduleResolution\": \"bundler\"")} compiler option. Note that you cannot use "${h.bold(typesFilePath)}" because it has a mismatching format. Instead, you can duplicate the file and use the ${h.bold(m.args.expectExtension)} extension, e.g. ${h.bold(formatMessagePath(m.path) + ".types")}: "${h.bold(replaceLast(typesFilePath, m.args.actualExtension, m.args.expectExtension))}"`;
|
|
119
|
+
else return `${start} types is not exported. Consider adding ${h.bold(formatMessagePath(m.path) + ".types")}: "${h.bold(typesFilePath)}" to be compatible with TypeScript's ${h.bold("\"moduleResolution\": \"bundler\"")} compiler option.`;
|
|
120
|
+
}
|
|
121
|
+
case "EXPORTS_TYPES_INVALID_FORMAT": {
|
|
122
|
+
let additionalMessage = "";
|
|
123
|
+
if (m.args.expectFormat === "ESM" && m.args.actualFormat === "CJS") additionalMessage = `This causes the types to be ambiguous when default importing the package due to its implied interop. `;
|
|
124
|
+
else if (m.args.expectFormat === "CJS" && m.args.actualFormat === "ESM") additionalMessage = `This causes the types to only work when dynamically importing the package, even though the package exports CJS. `;
|
|
125
|
+
return `${opts.reference ? "The" : h.bold(formatMessagePath(m.path))} types is interpreted as ${m.args.actualFormat} when resolving with the "${h.bold(m.args.condition)}" condition. ` + additionalMessage + `Consider splitting out two ${h.bold("\"types\"")} conditions for ${h.bold("\"import\"")} and ${h.bold("\"require\"")}, and use the ${h.warn(m.args.expectExtension)} extension, e.g. ${h.bold(formatMessagePath(m.args.expectPath))}: "${h.bold(replaceLast(pv(m.path), m.args.actualExtension, m.args.expectExtension))}"`;
|
|
126
|
+
}
|
|
127
|
+
case "FIELD_INVALID_VALUE_TYPE": {
|
|
128
|
+
let expectStr = m.args.expectTypes[0];
|
|
129
|
+
for (let i = 1; i < m.args.expectTypes.length; i++) if (i === m.args.expectTypes.length - 1) expectStr += ` or ${m.args.expectTypes[i]}`;
|
|
130
|
+
else expectStr += `, ${m.args.expectTypes[i]}`;
|
|
131
|
+
return `${opts.reference ? "The field value has" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} which is`} an invalid ${h.bold(m.args.actualType)} type. Expected a ${h.bold(expectStr)} type instead.`;
|
|
132
|
+
}
|
|
133
|
+
case "EXPORTS_VALUE_CONFLICTS_WITH_BROWSER": return `${opts.reference ? `${h.bold(pv(m.path))} matches` : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} which also matches`} ${h.bold(formatMessagePath(m.args.browserPath))}: "${h.bold(pv(m.args.browserPath))}", which overrides the path when building the library with the "${h.bold(m.args.browserishCondition)}" condition. This is usually unintentional and may cause build issues. Consider using a different file name for ${h.bold(pv(m.path))}.`;
|
|
134
|
+
case "DEPRECATED_FIELD_JSNEXT": return `${h.bold(formatMessagePath(m.path))} is deprecated. ${h.bold("pkg.module")} should be used instead.`;
|
|
135
|
+
case "INVALID_REPOSITORY_VALUE": switch (m.args.type) {
|
|
136
|
+
case "invalid-string-shorthand": return `${opts.reference ? "The field value" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} which`} isn't a valid shorthand value supported by npm. Consider using an object that references a repository.`;
|
|
137
|
+
case "invalid-git-url": return `${opts.reference ? "The field value" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} which`} isn't a valid git URL. A valid git URL is usually in the form of "${h.bold("git+https://example.com/user/repo.git")}".`;
|
|
138
|
+
case "deprecated-github-git-protocol": return `${opts.reference ? "The field value" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} which`} uses the git:// protocol that is deprecated by GitHub due to security concerns. Consider replacing the protocol with https://.`;
|
|
139
|
+
case "shorthand-git-sites": return `${opts.reference ? "The field value" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} but`} could be a full git URL like "${h.bold(m.args.suggestValue)}".`;
|
|
140
|
+
}
|
|
141
|
+
case "LOCAL_DEPENDENCY": if (opts.reference) return `This dependency references a local package that will likely not work when installed by end-users.`;
|
|
142
|
+
else return `The "${h.bold(m.path[m.path.length - 1])}" dependency references "${h.bold(pv(m.path))}" that will likely not work when installed by end-users.`;
|
|
143
|
+
case "BIN_FILE_NOT_EXECUTABLE": return `${opts.reference ? "This bin file" : `${h.bold(formatMessagePath(m.path))} is ${h.bold(pv(m.path))} but the file`} is not executable. It should start with a shebang, e.g. ${h.bold("#!/usr/bin/env node")}.`;
|
|
144
|
+
case "IMPORTS_KEY_INVALID": return `${opts.reference ? `The imports key is invalid as it` : `${h.bold(formatMessagePath(m.path))} is invalid as the imports key`} does not start with "${h.bold("#")}". Use ${h.bold(m.args.suggestKey)} instead.`;
|
|
145
|
+
case "CJS_WITH_ESMODULE_DEFAULT_EXPORT": return `${m.path[0] === "name" && m.args.filePath ? h.bold(m.args.filePath) : opts.reference ? "This file" : `${h.bold(formatMessagePath(m.path))}`} sets both ${h.bold("exports.__esModule = true")} and ${h.bold("exports.default")}. This pattern breaks default imports when importing from an ESM-interpreted file in some bundlers. Consider using ESM syntax instead of CommonJS with ${h.bold("__esModule")} or avoid the default export.`;
|
|
146
|
+
default: return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/** @type { import('picocolors/types.js').Colors | undefined } */
|
|
150
|
+
let _picocolorsWithForcedColor;
|
|
151
|
+
/**
|
|
152
|
+
* @param {import('../utils.js').FormatMessageOptions['color']} color
|
|
153
|
+
*/
|
|
154
|
+
function getHighlighter(color) {
|
|
155
|
+
/** @type {(s: string) => string} */
|
|
156
|
+
let bold;
|
|
157
|
+
/** @type {(s: string) => string} */
|
|
158
|
+
let warn;
|
|
159
|
+
switch (color) {
|
|
160
|
+
case "html":
|
|
161
|
+
bold = (s) => `<strong>${s}</strong>`;
|
|
162
|
+
warn = (s) => `<strong>${s}</strong>`;
|
|
163
|
+
break;
|
|
164
|
+
case true:
|
|
165
|
+
_picocolorsWithForcedColor ??= import_picocolors.default.createColors(true);
|
|
166
|
+
bold = (s) => _picocolorsWithForcedColor.bold(s);
|
|
167
|
+
warn = (s) => _picocolorsWithForcedColor.yellow(s);
|
|
168
|
+
break;
|
|
169
|
+
case false:
|
|
170
|
+
bold = (s) => s;
|
|
171
|
+
warn = (s) => s;
|
|
172
|
+
break;
|
|
173
|
+
default:
|
|
174
|
+
bold = (s) => import_picocolors.default.bold(s);
|
|
175
|
+
warn = (s) => import_picocolors.default.yellow(s);
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
bold,
|
|
180
|
+
warn
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Make sure s is an `"exports"` compatible relative path
|
|
185
|
+
* @param {string} s
|
|
186
|
+
*/
|
|
187
|
+
function exportsRel(s) {
|
|
188
|
+
if (s[0] === ".") return s;
|
|
189
|
+
if (s[0] === "/") return "." + s;
|
|
190
|
+
return "./" + s;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
//#endregion
|
|
194
|
+
export { formatMessage, formatMessagePath, getPkgPathValue };
|