@depack/cache
Version:
Computes Necessary Information To Cache A Module, And Allows To Check If It Has Been Updated.
400 lines (397 loc) • 11.8 kB
JavaScript
const _crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const os = require('os');
const _module = require('module');
const stream = require('stream');
const t = _crypto.createHash;
const u = (a, b = 0, c = !1) => {
if (0 === b && !c) {
return a;
}
a = a.split("\n", c ? b + 1 : void 0);
return c ? a[a.length - 1] : a.slice(b).join("\n");
}, v = (a, b = !1) => u(a, 2 + (b ? 1 : 0)), w = a => {
({callee:{caller:a}} = a);
return a;
};
const x = os.homedir;
const y = /\s+at.*(?:\(|\s)(.*)\)?/, A = /^(?:(?:(?:node|(?:internal\/[\w/]*|.*node_modules\/(?:IGNORED_MODULES)\/.*)?\w+)\.js:\d+:\d+)|native)/, B = x(), C = a => {
const {pretty:b = !1, ignoredModules:c = ["pirates"]} = {}, k = c.join("|"), h = new RegExp(A.source.replace("IGNORED_MODULES", k));
return a.replace(/\\/g, "/").split("\n").filter(d => {
d = d.match(y);
if (null === d || !d[1]) {
return !0;
}
d = d[1];
return d.includes(".app/Contents/Resources/electron.asar") || d.includes(".app/Contents/Resources/default_app.asar") ? !1 : !h.test(d);
}).filter(d => d.trim()).map(d => b ? d.replace(y, (m, e) => m.replace(e, e.replace(B, "~"))) : d).join("\n");
};
function F(a, b, c = !1) {
return function(k) {
var h = w(arguments), {stack:d} = Error();
const m = u(d, 2, !0), e = (d = k instanceof Error) ? k.message : k;
h = [`Error: ${e}`, ...null !== h && a === h || c ? [b] : [m, b]].join("\n");
h = C(h);
return Object.assign(d ? k : Error(), {message:e, stack:h});
};
}
;function G(a) {
var {stack:b} = Error();
const c = w(arguments);
b = v(b, a);
return F(c, b, a);
}
;async function H(a, b, c) {
const k = G(!0);
if ("function" != typeof a) {
throw Error("Function must be passed.");
}
if (!a.length) {
throw Error(`Function${a.name ? ` ${a.name}` : ""} does not accept any arguments.`);
}
return await new Promise((h, d) => {
const m = (f, g) => f ? (f = k(f), d(f)) : h(c || g);
let e = [m];
Array.isArray(b) ? e = [...b, m] : 1 < Array.from(arguments).length && (e = [b, m]);
a(...e);
});
}
;const I = fs.createReadStream, J = fs.lstat;
const K = async a => {
try {
return await H(J, a);
} catch (b) {
return null;
}
};
const L = path.dirname, M = path.join, aa = path.parse, N = path.relative, ba = path.resolve;
const P = async(a, b) => {
b && (b = L(b), a = M(b, a));
var c = await K(a);
b = a;
let k = !1;
if (!c) {
if (b = await O(a), !b) {
throw Error(`${a}.js or ${a}.jsx is not found.`);
}
} else {
if (c.isDirectory()) {
c = !1;
let h;
a.endsWith("/") || (h = b = await O(a), c = !0);
if (!h) {
b = await O(M(a, "index"));
if (!b) {
throw Error(`${c ? `${a}.jsx? does not exist, and ` : ""}index.jsx? file is not found in ${a}`);
}
k = !0;
}
}
}
return {path:a.startsWith(".") ? N("", b) : b, j:k};
}, O = async a => {
a = `${a}.js`;
let b = await K(a);
b || (a = `${a}x`);
if (b = await K(a)) {
return a;
}
};
const ca = _module.builtinModules;
const da = stream.Writable;
const ea = (a, b) => {
b.once("error", c => {
a.emit("error", c);
});
return b;
};
class fa extends da {
constructor(a) {
const {binary:b = !1, rs:c = null, ...k} = a || {}, {g:h = G(!0), proxyError:d} = a || {}, m = (e, f) => h(f);
super(k);
this.a = [];
this.c = new Promise((e, f) => {
this.on("finish", () => {
let g;
b ? g = Buffer.concat(this.a) : g = this.a.join("");
e(g);
this.a = [];
});
this.once("error", g => {
if (-1 == g.stack.indexOf("\n")) {
m`${g}`;
} else {
const n = C(g.stack);
g.stack = n;
d && m`${g}`;
}
f(g);
});
c && ea(this, c).pipe(this);
});
}
_write(a, b, c) {
this.a.push(a);
c();
}
get f() {
return this.c;
}
}
const ha = async a => {
({f:a} = new fa({rs:a, g:G(!0)}));
return await a;
};
async function Q(a) {
a = I(a);
return await ha(a);
}
;function R(a, b) {
var c = ["q", "from"];
const k = [];
b.replace(a, (h, ...d) => {
h = d.slice(0, d.length - 2).reduce((m, e, f) => {
f = c[f];
if (!f || void 0 === e) {
return m;
}
m[f] = e;
return m;
}, {});
k.push(h);
});
return k;
}
;const ia = /^ *import(?:\s+(?:[^\s,]+)\s*,?)?(?:\s*{(?:[^}]+)})?\s+from\s+(['"])(.+?)\1/gm, ja = /^ *import\s+(?:.+?\s*,\s*)?\*\s+as\s+.+?\s+from\s+(['"])(.+?)\1/gm, ka = /^ *import\s+(['"])(.+?)\1/gm, la = /^ *export\s+(?:{[^}]+?}|\*)\s+from\s+(['"])(.+?)\1/gm, ma = a => [ia, ja, ka, la].reduce((b, c) => {
c = R(c, a).map(k => k.from);
return [...b, ...c];
}, []);
let S;
const T = async(a, b, c = {}) => {
S || ({root:S} = aa(process.cwd()));
const {fields:k, soft:h = !1} = c;
var d = M(a, "node_modules", b);
d = M(d, "package.json");
const m = await K(d);
if (m) {
a = await na(d, k);
if (void 0 === a) {
throw Error(`The package ${N("", d)} does export the module.`);
}
if (!a.entryExists && !h) {
throw Error(`The exported module ${a.main} in package ${b} does not exist.`);
}
const {entry:e, version:f, packageName:g, main:n, entryExists:p, ...l} = a;
return {entry:N("", e), packageJson:N("", d), ...f ? {version:f} : {}, packageName:g, ...n ? {hasMain:!0} : {}, ...p ? {} : {entryExists:!1}, ...l};
}
if (a == S && !m) {
throw Error(`Package.json for module ${b} not found.`);
}
return T(M(ba(a), ".."), b, c);
}, na = async(a, b = []) => {
const c = await Q(a);
let k, h, d, m, e;
try {
({module:k, version:h, name:d, main:m, ...e} = JSON.parse(c)), e = b.reduce((g, n) => {
g[n] = e[n];
return g;
}, {});
} catch (g) {
throw Error(`Could not parse ${a}.`);
}
a = L(a);
b = k || m;
if (!b) {
if (!await K(M(a, "index.js"))) {
return;
}
b = m = "index.js";
}
a = M(a, b);
let f;
try {
({path:f} = await P(a)), a = f;
} catch (g) {
}
return {entry:a, version:h, packageName:d, main:!k && m, entryExists:!!f, ...e};
};
const U = a => /^[./]/.test(a), V = async(a, b, c, k, h = null) => {
const d = G(), m = L(a);
b = b.map(async e => {
if (ca.includes(e)) {
return {internal:e};
}
if (/^[./]/.test(e)) {
try {
var {path:f} = await P(e, a);
return {entry:f, package:h};
} catch (g) {
}
} else {
{
let [p, l, ...q] = e.split("/");
!p.startsWith("@") && l ? (q = [l, ...q], l = p) : l = p.startsWith("@") ? `${p}/${l}` : p;
f = {name:l, paths:q.join("/")};
}
const {name:g, paths:n} = f;
if (n) {
const {packageJson:p, packageName:l} = await T(m, g);
e = L(p);
({path:e} = await P(M(e, n)));
return {entry:e, package:l};
}
}
try {
const {entry:g, packageJson:n, version:p, packageName:l, hasMain:q, ...r} = await T(m, e, {fields:k});
return l == h ? (console.warn("[static-analysis] Skipping package %s that imports itself in %s", l, a), null) : {entry:g, packageJson:n, version:p, name:l, ...q ? {hasMain:q} : {}, ...r};
} catch (g) {
if (c) {
return null;
}
[e] = process.version.split(".");
e = parseInt(e.replace("v", ""), 10);
if (12 <= e) {
throw g;
}
throw d(g);
}
});
return (await Promise.all(b)).filter(Boolean);
}, W = async(a, b = {}, {nodeModules:c = !0, shallow:k = !1, soft:h = !1, fields:d = [], h:m = {}, mergeSameNodeModules:e = !0, package:f} = {}) => {
if (a in b) {
return [];
}
b[a] = 1;
var g = await Q(a), n = ma(g);
g = oa(g);
n = c ? n : n.filter(U);
g = c ? g : g.filter(U);
try {
const l = await V(a, n, h, d, f), q = await V(a, g, h, d, f);
q.forEach(r => {
r.required = !0;
});
var p = [...l, ...q];
} catch (l) {
throw l.message = `${a}\n [!] ${l.message}`, l;
}
f = e ? p.map(l => {
var q = l.name, r = l.version;
const D = l.required;
if (q && r) {
q = `${q}:${r}${D ? "-required" : ""}`;
if (r = m[q]) {
return r;
}
m[q] = l;
}
return l;
}) : p;
p = f.map(l => ({...l, from:a}));
return await f.filter(({entry:l}) => l && !(l in b)).reduce(async(l, {entry:q, hasMain:r, packageJson:D, name:E, package:pa}) => {
if (D && k) {
return l;
}
l = await l;
E = (await W(q, b, {nodeModules:c, shallow:k, soft:h, fields:d, package:E || pa, h:m, mergeSameNodeModules:e})).map(z => ({...z, from:z.from ? z.from : q, ...!z.packageJson && r ? {hasMain:r} : {}}));
return [...l, ...E];
}, p);
}, oa = a => R(/(?:^|[^\w\d_])require\(\s*(['"])(.+?)\1\s*\)/gm, a).map(b => b.from);
const qa = async a => {
const b = G();
a = Array.isArray(a) ? a : [a];
a = await Promise.all(a.map(async f => {
({path:f} = await P(f));
return f;
}));
const {nodeModules:c = !0, shallow:k = !1, soft:h = !1, fields:d = [], mergeSameNodeModules:m = !0} = {shallow:!0, soft:!0};
let e;
try {
const f = {};
e = await a.reduce(async(g, n) => {
g = await g;
n = await W(n, f, {nodeModules:c, shallow:k, soft:h, fields:d, mergeSameNodeModules:m});
g.push(...n);
return g;
}, []);
} catch (f) {
[a] = process.version.split(".");
a = parseInt(a.replace("v", ""), 10);
if (12 <= a) {
throw f;
}
throw b(f);
}
return e.filter(({internal:f, entry:g}, n) => f ? e.findIndex(({internal:p}) => p == f) == n : e.findIndex(({entry:p}) => g == p) == n).map(f => {
const g = f.entry, n = f.internal, p = e.filter(({internal:l, entry:q}) => {
if (n) {
return n == l;
}
if (g) {
return g == q;
}
}).map(({from:l}) => l).filter((l, q, r) => r.indexOf(l) == q);
return {...f, from:p};
}).map(({package:f, ...g}) => f ? {package:f, ...g} : g);
};
/*
diff package https://github.com/kpdecker/jsdiff
BSD License
Copyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>
*/
const ra = {black:30, red:31, green:32, yellow:33, blue:34, magenta:35, cyan:36, white:37, grey:90};
function X(a, b) {
return (b = ra[b]) ? `\x1b[${b}m${a}\x1b[0m` : a;
}
;const sa = (a, b, c = console.log) => {
const k = [], h = [];
b.forEach(d => {
a.includes(d) || k.push(d);
});
a.forEach(d => {
b.includes(d) || h.push(d);
});
if (!k.length && !h.length) {
return !0;
}
k.forEach(d => {
const {entry:m, b:e} = Y(d);
c(X("+", "green"), m, e);
});
h.forEach(d => {
const {entry:m, b:e} = Y(d);
c(X("-", "red"), m, e);
});
return !1;
}, Y = a => {
const [b, c] = a.split(" ");
a = "";
c && (a = /^\d+$/.test(c) ? (new Date(parseInt(c, 10))).toLocaleString() : c);
return {entry:b, b:a};
}, Z = async a => (await H(J, a)).mtime.getTime(), ta = async a => await Promise.all(a.map(async({entry:b, name:c, internal:k, version:h}) => {
if (c) {
return `${c} ${h}`;
}
if (k) {
return k;
}
c = await Z(b);
return `${b} ${c}`;
})), ua = async a => {
const b = await qa(a), c = await ta(b);
({path:a} = await P(a));
return {mtime:await Z(a), hash:c, i:b};
};
module.exports = async(a, b = {}, c = console.log) => {
b = b[a];
const {mtime:k, hash:h} = await ua(a);
a = t("md5").update(JSON.stringify(h)).digest("hex");
if (!b) {
return {result:!1, reason:"NO_CACHE", mtime:k, hash:h, md5:a};
}
const {mtime:d, hash:m} = b;
return k != d ? {result:!1, reason:"MTIME_CHANGE", mtime:k, hash:h, currentMtime:d, md5:a} : sa(m, h, c) ? {result:!0, md5:a} : {result:!1, mtime:k, hash:h, reason:"HASH_CHANGE", md5:a};
};
//# sourceMappingURL=cache.js.map