create-koishi-ce 1.0.0 → 1.0.1
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/lib/bin.mjs +1 -1
- package/lib/index.d.ts +15 -1
- package/lib/index.mjs +2 -2
- package/lib/{src-D9XdTOrE.mjs → src-B_s70NbL.mjs} +32 -5
- package/package.json +1 -2
- package/src/__tests__/registry.test.ts +54 -0
- package/src/index.ts +44 -2
package/lib/bin.mjs
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -17,6 +17,20 @@ interface Manifest {
|
|
|
17
17
|
* 本 CLI 自身以 bun 为运行时(bin shebang),能执行即已具备 bun 环境。
|
|
18
18
|
*/
|
|
19
19
|
declare function detectAgent(): string;
|
|
20
|
+
/**
|
|
21
|
+
* 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
|
|
22
|
+
* 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
|
|
23
|
+
*/
|
|
24
|
+
declare function readNpmrcRegistry(file: string): string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
|
|
27
|
+
* .npmrc > 用户 ~/.npmrc)。刻意不 spawn 子进程探测——既有实现按
|
|
28
|
+
* user-agent 选 `bun config get registry`,而 Bun 没有 config 子命令,
|
|
29
|
+
* bunx 场景下子进程退出码 1 直接炸掉脚手架;读 npmrc 是零依赖、零
|
|
30
|
+
* 子进程的等价路径。任何一步都拿不到时返回 undefined,由调用方回落
|
|
31
|
+
* 官方源。
|
|
32
|
+
*/
|
|
33
|
+
declare function getLocalRegistry(cwd?: string, userHome?: string): string | undefined;
|
|
20
34
|
/**
|
|
21
35
|
* 改写模板的 package.json(纯函数,导出供单测):替换项目名、标记
|
|
22
36
|
* private、版本归零。
|
|
@@ -28,4 +42,4 @@ declare function renderManifest(source: Manifest, project: string, prod: boolean
|
|
|
28
42
|
*/
|
|
29
43
|
declare function start(): Promise<void>;
|
|
30
44
|
//#endregion
|
|
31
|
-
export { Manifest, detectAgent, renderManifest, start };
|
|
45
|
+
export { Manifest, detectAgent, getLocalRegistry, readNpmrcRegistry, renderManifest, start };
|
package/lib/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { detectAgent, renderManifest, start };
|
|
1
|
+
import { a as start, i as renderManifest, n as getLocalRegistry, r as readNpmrcRegistry, t as detectAgent } from "./src-B_s70NbL.mjs";
|
|
2
|
+
export { detectAgent, getLocalRegistry, readNpmrcRegistry, renderManifest, start };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { spawnSync } from "node:child_process";
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
3
4
|
import { basename, join, relative } from "node:path";
|
|
4
5
|
import { Readable } from "node:stream";
|
|
5
|
-
import getRegistry from "get-registry";
|
|
6
6
|
import kleur from "kleur";
|
|
7
7
|
import prompts from "prompts";
|
|
8
8
|
import { extract } from "tar";
|
|
@@ -23,7 +23,7 @@ import parse from "yargs-parser";
|
|
|
23
23
|
const { version } = {
|
|
24
24
|
name: "create-koishi-ce",
|
|
25
25
|
description: "Setup a Koishi application",
|
|
26
|
-
version: "1.0.
|
|
26
|
+
version: "1.0.1",
|
|
27
27
|
type: "module",
|
|
28
28
|
main: "./lib/index.mjs",
|
|
29
29
|
module: "./lib/index.mjs",
|
|
@@ -57,7 +57,6 @@ const { version } = {
|
|
|
57
57
|
"@types/yargs-parser": "^21.0.3"
|
|
58
58
|
},
|
|
59
59
|
dependencies: {
|
|
60
|
-
"get-registry": "^1.1.0",
|
|
61
60
|
"kleur": "^4.1.5",
|
|
62
61
|
"prompts": "^2.4.2",
|
|
63
62
|
"tar": "^7.5.22",
|
|
@@ -108,6 +107,34 @@ function detectAgent() {
|
|
|
108
107
|
if (ua.startsWith("pnpm")) return "pnpm";
|
|
109
108
|
return "bun";
|
|
110
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
|
|
112
|
+
* 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
|
|
113
|
+
*/
|
|
114
|
+
function readNpmrcRegistry(file) {
|
|
115
|
+
try {
|
|
116
|
+
for (const line of readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
117
|
+
const value = /^\s*registry\s*=\s*(\S+)\s*$/.exec(line)?.[1];
|
|
118
|
+
if (value) return value;
|
|
119
|
+
}
|
|
120
|
+
} catch {}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
|
|
124
|
+
* .npmrc > 用户 ~/.npmrc)。刻意不 spawn 子进程探测——既有实现按
|
|
125
|
+
* user-agent 选 `bun config get registry`,而 Bun 没有 config 子命令,
|
|
126
|
+
* bunx 场景下子进程退出码 1 直接炸掉脚手架;读 npmrc 是零依赖、零
|
|
127
|
+
* 子进程的等价路径。任何一步都拿不到时返回 undefined,由调用方回落
|
|
128
|
+
* 官方源。
|
|
129
|
+
*/
|
|
130
|
+
function getLocalRegistry(cwd = process.cwd(), userHome = homedir()) {
|
|
131
|
+
const candidates = [
|
|
132
|
+
process.env["npm_config_registry"],
|
|
133
|
+
readNpmrcRegistry(join(cwd, ".npmrc")),
|
|
134
|
+
readNpmrcRegistry(join(userHome, ".npmrc"))
|
|
135
|
+
];
|
|
136
|
+
for (const candidate of candidates) if (candidate?.startsWith("https://") || candidate?.startsWith("http://")) return candidate;
|
|
137
|
+
}
|
|
111
138
|
/** 静默执行命令探测其是否可用(如 git --version),失败即视为不可用 */
|
|
112
139
|
function supports(command) {
|
|
113
140
|
return spawnSync(command[0] ?? "", command.slice(1), { stdio: "ignore" }).status === 0;
|
|
@@ -199,7 +226,7 @@ function writePackageJson() {
|
|
|
199
226
|
*/
|
|
200
227
|
async function scaffold() {
|
|
201
228
|
console.log(kleur.dim(" 正在 ") + project + kleur.dim(" 中生成项目 ..."));
|
|
202
|
-
const registry = (argv.registry ||
|
|
229
|
+
const registry = (argv.registry || getLocalRegistry() || "https://registry.npmjs.org").replace(/\/$/, "");
|
|
203
230
|
console.log(kleur.dim(` 使用 registry:${registry}\n`));
|
|
204
231
|
const template = argv.template || "@koishijs/boilerplate";
|
|
205
232
|
const ref = argv.ref || "latest";
|
|
@@ -309,4 +336,4 @@ async function start() {
|
|
|
309
336
|
await install();
|
|
310
337
|
}
|
|
311
338
|
//#endregion
|
|
312
|
-
export { renderManifest as n,
|
|
339
|
+
export { start as a, renderManifest as i, getLocalRegistry as n, readNpmrcRegistry as r, detectAgent as t };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-koishi-ce",
|
|
3
3
|
"description": "Setup a Koishi application",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.mjs",
|
|
7
7
|
"module": "./lib/index.mjs",
|
|
@@ -47,7 +47,6 @@
|
|
|
47
47
|
"@types/yargs-parser": "^21.0.3"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"get-registry": "^1.1.0",
|
|
51
50
|
"kleur": "^4.1.5",
|
|
52
51
|
"prompts": "^2.4.2",
|
|
53
52
|
"tar": "^7.5.22",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { expect, test } from "bun:test";
|
|
2
|
+
import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { getLocalRegistry, readNpmrcRegistry } from "../index.ts";
|
|
6
|
+
|
|
7
|
+
test("readNpmrcRegistry:提取首个 registry= 行,忽略注释与空行", () => {
|
|
8
|
+
const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
|
|
9
|
+
const file = join(dir, ".npmrc");
|
|
10
|
+
writeFileSync(
|
|
11
|
+
file,
|
|
12
|
+
"# 注释行\n; 另一种注释\n\nstrict-ssl=false\nregistry=https://registry.npmmirror.com/\r\n@scope:registry=https://example.com/\n",
|
|
13
|
+
);
|
|
14
|
+
expect(readNpmrcRegistry(file)).toBe("https://registry.npmmirror.com/");
|
|
15
|
+
rmSync(dir, { recursive: true, force: true });
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
test("readNpmrcRegistry:文件不存在或未配置时返回 undefined 而不抛错", () => {
|
|
19
|
+
expect(
|
|
20
|
+
readNpmrcRegistry(join(tmpdir(), "ckc-不存在", ".npmrc")),
|
|
21
|
+
).toBeUndefined();
|
|
22
|
+
const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
|
|
23
|
+
const file = join(dir, ".npmrc");
|
|
24
|
+
writeFileSync(file, "strict-ssl=false\n");
|
|
25
|
+
expect(readNpmrcRegistry(file)).toBeUndefined();
|
|
26
|
+
rmSync(dir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("getLocalRegistry:环境变量优先且校验协议,非法值跳过", () => {
|
|
30
|
+
const key = "npm_config_registry";
|
|
31
|
+
const isolated = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
|
|
32
|
+
process.env[key] = "https://registry.example.com/";
|
|
33
|
+
expect(getLocalRegistry(isolated, isolated)).toBe(
|
|
34
|
+
"https://registry.example.com/",
|
|
35
|
+
);
|
|
36
|
+
// 非 http(s) 的值视为未配置,继续走后续候选
|
|
37
|
+
process.env[key] = "ftp://not-a-registry/";
|
|
38
|
+
expect(getLocalRegistry(isolated, isolated)).toBeUndefined();
|
|
39
|
+
delete process.env[key];
|
|
40
|
+
rmSync(isolated, { recursive: true, force: true });
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("getLocalRegistry:项目 .npmrc 优先于用户级 .npmrc,均无配置时返回 undefined", () => {
|
|
44
|
+
const key = "npm_config_registry";
|
|
45
|
+
delete process.env[key];
|
|
46
|
+
const dir = mkdtempSync(join(tmpdir(), "ckc-npmrc-"));
|
|
47
|
+
const emptyHome = mkdtempSync(join(tmpdir(), "ckc-home-"));
|
|
48
|
+
writeFileSync(join(dir, ".npmrc"), "registry=http://localhost:4873/\n");
|
|
49
|
+
expect(getLocalRegistry(dir, emptyHome)).toBe("http://localhost:4873/");
|
|
50
|
+
// 目录与用户级均无 .npmrc 时返回 undefined,主流程回落官方源
|
|
51
|
+
expect(getLocalRegistry(emptyHome, emptyHome)).toBeUndefined();
|
|
52
|
+
rmSync(dir, { recursive: true, force: true });
|
|
53
|
+
rmSync(emptyHome, { recursive: true, force: true });
|
|
54
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -18,10 +18,10 @@ import {
|
|
|
18
18
|
rmSync,
|
|
19
19
|
writeFileSync,
|
|
20
20
|
} from "node:fs";
|
|
21
|
+
import { homedir } from "node:os";
|
|
21
22
|
import { basename, join, relative } from "node:path";
|
|
22
23
|
import { Readable } from "node:stream";
|
|
23
24
|
import type { ReadableStream as NodeWebReadableStream } from "node:stream/web";
|
|
24
|
-
import getRegistry from "get-registry";
|
|
25
25
|
import kleur from "kleur";
|
|
26
26
|
import prompts from "prompts";
|
|
27
27
|
import { extract } from "tar";
|
|
@@ -106,6 +106,48 @@ export function detectAgent(): string {
|
|
|
106
106
|
return "bun";
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
/**
|
|
110
|
+
* 从单个 .npmrc 文件提取 registry 配置项(非注释、非 scoped 的 registry= 行)。
|
|
111
|
+
* 文件不存在或未配置时返回 undefined,读文件异常一律静默吞掉。
|
|
112
|
+
*/
|
|
113
|
+
export function readNpmrcRegistry(file: string): string | undefined {
|
|
114
|
+
try {
|
|
115
|
+
for (const line of readFileSync(file, "utf8").split(/\r?\n/)) {
|
|
116
|
+
const matched = /^\s*registry\s*=\s*(\S+)\s*$/.exec(line);
|
|
117
|
+
const value = matched?.[1];
|
|
118
|
+
if (value) return value;
|
|
119
|
+
}
|
|
120
|
+
} catch {
|
|
121
|
+
// registry 探测不允许打断主流程,任何读取失败都视为未配置
|
|
122
|
+
}
|
|
123
|
+
return undefined;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 读取本机 npm registry 配置(优先级对齐 npm 自身:环境变量 > 项目
|
|
128
|
+
* .npmrc > 用户 ~/.npmrc)。刻意不 spawn 子进程探测——既有实现按
|
|
129
|
+
* user-agent 选 `bun config get registry`,而 Bun 没有 config 子命令,
|
|
130
|
+
* bunx 场景下子进程退出码 1 直接炸掉脚手架;读 npmrc 是零依赖、零
|
|
131
|
+
* 子进程的等价路径。任何一步都拿不到时返回 undefined,由调用方回落
|
|
132
|
+
* 官方源。
|
|
133
|
+
*/
|
|
134
|
+
export function getLocalRegistry(
|
|
135
|
+
cwd: string = process.cwd(),
|
|
136
|
+
userHome: string = homedir(),
|
|
137
|
+
): string | undefined {
|
|
138
|
+
const candidates = [
|
|
139
|
+
process.env["npm_config_registry"],
|
|
140
|
+
readNpmrcRegistry(join(cwd, ".npmrc")),
|
|
141
|
+
readNpmrcRegistry(join(userHome, ".npmrc")),
|
|
142
|
+
];
|
|
143
|
+
for (const candidate of candidates) {
|
|
144
|
+
if (candidate?.startsWith("https://") || candidate?.startsWith("http://")) {
|
|
145
|
+
return candidate;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
}
|
|
150
|
+
|
|
109
151
|
/** 静默执行命令探测其是否可用(如 git --version),失败即视为不可用 */
|
|
110
152
|
function supports(command: readonly string[]) {
|
|
111
153
|
return (
|
|
@@ -220,7 +262,7 @@ async function scaffold() {
|
|
|
220
262
|
|
|
221
263
|
const registry = (
|
|
222
264
|
argv.registry ||
|
|
223
|
-
(
|
|
265
|
+
getLocalRegistry() ||
|
|
224
266
|
"https://registry.npmjs.org"
|
|
225
267
|
).replace(/\/$/, "");
|
|
226
268
|
console.log(kleur.dim(` 使用 registry:${registry}\n`));
|