vlt
Version:
The vlt CLI
288 lines (282 loc) • 8.61 kB
JavaScript
var global = globalThis;
import {Buffer} from "node:buffer";
import {setTimeout,clearTimeout,setImmediate,clearImmediate,setInterval,clearInterval} from "node:timers";
import {createRequire as _vlt_createRequire} from "node:module";
var require = _vlt_createRequire(import.meta.filename);
import {
XDG
} from "./chunk-BA67AKYJ.js";
import {
error
} from "./chunk-KVH5ECIG.js";
// ../../src/vlt-json/src/index.ts
import {
lstatSync,
mkdirSync,
readFileSync,
writeFileSync
} from "node:fs";
import { homedir } from "node:os";
import { dirname as dirname2, resolve as resolve2 } from "node:path";
// ../../node_modules/.pnpm/walk-up-path@4.0.0/node_modules/walk-up-path/dist/esm/index.js
import { dirname, resolve } from "node:path";
var walkUp = function* (path) {
for (path = resolve(path); path; ) {
yield path;
const pp = dirname(path);
if (pp === path) {
break;
} else {
path = pp;
}
}
};
// ../../node_modules/.pnpm/polite-json@5.0.0/node_modules/polite-json/dist/esm/index.js
var hexify = (s) => Array.from(s).map((c) => "0x" + c.charCodeAt(0).toString(16).toUpperCase().padStart(2, "0")).join("");
var parseError = (e, txt, context) => {
if (!txt) {
return {
message: e.message + " while parsing empty string",
position: 0
};
}
const badToken = e.message.match(/^Unexpected (?:token (.*?))?/i);
const atPos = e.message.match(/at positions? (\d+)/);
const errIdx = /^Unexpected end of JSON|Unterminated string in JSON/i.test(e.message) ? txt.length - 1 : atPos && atPos[1] ? +atPos[1] : /is not valid JSON$/.test(e.message) ? 0 : null;
const msg = badToken && badToken[1] ? e.message.replace(/^Unexpected token ./, `Unexpected token ${JSON.stringify(badToken[1])} (${hexify(badToken[1])})`) : e.message;
if (errIdx !== null && errIdx !== void 0) {
const start = errIdx <= context ? 0 : errIdx - context;
const end = errIdx + context >= txt.length ? txt.length : errIdx + context;
const slice = (start === 0 ? "" : "...") + txt.slice(start, end) + (end === txt.length ? "" : "...");
const near = txt === slice ? "" : "near ";
return {
message: msg + ` while parsing ${near}${JSON.stringify(slice)}`,
position: errIdx
};
} else {
return {
message: msg + ` while parsing '${txt.slice(0, context * 2)}'`,
position: 0
};
}
};
var JSONParseError = class extends SyntaxError {
code;
cause;
position;
constructor(er, txt, context = 20, caller) {
const { message, position } = parseError(er, txt, context);
super(message);
this.cause = er;
this.position = position;
this.code = "EJSONPARSE";
Error.captureStackTrace(this, caller || this.constructor);
}
get name() {
return this.constructor.name;
}
set name(_) {
}
get [Symbol.toStringTag]() {
return this.constructor.name;
}
};
var kIndent = Symbol.for("indent");
var kNewline = Symbol.for("newline");
var formatRE = /^\s*[{\[]((?:\r?\n)+)([\s\t]*)/;
var emptyRE = /^(?:\{\}|\[\])((?:\r?\n)+)?$/;
var parse = (txt, reviver, context) => {
const parseText = stripBOM(String(txt));
if (!reviver)
reviver = void 0;
context = context || 20;
try {
const [, newline = "\n", indent = " "] = parseText.match(emptyRE) || parseText.match(formatRE) || [, "", ""];
const result = JSON.parse(parseText, reviver);
if (result && typeof result === "object") {
result[kNewline] = newline;
result[kIndent] = indent;
}
return result;
} catch (e) {
if (typeof txt !== "string" && !Buffer.isBuffer(txt)) {
const isEmptyArray = Array.isArray(txt) && txt.length === 0;
throw Object.assign(new TypeError(`Cannot parse ${isEmptyArray ? "an empty array" : String(txt)}`), {
code: "EJSONPARSE",
systemError: e
});
}
throw new JSONParseError(e, parseText, context, parse);
}
};
var stripBOM = (txt) => String(txt).replace(/^\uFEFF/, "");
var stringify = (obj, replacer, indent) => {
const space = indent === void 0 ? obj[kIndent] : indent;
const res = (
/* c8 ignore start */
typeof replacer === "function" ? JSON.stringify(obj, replacer, space) : JSON.stringify(obj, replacer, space)
);
const nl = obj[kNewline] || "\n";
return space ? (nl === "\n" ? res : res.split("\n").join(nl)) + nl : res;
};
// ../../src/vlt-json/src/index.ts
var stringifyOptions = {};
var lstatCache = {};
var cachedLstat = (path) => {
if (path in lstatCache) return lstatCache[path];
try {
return lstatCache[path] = lstatSync(path);
} catch {
delete lstatCache[path];
return void 0;
}
};
var exists = (f) => !!cachedLstat(f);
var isRecord = (x) => !!x && typeof x === "object";
var mtimes = {
user: void 0,
project: void 0
};
var datas = {
user: void 0,
project: void 0
};
var validators = {};
var paths = {
user: new XDG("vlt").config("vlt.json"),
project: void 0
};
var maybeReadData = (path) => {
try {
const rawData = parse(readFileSync(path, "utf8"));
if (!isRecord(rawData)) return void 0;
const so = stringifyOptions[path] ?? {
[kIndent]: 2,
[kNewline]: "\n"
};
const {
[kNewline]: nl = so[kNewline],
[kIndent]: ind = so[kIndent],
...data
} = rawData;
stringifyOptions[path] = so;
stringifyOptions[path][kNewline] = nl;
stringifyOptions[path][kIndent] = ind;
return data;
} catch (er) {
throw error("Failed to parse vlt.json file", {
path,
cause: er
});
}
};
var loadFullObject = (which) => {
if (datas[which]) return datas[which];
const path = find(which);
const mtime = cachedLstat(path)?.mtime.getTime();
const data = mtime ? maybeReadData(path) : {};
if (mtime && data) {
mtimes[which] = mtime;
}
return datas[which] = data ?? {};
};
var runValidator = (v, x, file) => {
if (x !== void 0) v(x, file);
};
var unload = (which = "project") => {
const file = find(which);
delete datas[which];
delete paths[which];
delete lstatCache[file];
delete mtimes[which];
};
var reload = (field, which = "project") => {
unload(which);
const file = find(which);
const data = loadFullObject(which);
for (const [field2, validator] of Object.entries(validators)) {
const value = data[field2];
runValidator(validator, value, file);
}
return data[field];
};
var load = (field, validator, which = "project") => {
const data = loadFullObject(which);
const file = find(which);
validators[field] ??= validator;
const value = data[field];
if (value !== void 0) validator(value, file);
return value;
};
var find = (which = "project", cwd = process.cwd(), home = homedir()) => {
if (which === "user") {
return paths.user ??= new XDG("vlt").config("vlt.json");
}
if (paths[which]) return paths[which];
let lastKnownRoot = cwd;
for (const dir of walkUp(cwd)) {
if (dir === home) break;
const projectConfig = resolve2(dir, "vlt.json");
if (projectConfig === paths.user) break;
if (exists(projectConfig)) {
return paths[which] = projectConfig;
}
if (exists(resolve2(dir, "package.json")) || exists(resolve2(dir, "node_modules"))) {
lastKnownRoot = dir;
}
if (exists(resolve2(dir, ".git"))) break;
}
return paths[which] = resolve2(lastKnownRoot, "vlt.json");
};
var save = (field, value, which = "project") => {
const validator = validators[field];
const data = datas[which];
if (!validator || !data) {
throw error("Cannot save field before loading initially", {
name: field,
found: value
});
}
const file = find(which);
runValidator(validator, value, file);
data[field] = value;
const mtime = mtimes[which];
const path = find(which);
delete lstatCache[path];
const updatedMtime = cachedLstat(path)?.mtime.getTime();
if (updatedMtime && (!mtime || updatedMtime > mtime)) {
throw error(
"File was changed by another process, cannot safely write",
{
path,
name: field,
found: value
}
);
}
const extraStringifyOptions = stringifyOptions[path] ?? {};
if (!extraStringifyOptions[kIndent]) {
extraStringifyOptions[kIndent] = 2;
}
if (!extraStringifyOptions[kNewline]) {
extraStringifyOptions[kNewline] = "\n";
}
mkdirSync(dirname2(path), { recursive: true });
writeFileSync(
path,
stringify({ ...data, ...extraStringifyOptions })
);
delete lstatCache[path];
mtimes[which] = cachedLstat(path)?.mtime.getTime();
};
export {
parse,
stringify,
walkUp,
unload,
reload,
load,
find,
save
};
//# sourceMappingURL=chunk-QOAKZNUG.js.map