vite-plus 0.2.8 → 0.2.9
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/AGENTS.md +7 -0
- package/README.md +9 -3
- package/binding/index.cjs +54 -54
- package/binding/index.d.cts +7 -3
- package/dist/{agent-CI79DuSy.js → agent-DQU8uS6P.js} +4 -188
- package/dist/bin.js +288 -278
- package/dist/config/bin.js +27 -15
- package/dist/{constants-BppDcRc1.js → constants-CG513DRa.js} +10 -2
- package/dist/create/bin.js +178 -204
- package/dist/{define-config-DPnHe1Mx.js → define-config-CV4bQG_8.js} +3 -3
- package/dist/{define-config-CEm_MtvJ.cjs → define-config-DyNLA_f0.cjs} +1 -1
- package/dist/define-config.cjs +1 -1
- package/dist/define-config.js +1 -1
- package/dist/{dist-CSQWHI6y.js → dist-BDYZP12R.js} +193 -149
- package/dist/dist-Dqv1-Clg.js +3 -0
- package/dist/{editor-CGWdbLgD.js → editor-g4PosU99.js} +188 -108
- package/dist/hooks/bin.d.ts +1 -0
- package/dist/hooks/bin.js +130 -0
- package/dist/hooks-pNCBWtFT.js +570 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{json-BU88uu6o.js → json-qlK6UH0r.js} +38 -32
- package/dist/migration/bin.js +15 -18
- package/dist/{oxlint-plugin-config-BHOzlwMw.js → oxlint-plugin-config-BEZ9IUf7.js} +1 -1
- package/dist/oxlint-plugin.js +1 -1
- package/dist/pack-bin.js +1 -1
- package/dist/{package-hV-77cBb.js → package-B4T8RGMG.js} +2 -2
- package/dist/{prompts-DYap08te.js → prompts-CHz_98bJ.js} +142 -50
- package/dist/{resolve-vite-config-EWXclqvV.js → resolve-vite-config-Dmeyeyj-.js} +2 -9
- package/dist/staged/bin.js +224 -206
- package/dist/{terminal-CrqqK8WT.js → terminal-Bz-ps6rJ.js} +33 -3
- package/dist/test/browser/providers/playwright/context.d.ts +1 -1
- package/dist/test/browser/providers/playwright.d.ts +6 -6
- package/dist/test/browser/providers/preview/context.d.ts +1 -1
- package/dist/test/browser/providers/preview.d.ts +4 -4
- package/dist/test/browser/providers/webdriverio/context.d.ts +1 -1
- package/dist/test/browser/providers/webdriverio.d.ts +6 -6
- package/dist/test/browser-playwright/context.d.ts +1 -1
- package/dist/test/browser-playwright.d.ts +6 -6
- package/dist/test/browser-preview/context.d.ts +1 -1
- package/dist/test/browser-preview.d.ts +4 -4
- package/dist/test/browser-webdriverio/context.d.ts +1 -1
- package/dist/test/browser-webdriverio.d.ts +6 -6
- package/dist/test/context.d.ts +3 -3
- package/dist/test/locators.d.ts +1 -1
- package/dist/toolchain.d.ts +25 -0
- package/dist/toolchain.js +194 -0
- package/dist/toolchain.json +193 -0
- package/dist/{tsconfig-CVUKLfL8.js → tsconfig-7v_BHagU.js} +3 -3
- package/dist/tsgolint-path.js +1 -1
- package/dist/version.js +4 -4
- package/dist/versions.d.ts +3 -3
- package/dist/versions.js +6 -6
- package/docs/guide/ci.md +37 -4
- package/docs/guide/commit-hooks.md +87 -14
- package/docs/guide/create.md +7 -4
- package/docs/guide/fmt.md +2 -2
- package/docs/guide/github-actions-cache.md +5 -1
- package/docs/guide/ide-integration.md +61 -2
- package/docs/guide/index.md +3 -1
- package/docs/guide/install.md +25 -0
- package/docs/guide/installer-env-vars.md +12 -1
- package/docs/guide/lint.md +3 -1
- package/docs/guide/migrate.md +39 -2
- package/docs/guide/monorepo.md +4 -4
- package/docs/guide/troubleshooting.md +12 -4
- package/docs/guide/upgrade.md +27 -4
- package/docs/package.json +1 -1
- package/docs/pnpm-workspace.yaml +7 -0
- package/docs/vite.config.ts +3 -0
- package/package.json +18 -14
- package/rules/vite-tools.yml +0 -7
- package/dist/dist-DT25H9pj.js +0 -3
- package/dist/{tsgolint-path-eMZT-oea.js → tsgolint-path-CbDReEOx.js} +1 -1
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
2
|
+
import { chmodSync, existsSync, lstatSync, mkdirSync, readdirSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
//#region src/config/hooks.ts
|
|
5
|
+
const SUPPORTED_GIT_HOOK_NAMES = [
|
|
6
|
+
"pre-commit",
|
|
7
|
+
"pre-merge-commit",
|
|
8
|
+
"prepare-commit-msg",
|
|
9
|
+
"commit-msg",
|
|
10
|
+
"post-commit",
|
|
11
|
+
"applypatch-msg",
|
|
12
|
+
"pre-applypatch",
|
|
13
|
+
"post-applypatch",
|
|
14
|
+
"pre-rebase",
|
|
15
|
+
"post-rewrite",
|
|
16
|
+
"post-checkout",
|
|
17
|
+
"post-merge",
|
|
18
|
+
"pre-push",
|
|
19
|
+
"pre-auto-gc"
|
|
20
|
+
];
|
|
21
|
+
const DEFAULT_HOOKS_DIR = ".vite-hooks";
|
|
22
|
+
/** Local git config: user chose `vp hooks disable` (survives prepare / vp config). */
|
|
23
|
+
const PREFERENCE_DISABLED_KEY = "vp.hooks.disabled";
|
|
24
|
+
/** Local git config: last hooks directory used by enable (relative to setup cwd). */
|
|
25
|
+
const PREFERENCE_DIR_KEY = "vp.hooks.dir";
|
|
26
|
+
/** Local git config: `git rev-parse --show-prefix` when the dir was stored. `.` = worktree root. */
|
|
27
|
+
const PREFERENCE_PREFIX_KEY = "vp.hooks.prefix";
|
|
28
|
+
const ROOT_PREFIX_TOKEN = ".";
|
|
29
|
+
function nestedDirname(depth) {
|
|
30
|
+
let expr = "\"$0\"";
|
|
31
|
+
for (let i = 0; i < depth; i++) expr = `"$(dirname ${expr})"`;
|
|
32
|
+
return expr;
|
|
33
|
+
}
|
|
34
|
+
function hookScript(dir) {
|
|
35
|
+
const separators = process.platform === "win32" ? /[\\/]/ : /\//;
|
|
36
|
+
return `#!/usr/bin/env sh
|
|
37
|
+
{ [ "$HUSKY" = "2" ] || [ "$VP_GIT_HOOKS" = "2" ] || [ "$VITE_GIT_HOOKS" = "2" ]; } && set -x
|
|
38
|
+
n=$(basename "$0")
|
|
39
|
+
s=$(dirname "$(dirname "$0")")/$n
|
|
40
|
+
|
|
41
|
+
[ ! -f "$s" ] && exit 0
|
|
42
|
+
|
|
43
|
+
i="\${XDG_CONFIG_HOME:-$HOME/.config}/vite-plus/hooks-init.sh"
|
|
44
|
+
[ ! -f "$i" ] && i="\${XDG_CONFIG_HOME:-$HOME/.config}/husky/init.sh"
|
|
45
|
+
[ -f "$i" ] && . "$i"
|
|
46
|
+
|
|
47
|
+
{ [ "\${HUSKY-}" = "0" ] || [ "\${VP_GIT_HOOKS-}" = "0" ] || [ "\${VITE_GIT_HOOKS-}" = "0" ]; } && exit 0
|
|
48
|
+
|
|
49
|
+
d=${nestedDirname(dir.split(separators).filter((s) => s !== "" && s !== ".").length + 2)}
|
|
50
|
+
__vp_shell=/bin/sh
|
|
51
|
+
[ -x "$__vp_shell" ] || __vp_shell=$(command -v sh)
|
|
52
|
+
|
|
53
|
+
if [ -n "\${VP_HOME-}" ]; then
|
|
54
|
+
__vp_bin="$VP_HOME/bin"
|
|
55
|
+
elif [ -n "\${HOME-}" ]; then
|
|
56
|
+
__vp_bin="$HOME/.vite-plus/bin"
|
|
57
|
+
else
|
|
58
|
+
__vp_bin=""
|
|
59
|
+
fi
|
|
60
|
+
[ -n "$__vp_bin" ] && [ -d "$__vp_bin" ] && export PATH="$PATH:$__vp_bin"
|
|
61
|
+
|
|
62
|
+
export PATH="$d/node_modules/.bin:$PATH"
|
|
63
|
+
"$__vp_shell" -e "$s" "$@"
|
|
64
|
+
c=$?
|
|
65
|
+
|
|
66
|
+
[ $c != 0 ] && echo "VITE+ - $n script failed (code $c)"
|
|
67
|
+
[ $c = 127 ] && echo "VITE+ - command not found in PATH=$PATH"
|
|
68
|
+
exit $c`;
|
|
69
|
+
}
|
|
70
|
+
function normalizeHooksPath(hooksPath) {
|
|
71
|
+
let normalized = normalize(hooksPath);
|
|
72
|
+
while (normalized.endsWith(sep)) normalized = normalized.slice(0, -1);
|
|
73
|
+
return normalized;
|
|
74
|
+
}
|
|
75
|
+
function getGitToplevel() {
|
|
76
|
+
const result = spawnSync("git", ["rev-parse", "--show-toplevel"]);
|
|
77
|
+
if (result.status == null) return {
|
|
78
|
+
message: "git command not found",
|
|
79
|
+
isError: true
|
|
80
|
+
};
|
|
81
|
+
if (result.status !== 0) return {
|
|
82
|
+
message: ".git can't be found",
|
|
83
|
+
isError: false
|
|
84
|
+
};
|
|
85
|
+
const toplevel = result.stdout.toString().trim();
|
|
86
|
+
try {
|
|
87
|
+
return realpathSync(toplevel);
|
|
88
|
+
} catch {
|
|
89
|
+
return toplevel;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/** Resolve a core.hooksPath value against the worktree root for ownership checks. */
|
|
93
|
+
function resolveHooksPath(hooksPath, gitRoot) {
|
|
94
|
+
const resolved = isAbsolute(hooksPath) ? hooksPath : resolve(gitRoot, hooksPath);
|
|
95
|
+
try {
|
|
96
|
+
return normalizeHooksPath(realpathSync(resolved));
|
|
97
|
+
} catch {
|
|
98
|
+
return normalizeHooksPath(resolved);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function hooksPathsEqual(a, b, gitRoot) {
|
|
102
|
+
return resolveHooksPath(a, gitRoot) === resolveHooksPath(b, gitRoot);
|
|
103
|
+
}
|
|
104
|
+
function findUnsafeHookInstallPath(root, dir) {
|
|
105
|
+
const projectRoot = resolve(root);
|
|
106
|
+
const internalPath = resolve(projectRoot, dir, "_");
|
|
107
|
+
const relativeInternalPath = relative(projectRoot, internalPath);
|
|
108
|
+
let currentPath = projectRoot;
|
|
109
|
+
for (const component of relativeInternalPath.split(sep).filter(Boolean)) {
|
|
110
|
+
currentPath = join(currentPath, component);
|
|
111
|
+
const stats = lstatSync(currentPath, { throwIfNoEntry: false });
|
|
112
|
+
if (!stats) return null;
|
|
113
|
+
if (stats.isSymbolicLink()) return {
|
|
114
|
+
kind: "symbolic",
|
|
115
|
+
relativePath: relative(projectRoot, currentPath)
|
|
116
|
+
};
|
|
117
|
+
if (!stats.isDirectory()) return {
|
|
118
|
+
kind: "not-directory",
|
|
119
|
+
relativePath: relative(projectRoot, currentPath)
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
for (const filename of [
|
|
123
|
+
"husky.sh",
|
|
124
|
+
".gitignore",
|
|
125
|
+
"h",
|
|
126
|
+
...SUPPORTED_GIT_HOOK_NAMES
|
|
127
|
+
]) {
|
|
128
|
+
const filePath = join(internalPath, filename);
|
|
129
|
+
const stats = lstatSync(filePath, { throwIfNoEntry: false });
|
|
130
|
+
if (!stats) continue;
|
|
131
|
+
if (stats.isSymbolicLink()) return {
|
|
132
|
+
kind: "symbolic",
|
|
133
|
+
relativePath: relative(projectRoot, filePath)
|
|
134
|
+
};
|
|
135
|
+
if (!stats.isFile()) return {
|
|
136
|
+
kind: "not-file",
|
|
137
|
+
relativePath: relative(projectRoot, filePath)
|
|
138
|
+
};
|
|
139
|
+
if (stats.nlink > 1) return {
|
|
140
|
+
kind: "linked",
|
|
141
|
+
relativePath: relative(projectRoot, filePath)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
function describeUnsafeHookInstallPath(unsafePath) {
|
|
147
|
+
if (unsafePath.kind === "symbolic") return `symbolic hook path "${unsafePath.relativePath}" not allowed`;
|
|
148
|
+
if (unsafePath.kind === "linked") return `multiply linked hook path "${unsafePath.relativePath}" not allowed`;
|
|
149
|
+
if (unsafePath.kind === "not-directory") return `hook path "${unsafePath.relativePath}" is not a directory`;
|
|
150
|
+
return `hook path "${unsafePath.relativePath}" is not a file`;
|
|
151
|
+
}
|
|
152
|
+
function gitConfigGet(key, options) {
|
|
153
|
+
const args = ["config"];
|
|
154
|
+
if (options?.local) args.push("--local");
|
|
155
|
+
if (options?.bool) args.push("--bool");
|
|
156
|
+
args.push("--get", key);
|
|
157
|
+
const result = spawnSync("git", args);
|
|
158
|
+
if (result.status !== 0) return null;
|
|
159
|
+
return result.stdout?.toString().trim() || null;
|
|
160
|
+
}
|
|
161
|
+
function gitConfigSet(key, value) {
|
|
162
|
+
const result = spawnSync("git", [
|
|
163
|
+
"config",
|
|
164
|
+
"--local",
|
|
165
|
+
key,
|
|
166
|
+
value
|
|
167
|
+
]);
|
|
168
|
+
if (result.status == null) return {
|
|
169
|
+
ok: false,
|
|
170
|
+
error: "git command not found"
|
|
171
|
+
};
|
|
172
|
+
if (result.status !== 0) return {
|
|
173
|
+
ok: false,
|
|
174
|
+
error: result.stderr?.toString().trim() || `failed to set ${key}`
|
|
175
|
+
};
|
|
176
|
+
return { ok: true };
|
|
177
|
+
}
|
|
178
|
+
function gitConfigUnset(key) {
|
|
179
|
+
const result = spawnSync("git", [
|
|
180
|
+
"config",
|
|
181
|
+
"--local",
|
|
182
|
+
"--unset-all",
|
|
183
|
+
key
|
|
184
|
+
]);
|
|
185
|
+
if (result.status == null) return {
|
|
186
|
+
ok: false,
|
|
187
|
+
error: "git command not found"
|
|
188
|
+
};
|
|
189
|
+
if (result.status !== 0 && result.status !== 5) return {
|
|
190
|
+
ok: false,
|
|
191
|
+
error: result.stderr?.toString().trim() || `failed to unset ${key}`
|
|
192
|
+
};
|
|
193
|
+
return { ok: true };
|
|
194
|
+
}
|
|
195
|
+
/** Whether the user ran `vp hooks disable` in this repo (local git config). */
|
|
196
|
+
function isHooksUserDisabled() {
|
|
197
|
+
return gitConfigGet(PREFERENCE_DISABLED_KEY, {
|
|
198
|
+
local: true,
|
|
199
|
+
bool: true
|
|
200
|
+
}) === "true";
|
|
201
|
+
}
|
|
202
|
+
function setHooksUserDisabled(disabled) {
|
|
203
|
+
if (disabled) return gitConfigSet(PREFERENCE_DISABLED_KEY, "true");
|
|
204
|
+
return gitConfigUnset(PREFERENCE_DISABLED_KEY);
|
|
205
|
+
}
|
|
206
|
+
function getStoredHooksDir() {
|
|
207
|
+
return gitConfigGet(PREFERENCE_DIR_KEY, { local: true });
|
|
208
|
+
}
|
|
209
|
+
function getStoredHooksPrefix() {
|
|
210
|
+
const value = gitConfigGet(PREFERENCE_PREFIX_KEY, { local: true });
|
|
211
|
+
if (value == null) return null;
|
|
212
|
+
if (value === ROOT_PREFIX_TOKEN) return "";
|
|
213
|
+
return value.replace(/\/$/, "");
|
|
214
|
+
}
|
|
215
|
+
function setStoredHooksLocation(dir, prefix) {
|
|
216
|
+
const storedDir = gitConfigSet(PREFERENCE_DIR_KEY, dir);
|
|
217
|
+
if (!storedDir.ok) return storedDir;
|
|
218
|
+
return gitConfigSet(PREFERENCE_PREFIX_KEY, prefix || ROOT_PREFIX_TOKEN);
|
|
219
|
+
}
|
|
220
|
+
function displayHooksDir(location) {
|
|
221
|
+
return location.prefix ? `${location.prefix}/${location.dir}` : location.dir;
|
|
222
|
+
}
|
|
223
|
+
function getGitWorktree() {
|
|
224
|
+
const toplevel = getGitToplevel();
|
|
225
|
+
if (typeof toplevel !== "string") return toplevel;
|
|
226
|
+
const prefixResult = spawnSync("git", ["rev-parse", "--show-prefix"]);
|
|
227
|
+
if (prefixResult.status == null) return {
|
|
228
|
+
message: "git command not found",
|
|
229
|
+
isError: true
|
|
230
|
+
};
|
|
231
|
+
if (prefixResult.status !== 0) return {
|
|
232
|
+
message: ".git can't be found",
|
|
233
|
+
isError: false
|
|
234
|
+
};
|
|
235
|
+
return {
|
|
236
|
+
toplevel,
|
|
237
|
+
prefix: prefixResult.stdout.toString().trim().replace(/\/$/, "")
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function buildHooksLocation(git, hooksDir, prefix) {
|
|
241
|
+
const dirError = validateHooksDir(hooksDir);
|
|
242
|
+
if (dirError) return dirError;
|
|
243
|
+
const baseDir = prefix ? resolve(git.toplevel, prefix) : git.toplevel;
|
|
244
|
+
const target = prefix ? `${prefix}/${hooksDir}/_` : `${hooksDir}/_`;
|
|
245
|
+
return {
|
|
246
|
+
toplevel: git.toplevel,
|
|
247
|
+
baseDir,
|
|
248
|
+
dir: hooksDir,
|
|
249
|
+
prefix,
|
|
250
|
+
target
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function tryAdoptEffectiveDispatcher(git) {
|
|
254
|
+
const existing = getEffectiveHooksPath();
|
|
255
|
+
if (!existing) return null;
|
|
256
|
+
const abs = isAbsolute(existing) ? existing : resolve(git.toplevel, existing);
|
|
257
|
+
let dispatcherDir;
|
|
258
|
+
try {
|
|
259
|
+
dispatcherDir = realpathSync(abs);
|
|
260
|
+
} catch {
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
if (!existsSync(join(dispatcherDir, "h"))) return null;
|
|
264
|
+
const hooksAbs = resolve(dispatcherDir, "..");
|
|
265
|
+
const relHooks = relative(git.toplevel, hooksAbs);
|
|
266
|
+
if (!relHooks || relHooks === "." || relHooks.startsWith("..")) return null;
|
|
267
|
+
const posixRel = relHooks.split(sep).join("/");
|
|
268
|
+
let prefix = "";
|
|
269
|
+
let dir = posixRel;
|
|
270
|
+
if (posixRel === ".vite-hooks") {
|
|
271
|
+
prefix = "";
|
|
272
|
+
dir = DEFAULT_HOOKS_DIR;
|
|
273
|
+
} else if (posixRel.endsWith(`/.vite-hooks`)) {
|
|
274
|
+
prefix = posixRel.slice(0, -12);
|
|
275
|
+
dir = DEFAULT_HOOKS_DIR;
|
|
276
|
+
}
|
|
277
|
+
const location = buildHooksLocation(git, dir, prefix);
|
|
278
|
+
return "isError" in location ? null : location;
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Resolve where hook files live.
|
|
282
|
+
*
|
|
283
|
+
* An explicit `dir` is relative to the current working directory (current
|
|
284
|
+
* git prefix). Omitting it uses the stored dir + the prefix recorded at
|
|
285
|
+
* enable/disable time, so later commands find the same tree from any cwd.
|
|
286
|
+
*/
|
|
287
|
+
function resolveHooksLocation(dir, options = {}) {
|
|
288
|
+
const git = getGitWorktree();
|
|
289
|
+
if ("isError" in git) return git;
|
|
290
|
+
let prefix;
|
|
291
|
+
let hooksDir;
|
|
292
|
+
if (dir !== void 0) {
|
|
293
|
+
prefix = git.prefix;
|
|
294
|
+
hooksDir = dir;
|
|
295
|
+
} else {
|
|
296
|
+
const storedDir = getStoredHooksDir();
|
|
297
|
+
if (storedDir) {
|
|
298
|
+
hooksDir = storedDir;
|
|
299
|
+
prefix = getStoredHooksPrefix() ?? git.prefix;
|
|
300
|
+
} else if (options.adoptEffectiveDispatcher) {
|
|
301
|
+
const adopted = tryAdoptEffectiveDispatcher(git);
|
|
302
|
+
if (adopted) return adopted;
|
|
303
|
+
hooksDir = DEFAULT_HOOKS_DIR;
|
|
304
|
+
prefix = options.unstoredPrefix === "root" ? "" : git.prefix;
|
|
305
|
+
} else {
|
|
306
|
+
hooksDir = DEFAULT_HOOKS_DIR;
|
|
307
|
+
prefix = options.unstoredPrefix === "root" ? "" : git.prefix;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
return buildHooksLocation(git, hooksDir, prefix);
|
|
311
|
+
}
|
|
312
|
+
function validateHooksDir(dir) {
|
|
313
|
+
if (dir.includes("..")) return {
|
|
314
|
+
message: ".. not allowed",
|
|
315
|
+
isError: true
|
|
316
|
+
};
|
|
317
|
+
if (isAbsolute(dir)) return {
|
|
318
|
+
message: "absolute hooks directory not allowed",
|
|
319
|
+
isError: true
|
|
320
|
+
};
|
|
321
|
+
if (relative(process.cwd(), resolve(process.cwd(), dir)) === "") return {
|
|
322
|
+
message: "hooks directory must be a project subdirectory",
|
|
323
|
+
isError: true
|
|
324
|
+
};
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
function getEffectiveHooksPath() {
|
|
328
|
+
const checkResult = spawnSync("git", [
|
|
329
|
+
"config",
|
|
330
|
+
"--get",
|
|
331
|
+
"core.hooksPath"
|
|
332
|
+
]);
|
|
333
|
+
return checkResult.status === 0 ? checkResult.stdout?.toString().trim() : "";
|
|
334
|
+
}
|
|
335
|
+
function getScopedHooksPath(scope) {
|
|
336
|
+
const result = spawnSync("git", [
|
|
337
|
+
"config",
|
|
338
|
+
`--${scope}`,
|
|
339
|
+
"--get",
|
|
340
|
+
"core.hooksPath"
|
|
341
|
+
]);
|
|
342
|
+
return result.status === 0 ? result.stdout?.toString().trim() : "";
|
|
343
|
+
}
|
|
344
|
+
function unsetScopedHooksPath(scope) {
|
|
345
|
+
const result = spawnSync("git", [
|
|
346
|
+
"config",
|
|
347
|
+
`--${scope}`,
|
|
348
|
+
"--unset-all",
|
|
349
|
+
"core.hooksPath"
|
|
350
|
+
]);
|
|
351
|
+
if (result.status == null) return {
|
|
352
|
+
message: "git command not found",
|
|
353
|
+
isError: true
|
|
354
|
+
};
|
|
355
|
+
if (result.status !== 0 && result.status !== 5) return {
|
|
356
|
+
message: result.stderr?.toString().trim() || `failed to unset ${scope} core.hooksPath`,
|
|
357
|
+
isError: true
|
|
358
|
+
};
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Unset core.hooksPath only at scopes that actually point at our dispatcher.
|
|
363
|
+
*
|
|
364
|
+
* Must not touch a foreign value at another scope (e.g. local still `.husky/_`
|
|
365
|
+
* while worktree holds the Vite+ target).
|
|
366
|
+
*/
|
|
367
|
+
function unsetOwnedHooksPath(target) {
|
|
368
|
+
const toplevel = getGitToplevel();
|
|
369
|
+
if (typeof toplevel !== "string") return toplevel;
|
|
370
|
+
for (const scope of ["local", "worktree"]) {
|
|
371
|
+
const scopedPath = getScopedHooksPath(scope);
|
|
372
|
+
if (!scopedPath || !hooksPathsEqual(scopedPath, target, toplevel)) continue;
|
|
373
|
+
const unsetError = unsetScopedHooksPath(scope);
|
|
374
|
+
if (unsetError) return unsetError;
|
|
375
|
+
}
|
|
376
|
+
const finalPath = getEffectiveHooksPath();
|
|
377
|
+
if (finalPath && hooksPathsEqual(finalPath, target, toplevel)) return {
|
|
378
|
+
message: `could not unset core.hooksPath (still "${finalPath}"); remove it with git config --unset core.hooksPath`,
|
|
379
|
+
isError: true
|
|
380
|
+
};
|
|
381
|
+
return null;
|
|
382
|
+
}
|
|
383
|
+
function install(dir, options = {}) {
|
|
384
|
+
if (process.env.HUSKY === "0" || process.env.VP_GIT_HOOKS === "0" || process.env.VITE_GIT_HOOKS === "0") return {
|
|
385
|
+
message: "skip install (git hooks disabled)",
|
|
386
|
+
isError: false
|
|
387
|
+
};
|
|
388
|
+
if (!options.ignoreUserPreference && isHooksUserDisabled()) return {
|
|
389
|
+
message: "skip install (hooks disabled; run `vp hooks enable` to re-enable)",
|
|
390
|
+
isError: false
|
|
391
|
+
};
|
|
392
|
+
const location = resolveHooksLocation(dir);
|
|
393
|
+
if ("isError" in location) return location;
|
|
394
|
+
const unsafeInstallPath = findUnsafeHookInstallPath(location.baseDir, location.dir);
|
|
395
|
+
if (unsafeInstallPath) return {
|
|
396
|
+
message: describeUnsafeHookInstallPath(unsafeInstallPath),
|
|
397
|
+
isError: false
|
|
398
|
+
};
|
|
399
|
+
const internal = (x = "") => join(location.baseDir, location.dir, "_", x);
|
|
400
|
+
const existingHooksPath = getEffectiveHooksPath();
|
|
401
|
+
if (existingHooksPath && !hooksPathsEqual(existingHooksPath, location.target, location.toplevel)) return {
|
|
402
|
+
message: `core.hooksPath is already set to "${existingHooksPath}", skipping`,
|
|
403
|
+
isError: false
|
|
404
|
+
};
|
|
405
|
+
rmSync(internal("husky.sh"), { force: true });
|
|
406
|
+
mkdirSync(internal(), { recursive: true });
|
|
407
|
+
writeFileSync(internal(".gitignore"), "*");
|
|
408
|
+
writeFileSync(internal("h"), hookScript(location.dir), { mode: 493 });
|
|
409
|
+
chmodSync(internal("h"), 493);
|
|
410
|
+
for (const hook of SUPPORTED_GIT_HOOK_NAMES) {
|
|
411
|
+
writeFileSync(internal(hook), `#!/usr/bin/env sh\n. "$(dirname "$0")/h"`, { mode: 493 });
|
|
412
|
+
chmodSync(internal(hook), 493);
|
|
413
|
+
}
|
|
414
|
+
const { status, stderr } = spawnSync("git", [
|
|
415
|
+
"config",
|
|
416
|
+
"core.hooksPath",
|
|
417
|
+
location.target
|
|
418
|
+
]);
|
|
419
|
+
if (status == null) return {
|
|
420
|
+
message: "git command not found",
|
|
421
|
+
isError: true
|
|
422
|
+
};
|
|
423
|
+
if (status) return {
|
|
424
|
+
message: "" + stderr,
|
|
425
|
+
isError: true
|
|
426
|
+
};
|
|
427
|
+
const clearDisabled = setHooksUserDisabled(false);
|
|
428
|
+
if (!clearDisabled.ok) return {
|
|
429
|
+
message: clearDisabled.error || "failed to clear hooks disabled preference",
|
|
430
|
+
isError: true
|
|
431
|
+
};
|
|
432
|
+
const storeDir = setStoredHooksLocation(location.dir, location.prefix);
|
|
433
|
+
if (!storeDir.ok) return {
|
|
434
|
+
message: storeDir.error || "failed to store hooks directory",
|
|
435
|
+
isError: true
|
|
436
|
+
};
|
|
437
|
+
return {
|
|
438
|
+
message: "",
|
|
439
|
+
isError: false
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Install (or refresh) the Vite+ hook dispatcher and mark hooks as enabled.
|
|
444
|
+
* Clears a previous `vp hooks disable` preference.
|
|
445
|
+
*/
|
|
446
|
+
function enable(dir) {
|
|
447
|
+
const location = resolveHooksLocation(dir);
|
|
448
|
+
if ("isError" in location) return location;
|
|
449
|
+
const result = install(dir, { ignoreUserPreference: true });
|
|
450
|
+
if (result.isError) return result;
|
|
451
|
+
if (result.message) return result;
|
|
452
|
+
return {
|
|
453
|
+
message: `Git hook dispatcher installed at ${displayHooksDir(location)}/_`,
|
|
454
|
+
isError: false
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Disable Vite+ hooks in this repo and tear down the dispatcher.
|
|
459
|
+
*
|
|
460
|
+
* - Persists the decision in local git config so `vp config` / prepare do not reinstall
|
|
461
|
+
* - Unsets `core.hooksPath` only when it points at this project's dispatcher
|
|
462
|
+
* - Removes the generated `<dir>/_` directory
|
|
463
|
+
* - Leaves project-owned hooks, staged config, and package.json scripts alone
|
|
464
|
+
*/
|
|
465
|
+
function disable(dir) {
|
|
466
|
+
const location = resolveHooksLocation(dir, {
|
|
467
|
+
unstoredPrefix: "root",
|
|
468
|
+
adoptEffectiveDispatcher: true
|
|
469
|
+
});
|
|
470
|
+
if ("isError" in location) return location;
|
|
471
|
+
const displayedDir = displayHooksDir(location);
|
|
472
|
+
const internalDir = join(location.baseDir, location.dir, "_");
|
|
473
|
+
const hasInternalDir = existsSync(internalDir);
|
|
474
|
+
if (hasInternalDir) {
|
|
475
|
+
const unsafeInstallPath = findUnsafeHookInstallPath(location.baseDir, location.dir);
|
|
476
|
+
if (unsafeInstallPath) return {
|
|
477
|
+
message: describeUnsafeHookInstallPath(unsafeInstallPath),
|
|
478
|
+
isError: false
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
const existingHooksPath = getEffectiveHooksPath();
|
|
482
|
+
const ownsHooksPath = !!existingHooksPath && hooksPathsEqual(existingHooksPath, location.target, location.toplevel);
|
|
483
|
+
const foreignHooksPath = !!existingHooksPath && !hooksPathsEqual(existingHooksPath, location.target, location.toplevel);
|
|
484
|
+
const actions = [];
|
|
485
|
+
const notes = [];
|
|
486
|
+
const pref = setHooksUserDisabled(true);
|
|
487
|
+
if (!pref.ok) return {
|
|
488
|
+
message: pref.error || "failed to persist hooks disabled preference",
|
|
489
|
+
isError: true
|
|
490
|
+
};
|
|
491
|
+
const storeDir = setStoredHooksLocation(location.dir, location.prefix);
|
|
492
|
+
if (!storeDir.ok) return {
|
|
493
|
+
message: storeDir.error || "failed to store hooks directory",
|
|
494
|
+
isError: true
|
|
495
|
+
};
|
|
496
|
+
actions.push("recorded disable preference (local git config)");
|
|
497
|
+
const unsetError = unsetOwnedHooksPath(location.target);
|
|
498
|
+
if (unsetError) return {
|
|
499
|
+
message: `${unsetError.message}; disable preference was recorded (local git config). Run \`vp hooks enable\` to clear it, or \`git config --local --unset vp.hooks.disabled\``,
|
|
500
|
+
isError: true
|
|
501
|
+
};
|
|
502
|
+
if (ownsHooksPath) actions.push(`unset core.hooksPath (was "${existingHooksPath}")`);
|
|
503
|
+
else if (foreignHooksPath) notes.push(`core.hooksPath is set to "${existingHooksPath}" (not Vite+ dispatcher "${location.target}"), left unchanged`);
|
|
504
|
+
if (hasInternalDir) {
|
|
505
|
+
rmSync(internalDir, {
|
|
506
|
+
recursive: true,
|
|
507
|
+
force: true
|
|
508
|
+
});
|
|
509
|
+
actions.push(`removed ${displayedDir}/_`);
|
|
510
|
+
}
|
|
511
|
+
const summary = `Git hooks disabled: ${actions.join("; ")}. Project-owned hooks under ${displayedDir}/ and staged config were left unchanged. Run \`vp hooks enable\` to re-enable.`;
|
|
512
|
+
if (notes.length > 0) return {
|
|
513
|
+
message: `${summary} ${notes.join("; ")}.`,
|
|
514
|
+
isError: false
|
|
515
|
+
};
|
|
516
|
+
return {
|
|
517
|
+
message: summary,
|
|
518
|
+
isError: false
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Report whether Vite+ hooks are set up, disabled by preference, and active.
|
|
523
|
+
*/
|
|
524
|
+
function status(dir) {
|
|
525
|
+
const location = resolveHooksLocation(dir, {
|
|
526
|
+
unstoredPrefix: "root",
|
|
527
|
+
adoptEffectiveDispatcher: true
|
|
528
|
+
});
|
|
529
|
+
if ("isError" in location) return location;
|
|
530
|
+
const hooksDir = displayHooksDir(location);
|
|
531
|
+
const existingHooksPath = getEffectiveHooksPath();
|
|
532
|
+
const userDisabled = isHooksUserDisabled();
|
|
533
|
+
const dispatcherInstalled = existsSync(join(location.baseDir, location.dir, "_", "h"));
|
|
534
|
+
const ownsHooksPath = !!existingHooksPath && hooksPathsEqual(existingHooksPath, location.target, location.toplevel);
|
|
535
|
+
let projectHooks = [];
|
|
536
|
+
const hooksDirPath = join(location.baseDir, location.dir);
|
|
537
|
+
if (existsSync(hooksDirPath)) try {
|
|
538
|
+
projectHooks = readdirSync(hooksDirPath, { withFileTypes: true }).filter((entry) => entry.isFile() && SUPPORTED_GIT_HOOK_NAMES.includes(entry.name)).map((entry) => entry.name).toSorted();
|
|
539
|
+
} catch {
|
|
540
|
+
projectHooks = [];
|
|
541
|
+
}
|
|
542
|
+
const preferenceLabel = userDisabled ? "disabled (local)" : getStoredHooksDir() || dispatcherInstalled || ownsHooksPath ? "enabled" : "not set";
|
|
543
|
+
const hooksPathLabel = existingHooksPath || "(unset)";
|
|
544
|
+
const ownership = !existingHooksPath ? "" : ownsHooksPath ? " (Vite+ dispatcher)" : " (not Vite+ dispatcher)";
|
|
545
|
+
const dispatcherLabel = dispatcherInstalled ? "installed" : "missing";
|
|
546
|
+
const projectHooksLabel = projectHooks.length > 0 ? projectHooks.join(", ") : "(none)";
|
|
547
|
+
const lines = [
|
|
548
|
+
`Preference: ${preferenceLabel}`,
|
|
549
|
+
`Hooks dir: ${hooksDir}`,
|
|
550
|
+
`core.hooksPath: ${hooksPathLabel}${ownership}`,
|
|
551
|
+
`Dispatcher: ${dispatcherLabel} (${hooksDir}/_)`,
|
|
552
|
+
`Project hooks: ${projectHooksLabel}`
|
|
553
|
+
];
|
|
554
|
+
const hooksStatus = {
|
|
555
|
+
hooksDir,
|
|
556
|
+
userDisabled,
|
|
557
|
+
hooksPath: existingHooksPath || null,
|
|
558
|
+
ownsHooksPath,
|
|
559
|
+
dispatcherInstalled,
|
|
560
|
+
projectHooks,
|
|
561
|
+
lines
|
|
562
|
+
};
|
|
563
|
+
return {
|
|
564
|
+
message: lines.join("\n"),
|
|
565
|
+
isError: false,
|
|
566
|
+
status: hooksStatus
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
//#endregion
|
|
570
|
+
export { findUnsafeHookInstallPath as a, resolveHooksLocation as c, enable as i, status as l, SUPPORTED_GIT_HOOK_NAMES as n, install as o, disable as r, isHooksUserDisabled as s, DEFAULT_HOOKS_DIR as t };
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_define_config = require("./define-config-
|
|
1
|
+
const require_define_config = require("./define-config-DyNLA_f0.cjs");
|
|
2
2
|
//#region src/index.cts
|
|
3
3
|
const vite = require("@voidzero-dev/vite-plus-core");
|
|
4
4
|
const { configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude } = require("vitest/config");
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as defineConfig, c as lazyPlugins, o as defineProject } from "./define-config-
|
|
1
|
+
import { a as defineConfig, c as lazyPlugins, o as defineProject } from "./define-config-CV4bQG_8.js";
|
|
2
2
|
import { configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude } from "vitest/config";
|
|
3
3
|
export * from "@voidzero-dev/vite-plus-core";
|
|
4
4
|
export { configDefaults, coverageConfigDefaults, defaultBrowserPort, defaultExclude, defaultInclude, defineConfig, defineProject, lazyPlugins };
|
|
@@ -114,11 +114,13 @@ function createScanner(text, ignoreTrivia = false) {
|
|
|
114
114
|
start = pos;
|
|
115
115
|
continue;
|
|
116
116
|
}
|
|
117
|
-
if (ch >= 0 && ch <= 31)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
117
|
+
if (ch >= 0 && ch <= 31) {
|
|
118
|
+
if (isLineBreak(ch)) {
|
|
119
|
+
result += text.substring(start, pos);
|
|
120
|
+
scanError = 2;
|
|
121
|
+
break;
|
|
122
|
+
} else scanError = 6;
|
|
123
|
+
}
|
|
122
124
|
pos++;
|
|
123
125
|
}
|
|
124
126
|
return result;
|
|
@@ -539,8 +541,10 @@ function format(documentText, range, options) {
|
|
|
539
541
|
}
|
|
540
542
|
if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) replaceContent = newLinesAndIndent();
|
|
541
543
|
}
|
|
542
|
-
if (secondToken === 17)
|
|
543
|
-
|
|
544
|
+
if (secondToken === 17) {
|
|
545
|
+
if (options.keepLines && numberLineBreaks > 0) replaceContent = newLinesAndIndent();
|
|
546
|
+
else replaceContent = options.insertFinalNewline ? eol : "";
|
|
547
|
+
}
|
|
544
548
|
const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
545
549
|
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
|
|
546
550
|
firstToken = secondToken;
|
|
@@ -964,9 +968,10 @@ function setProperty(text, originalPath, value, options) {
|
|
|
964
968
|
while (path.length > 0) {
|
|
965
969
|
lastSegment = path.pop();
|
|
966
970
|
parent = findNodeAtLocation(root, path);
|
|
967
|
-
if (parent === void 0 && value !== void 0)
|
|
968
|
-
|
|
969
|
-
|
|
971
|
+
if (parent === void 0 && value !== void 0) {
|
|
972
|
+
if (typeof lastSegment === "string") value = { [lastSegment]: value };
|
|
973
|
+
else value = [value];
|
|
974
|
+
} else break;
|
|
970
975
|
}
|
|
971
976
|
if (!parent) {
|
|
972
977
|
if (value === void 0) throw new Error("Can not delete in empty document");
|
|
@@ -977,29 +982,30 @@ function setProperty(text, originalPath, value, options) {
|
|
|
977
982
|
}, options);
|
|
978
983
|
} else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
|
|
979
984
|
const existing = findNodeAtLocation(parent, [lastSegment]);
|
|
980
|
-
if (existing !== void 0)
|
|
981
|
-
if (
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
985
|
+
if (existing !== void 0) {
|
|
986
|
+
if (value === void 0) {
|
|
987
|
+
if (!existing.parent) throw new Error("Malformed AST");
|
|
988
|
+
const propertyIndex = parent.children.indexOf(existing.parent);
|
|
989
|
+
let removeBegin;
|
|
990
|
+
let removeEnd = existing.parent.offset + existing.parent.length;
|
|
991
|
+
if (propertyIndex > 0) {
|
|
992
|
+
let previous = parent.children[propertyIndex - 1];
|
|
993
|
+
removeBegin = previous.offset + previous.length;
|
|
994
|
+
} else {
|
|
995
|
+
removeBegin = parent.offset + 1;
|
|
996
|
+
if (parent.children.length > 1) removeEnd = parent.children[1].offset;
|
|
997
|
+
}
|
|
998
|
+
return withFormatting(text, {
|
|
999
|
+
offset: removeBegin,
|
|
1000
|
+
length: removeEnd - removeBegin,
|
|
1001
|
+
content: ""
|
|
1002
|
+
}, options);
|
|
1003
|
+
} else return withFormatting(text, {
|
|
1004
|
+
offset: existing.offset,
|
|
1005
|
+
length: existing.length,
|
|
1006
|
+
content: JSON.stringify(value)
|
|
996
1007
|
}, options);
|
|
997
|
-
} else
|
|
998
|
-
offset: existing.offset,
|
|
999
|
-
length: existing.length,
|
|
1000
|
-
content: JSON.stringify(value)
|
|
1001
|
-
}, options);
|
|
1002
|
-
else {
|
|
1008
|
+
} else {
|
|
1003
1009
|
if (value === void 0) return [];
|
|
1004
1010
|
const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
|
|
1005
1011
|
const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
|