@stacksjs/utils 0.70.87 → 0.70.90
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/dist/bytes.js +55 -0
- package/dist/clean.js +13 -0
- package/dist/colors.js +100 -0
- package/dist/config.js +23 -0
- package/dist/debounce.js +77 -0
- package/dist/detect.js +65 -0
- package/dist/equal.js +27 -0
- package/dist/errors.js +44 -0
- package/dist/export-size.js +1 -0
- package/dist/find.js +68 -0
- package/dist/git.js +11 -0
- package/dist/glob.d.ts +1 -0
- package/dist/glob.js +1 -0
- package/dist/hash.js +36 -0
- package/dist/helpers.js +101 -0
- package/dist/index.js +23 -16
- package/dist/macroable.js +121 -0
- package/dist/markdown.js +92 -0
- package/dist/merge.js +51 -0
- package/dist/observer.js +78 -0
- package/dist/pipeline.js +37 -0
- package/dist/safe-json.js +33 -0
- package/dist/size.js +66 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +6 -0
- package/dist/versions.js +19 -0
- package/package.json +11 -11
package/dist/bytes.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const DECIMAL_UNITS = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], BINARY_UNITS = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
|
2
|
+
export function formatBytes(bytes, options = {}) {
|
|
3
|
+
const {
|
|
4
|
+
precision = 1,
|
|
5
|
+
binary = !1,
|
|
6
|
+
space = !0,
|
|
7
|
+
locale = "en-US",
|
|
8
|
+
minimumFractionDigits = 0,
|
|
9
|
+
maximumFractionDigits = precision
|
|
10
|
+
} = options;
|
|
11
|
+
if (!Number.isFinite(bytes))
|
|
12
|
+
throw TypeError(`Expected a finite number, got ${typeof bytes}: ${bytes}`);
|
|
13
|
+
const isNegative = bytes < 0, prefix = isNegative ? "-" : "";
|
|
14
|
+
if (isNegative)
|
|
15
|
+
bytes = -bytes;
|
|
16
|
+
if (bytes < 1) {
|
|
17
|
+
const numberString = bytes.toLocaleString(locale, {
|
|
18
|
+
minimumFractionDigits,
|
|
19
|
+
maximumFractionDigits
|
|
20
|
+
});
|
|
21
|
+
return `${prefix}${numberString}${space ? " " : ""}B`;
|
|
22
|
+
}
|
|
23
|
+
const base = binary ? 1024 : 1000, units = binary ? BINARY_UNITS : DECIMAL_UNITS, exponent = Math.min(Math.floor(Math.log(bytes) / Math.log(base)), units.length - 1), numberString = (bytes / base ** exponent).toLocaleString(locale, {
|
|
24
|
+
minimumFractionDigits,
|
|
25
|
+
maximumFractionDigits
|
|
26
|
+
}), unit = units[exponent];
|
|
27
|
+
return `${prefix}${numberString}${space ? " " : ""}${unit}`;
|
|
28
|
+
}
|
|
29
|
+
export function parseBytes(input) {
|
|
30
|
+
const match = input.match(/^(-?[\d.]+)\s*([A-Za-z]+)?$/);
|
|
31
|
+
if (!match)
|
|
32
|
+
throw Error(`Invalid byte string: ${input}`);
|
|
33
|
+
const [, numberStr, unit = "B"] = match;
|
|
34
|
+
if (numberStr === void 0)
|
|
35
|
+
throw Error(`Invalid byte string: ${input}`);
|
|
36
|
+
const number = Number.parseFloat(numberStr);
|
|
37
|
+
if (!Number.isFinite(number))
|
|
38
|
+
throw Error(`Invalid number in byte string: ${numberStr}`);
|
|
39
|
+
const normalizedUnit = unit.toUpperCase(), isBinary = normalizedUnit.endsWith("IB"), base = isBinary ? 1024 : 1000;
|
|
40
|
+
let exponent = 0;
|
|
41
|
+
const units = isBinary ? BINARY_UNITS : DECIMAL_UNITS;
|
|
42
|
+
for (let i = 0;i < units.length; i++)
|
|
43
|
+
if (units[i]?.toUpperCase() === normalizedUnit) {
|
|
44
|
+
exponent = i;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
return number * base ** exponent;
|
|
48
|
+
}
|
|
49
|
+
export function compareBytes(a, b) {
|
|
50
|
+
const bytesA = typeof a === "string" ? parseBytes(a) : a, bytesB = typeof b === "string" ? parseBytes(b) : b;
|
|
51
|
+
return bytesA - bytesB;
|
|
52
|
+
}
|
|
53
|
+
export const prettyBytes = formatBytes, readableSize = formatBytes;
|
|
54
|
+
|
|
55
|
+
export { formatBytes as default };
|
package/dist/clean.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { path as p } from "@stacksjs/path";
|
|
2
|
+
export async function cleanProject() {
|
|
3
|
+
await Bun.$`rm -rf ${p.projectPath("bun.lock")}`;
|
|
4
|
+
await Bun.$`rm -rf ${p.projectPath("yarn.lock")}`;
|
|
5
|
+
await Bun.$`rm -rf ${p.projectPath("node_modules/")}`;
|
|
6
|
+
await Bun.$`rm -rf ${p.frameworkPath("dist")}`;
|
|
7
|
+
await Bun.$`rm -rf ${p.frameworkPath("node_modules")}`;
|
|
8
|
+
await Bun.$`rm -rf ${p.frameworkPath("**/dist")}`;
|
|
9
|
+
await Bun.$`rm -rf ${p.frameworkPath("**/node_modules")}`;
|
|
10
|
+
await Bun.$`rm -rf ${p.frameworkCloudPath("cdk.out/")}`;
|
|
11
|
+
await Bun.$`rm -rf ${p.frameworkCloudPath("cdk.context.json")}`;
|
|
12
|
+
await Bun.$`rm -rf ${p.cloudPath("dist.zip")}`;
|
|
13
|
+
}
|
package/dist/colors.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const isColorSupported = !process.env.NO_COLOR && (process.env.FORCE_COLOR || process.stdout?.isTTY), colors = {
|
|
2
|
+
reset: isColorSupported ? "\x1B[0m" : "",
|
|
3
|
+
black: isColorSupported ? "\x1B[30m" : "",
|
|
4
|
+
red: isColorSupported ? "\x1B[31m" : "",
|
|
5
|
+
green: isColorSupported ? "\x1B[32m" : "",
|
|
6
|
+
yellow: isColorSupported ? "\x1B[33m" : "",
|
|
7
|
+
blue: isColorSupported ? "\x1B[34m" : "",
|
|
8
|
+
magenta: isColorSupported ? "\x1B[35m" : "",
|
|
9
|
+
cyan: isColorSupported ? "\x1B[36m" : "",
|
|
10
|
+
white: isColorSupported ? "\x1B[37m" : "",
|
|
11
|
+
gray: isColorSupported ? "\x1B[90m" : "",
|
|
12
|
+
grey: isColorSupported ? "\x1B[90m" : "",
|
|
13
|
+
lightRed: isColorSupported ? "\x1B[91m" : "",
|
|
14
|
+
lightGreen: isColorSupported ? "\x1B[92m" : "",
|
|
15
|
+
lightYellow: isColorSupported ? "\x1B[93m" : "",
|
|
16
|
+
lightBlue: isColorSupported ? "\x1B[94m" : "",
|
|
17
|
+
lightMagenta: isColorSupported ? "\x1B[95m" : "",
|
|
18
|
+
lightCyan: isColorSupported ? "\x1B[96m" : "",
|
|
19
|
+
lightGray: isColorSupported ? "\x1B[37m" : "",
|
|
20
|
+
lightGrey: isColorSupported ? "\x1B[37m" : "",
|
|
21
|
+
bgBlack: isColorSupported ? "\x1B[40m" : "",
|
|
22
|
+
bgRed: isColorSupported ? "\x1B[41m" : "",
|
|
23
|
+
bgGreen: isColorSupported ? "\x1B[42m" : "",
|
|
24
|
+
bgYellow: isColorSupported ? "\x1B[43m" : "",
|
|
25
|
+
bgBlue: isColorSupported ? "\x1B[44m" : "",
|
|
26
|
+
bgMagenta: isColorSupported ? "\x1B[45m" : "",
|
|
27
|
+
bgCyan: isColorSupported ? "\x1B[46m" : "",
|
|
28
|
+
bgWhite: isColorSupported ? "\x1B[47m" : "",
|
|
29
|
+
bgLightRed: isColorSupported ? "\x1B[101m" : "",
|
|
30
|
+
bgLightGreen: isColorSupported ? "\x1B[102m" : "",
|
|
31
|
+
bgLightYellow: isColorSupported ? "\x1B[103m" : "",
|
|
32
|
+
bgLightBlue: isColorSupported ? "\x1B[104m" : "",
|
|
33
|
+
bgLightMagenta: isColorSupported ? "\x1B[105m" : "",
|
|
34
|
+
bgLightCyan: isColorSupported ? "\x1B[106m" : "",
|
|
35
|
+
bold: isColorSupported ? "\x1B[1m" : "",
|
|
36
|
+
dim: isColorSupported ? "\x1B[2m" : "",
|
|
37
|
+
italic: isColorSupported ? "\x1B[3m" : "",
|
|
38
|
+
underline: isColorSupported ? "\x1B[4m" : "",
|
|
39
|
+
inverse: isColorSupported ? "\x1B[7m" : "",
|
|
40
|
+
hidden: isColorSupported ? "\x1B[8m" : "",
|
|
41
|
+
strikethrough: isColorSupported ? "\x1B[9m" : ""
|
|
42
|
+
};
|
|
43
|
+
function createColorFn(code, endCode = colors.reset) {
|
|
44
|
+
return (text) => {
|
|
45
|
+
if (!isColorSupported)
|
|
46
|
+
return String(text);
|
|
47
|
+
return `${code}${text}${endCode}`;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
export const black = createColorFn(colors.black), red = createColorFn(colors.red), green = createColorFn(colors.green), yellow = createColorFn(colors.yellow), blue = createColorFn(colors.blue), magenta = createColorFn(colors.magenta), cyan = createColorFn(colors.cyan), white = createColorFn(colors.white), gray = createColorFn(colors.gray), grey = gray, lightRed = createColorFn(colors.lightRed), lightGreen = createColorFn(colors.lightGreen), lightYellow = createColorFn(colors.lightYellow), lightBlue = createColorFn(colors.lightBlue), lightMagenta = createColorFn(colors.lightMagenta), lightCyan = createColorFn(colors.lightCyan), lightGray = createColorFn(colors.lightGray), lightGrey = lightGray, bgBlack = createColorFn(colors.bgBlack), bgRed = createColorFn(colors.bgRed), bgGreen = createColorFn(colors.bgGreen), bgYellow = createColorFn(colors.bgYellow), bgBlue = createColorFn(colors.bgBlue), bgMagenta = createColorFn(colors.bgMagenta), bgCyan = createColorFn(colors.bgCyan), bgWhite = createColorFn(colors.bgWhite), bgLightRed = createColorFn(colors.bgLightRed), bgLightGreen = createColorFn(colors.bgLightGreen), bgLightYellow = createColorFn(colors.bgLightYellow), bgLightBlue = createColorFn(colors.bgLightBlue), bgLightMagenta = createColorFn(colors.bgLightMagenta), bgLightCyan = createColorFn(colors.bgLightCyan), bold = createColorFn(colors.bold), dim = createColorFn(colors.dim), italic = createColorFn(colors.italic), underline = createColorFn(colors.underline), inverse = createColorFn(colors.inverse), hidden = createColorFn(colors.hidden), strikethrough = createColorFn(colors.strikethrough), reset = createColorFn(colors.reset, "");
|
|
51
|
+
export function stripColors(text) {
|
|
52
|
+
return text.replace(/\x1B\[\d+m/g, "");
|
|
53
|
+
}
|
|
54
|
+
export function supportsColor() {
|
|
55
|
+
return !!isColorSupported;
|
|
56
|
+
}
|
|
57
|
+
export default {
|
|
58
|
+
black,
|
|
59
|
+
red,
|
|
60
|
+
green,
|
|
61
|
+
yellow,
|
|
62
|
+
blue,
|
|
63
|
+
magenta,
|
|
64
|
+
cyan,
|
|
65
|
+
white,
|
|
66
|
+
gray,
|
|
67
|
+
grey,
|
|
68
|
+
lightRed,
|
|
69
|
+
lightGreen,
|
|
70
|
+
lightYellow,
|
|
71
|
+
lightBlue,
|
|
72
|
+
lightMagenta,
|
|
73
|
+
lightCyan,
|
|
74
|
+
lightGray,
|
|
75
|
+
lightGrey,
|
|
76
|
+
bgBlack,
|
|
77
|
+
bgRed,
|
|
78
|
+
bgGreen,
|
|
79
|
+
bgYellow,
|
|
80
|
+
bgBlue,
|
|
81
|
+
bgMagenta,
|
|
82
|
+
bgCyan,
|
|
83
|
+
bgWhite,
|
|
84
|
+
bgLightRed,
|
|
85
|
+
bgLightGreen,
|
|
86
|
+
bgLightYellow,
|
|
87
|
+
bgLightBlue,
|
|
88
|
+
bgLightMagenta,
|
|
89
|
+
bgLightCyan,
|
|
90
|
+
bold,
|
|
91
|
+
dim,
|
|
92
|
+
italic,
|
|
93
|
+
underline,
|
|
94
|
+
inverse,
|
|
95
|
+
hidden,
|
|
96
|
+
strikethrough,
|
|
97
|
+
reset,
|
|
98
|
+
stripColors,
|
|
99
|
+
supportsColor
|
|
100
|
+
};
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export {
|
|
2
|
+
defineApp,
|
|
3
|
+
defineCache,
|
|
4
|
+
defineCdn,
|
|
5
|
+
defineChat,
|
|
6
|
+
defineCli,
|
|
7
|
+
defineDatabase,
|
|
8
|
+
defineDependencies,
|
|
9
|
+
defineDns,
|
|
10
|
+
defineEmail,
|
|
11
|
+
defineEmailConfig,
|
|
12
|
+
defineGit,
|
|
13
|
+
defineHashing,
|
|
14
|
+
defineLibrary,
|
|
15
|
+
defineNotification,
|
|
16
|
+
definePayment,
|
|
17
|
+
defineQueue,
|
|
18
|
+
defineSearchEngine,
|
|
19
|
+
defineServices,
|
|
20
|
+
defineSms,
|
|
21
|
+
defineFilesystems,
|
|
22
|
+
defineUi
|
|
23
|
+
} from "@stacksjs/config";
|
package/dist/debounce.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
export function debounce(fn, wait = 0, options = {}) {
|
|
2
|
+
const { leading = !1, trailing = !0 } = options;
|
|
3
|
+
let timeout = null, lastArgs = null, lastThis = null, result;
|
|
4
|
+
const invokeFunc = () => {
|
|
5
|
+
if (lastArgs) {
|
|
6
|
+
result = fn.apply(lastThis, lastArgs);
|
|
7
|
+
lastArgs = null;
|
|
8
|
+
lastThis = null;
|
|
9
|
+
}
|
|
10
|
+
return result;
|
|
11
|
+
}, cancel = () => {
|
|
12
|
+
if (timeout) {
|
|
13
|
+
clearTimeout(timeout);
|
|
14
|
+
timeout = null;
|
|
15
|
+
}
|
|
16
|
+
lastArgs = null;
|
|
17
|
+
lastThis = null;
|
|
18
|
+
}, flush = () => {
|
|
19
|
+
if (timeout) {
|
|
20
|
+
clearTimeout(timeout);
|
|
21
|
+
timeout = null;
|
|
22
|
+
return invokeFunc();
|
|
23
|
+
}
|
|
24
|
+
return result;
|
|
25
|
+
}, debounced = function(...args) {
|
|
26
|
+
lastArgs = args;
|
|
27
|
+
lastThis = this;
|
|
28
|
+
const shouldCallNow = leading && !timeout;
|
|
29
|
+
if (timeout)
|
|
30
|
+
clearTimeout(timeout);
|
|
31
|
+
timeout = setTimeout(() => {
|
|
32
|
+
timeout = null;
|
|
33
|
+
if (trailing && lastArgs)
|
|
34
|
+
invokeFunc();
|
|
35
|
+
}, wait);
|
|
36
|
+
if (shouldCallNow)
|
|
37
|
+
return invokeFunc();
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
debounced.cancel = cancel;
|
|
41
|
+
debounced.flush = flush;
|
|
42
|
+
return debounced;
|
|
43
|
+
}
|
|
44
|
+
export function throttle(fn, wait = 0) {
|
|
45
|
+
let timeout = null, lastRun = 0, lastArgs = null, lastThis = null;
|
|
46
|
+
const invokeFunc = () => {
|
|
47
|
+
if (lastArgs) {
|
|
48
|
+
fn.apply(lastThis, lastArgs);
|
|
49
|
+
lastArgs = null;
|
|
50
|
+
lastThis = null;
|
|
51
|
+
lastRun = Date.now();
|
|
52
|
+
}
|
|
53
|
+
}, cancel = () => {
|
|
54
|
+
if (timeout) {
|
|
55
|
+
clearTimeout(timeout);
|
|
56
|
+
timeout = null;
|
|
57
|
+
}
|
|
58
|
+
lastArgs = null;
|
|
59
|
+
lastThis = null;
|
|
60
|
+
}, throttled = function(...args) {
|
|
61
|
+
lastArgs = args;
|
|
62
|
+
lastThis = this;
|
|
63
|
+
const timeSinceLastRun = Date.now() - lastRun;
|
|
64
|
+
if (timeSinceLastRun >= wait)
|
|
65
|
+
invokeFunc();
|
|
66
|
+
else if (!timeout)
|
|
67
|
+
timeout = setTimeout(() => {
|
|
68
|
+
timeout = null;
|
|
69
|
+
invokeFunc();
|
|
70
|
+
}, wait - timeSinceLastRun);
|
|
71
|
+
};
|
|
72
|
+
throttled.cancel = cancel;
|
|
73
|
+
return throttled;
|
|
74
|
+
}
|
|
75
|
+
export function delay(ms) {
|
|
76
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
77
|
+
}
|
package/dist/detect.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export function detectIndent(text) {
|
|
2
|
+
const lines = text.split(`
|
|
3
|
+
`), indents = [];
|
|
4
|
+
for (const line of lines) {
|
|
5
|
+
if (!line.trim())
|
|
6
|
+
continue;
|
|
7
|
+
const match = line.match(/^(\s+)/);
|
|
8
|
+
if (match && match[1] !== void 0)
|
|
9
|
+
indents.push(match[1]);
|
|
10
|
+
}
|
|
11
|
+
if (indents.length === 0)
|
|
12
|
+
return { amount: 0, type: null, indent: "" };
|
|
13
|
+
const indentCounts = new Map;
|
|
14
|
+
for (const indent of indents)
|
|
15
|
+
indentCounts.set(indent, (indentCounts.get(indent) || 0) + 1);
|
|
16
|
+
let mostCommon = "", maxCount = 0;
|
|
17
|
+
for (const [indent, count] of indentCounts)
|
|
18
|
+
if (count > maxCount) {
|
|
19
|
+
maxCount = count;
|
|
20
|
+
mostCommon = indent;
|
|
21
|
+
}
|
|
22
|
+
if (mostCommon.includes("\t"))
|
|
23
|
+
return {
|
|
24
|
+
amount: mostCommon.length,
|
|
25
|
+
type: "tab",
|
|
26
|
+
indent: mostCommon
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
amount: mostCommon.length,
|
|
30
|
+
type: "space",
|
|
31
|
+
indent: mostCommon
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export function detectNewline(text) {
|
|
35
|
+
if (!text)
|
|
36
|
+
return null;
|
|
37
|
+
if (text.includes(`\r
|
|
38
|
+
`))
|
|
39
|
+
return `\r
|
|
40
|
+
`;
|
|
41
|
+
if (text.includes(`
|
|
42
|
+
`))
|
|
43
|
+
return `
|
|
44
|
+
`;
|
|
45
|
+
if (text.includes("\r"))
|
|
46
|
+
return "\r";
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
export function detectNewlineGraceful(text, fallback = `
|
|
50
|
+
`) {
|
|
51
|
+
return detectNewline(text) || fallback;
|
|
52
|
+
}
|
|
53
|
+
export function normalizeNewlines(text, newline = `
|
|
54
|
+
`) {
|
|
55
|
+
return text.replace(/\r\n|\r|\n/g, newline);
|
|
56
|
+
}
|
|
57
|
+
export function countNewlines(text) {
|
|
58
|
+
const crlf = (text.match(/\r\n/g) || []).length, cr = (text.match(/\r(?!\n)/g) || []).length, lf = (text.match(/(?<!\r)\n/g) || []).length;
|
|
59
|
+
return {
|
|
60
|
+
crlf,
|
|
61
|
+
lf,
|
|
62
|
+
cr,
|
|
63
|
+
total: crlf + lf + cr
|
|
64
|
+
};
|
|
65
|
+
}
|
package/dist/equal.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getTypeName } from "@stacksjs/types";
|
|
2
|
+
export function isDeepEqual(value1, value2, seen = new WeakMap) {
|
|
3
|
+
if (value1 === value2)
|
|
4
|
+
return !0;
|
|
5
|
+
if (typeof value1 === "number" && typeof value2 === "number" && Number.isNaN(value1) && Number.isNaN(value2))
|
|
6
|
+
return !0;
|
|
7
|
+
const type1 = getTypeName(value1), type2 = getTypeName(value2);
|
|
8
|
+
if (type1 !== type2)
|
|
9
|
+
return !1;
|
|
10
|
+
if (value1 && typeof value1 === "object") {
|
|
11
|
+
if (seen.get(value1) === value2)
|
|
12
|
+
return !0;
|
|
13
|
+
seen.set(value1, value2);
|
|
14
|
+
}
|
|
15
|
+
if (type1 === "array") {
|
|
16
|
+
if (value1.length !== value2.length)
|
|
17
|
+
return !1;
|
|
18
|
+
return value1.every((item, i) => isDeepEqual(item, value2[i], seen));
|
|
19
|
+
}
|
|
20
|
+
if (type1 === "object") {
|
|
21
|
+
const keyArr = Object.keys(value1);
|
|
22
|
+
if (keyArr.length !== Object.keys(value2).length)
|
|
23
|
+
return !1;
|
|
24
|
+
return keyArr.every((key) => isDeepEqual(value1[key], value2[key], seen));
|
|
25
|
+
}
|
|
26
|
+
return Object.is(value1, value2);
|
|
27
|
+
}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export function getErrorMessage(e) {
|
|
2
|
+
if (e instanceof Error)
|
|
3
|
+
return e.message;
|
|
4
|
+
if (typeof e === "string")
|
|
5
|
+
return e;
|
|
6
|
+
if (typeof e === "number" || typeof e === "boolean")
|
|
7
|
+
return String(e);
|
|
8
|
+
if (e && typeof e === "object" && "message" in e && typeof e.message === "string")
|
|
9
|
+
return e.message;
|
|
10
|
+
if (e == null)
|
|
11
|
+
return "Unknown error";
|
|
12
|
+
try {
|
|
13
|
+
return String(e);
|
|
14
|
+
} catch {
|
|
15
|
+
return "Unknown error";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function getErrorStack(e) {
|
|
19
|
+
if (e instanceof Error)
|
|
20
|
+
return e.stack;
|
|
21
|
+
if (e && typeof e === "object" && "stack" in e && typeof e.stack === "string")
|
|
22
|
+
return e.stack;
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
export function getErrorCode(e) {
|
|
26
|
+
if (e && typeof e === "object" && "code" in e && typeof e.code === "string")
|
|
27
|
+
return e.code;
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
export function getErrorStatusCode(e) {
|
|
31
|
+
if (!e || typeof e !== "object")
|
|
32
|
+
return;
|
|
33
|
+
const obj = e;
|
|
34
|
+
if (typeof obj.statusCode === "number" && Number.isFinite(obj.statusCode))
|
|
35
|
+
return obj.statusCode;
|
|
36
|
+
if (typeof obj.status === "number" && Number.isFinite(obj.status))
|
|
37
|
+
return obj.status;
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
export function toError(e) {
|
|
41
|
+
if (e instanceof Error)
|
|
42
|
+
return e;
|
|
43
|
+
return Error(getErrorMessage(e), { cause: e });
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { getExportsSize } from "./size";
|
package/dist/find.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { italic } from "@stacksjs/cli";
|
|
5
|
+
import { log } from "@stacksjs/logging";
|
|
6
|
+
const targetFileName = "buddy", alwaysExcludePatterns = [
|
|
7
|
+
"node_modules",
|
|
8
|
+
"dist",
|
|
9
|
+
"vendor",
|
|
10
|
+
"storage/framework",
|
|
11
|
+
/.*out.*/,
|
|
12
|
+
/.*\/\..*/
|
|
13
|
+
], homeOnlyExcludePatterns = [
|
|
14
|
+
`${os.homedir()}/Documents`,
|
|
15
|
+
`${os.homedir()}/Pictures`,
|
|
16
|
+
`${os.homedir()}/Library`,
|
|
17
|
+
`${os.homedir()}/.Trash`
|
|
18
|
+
];
|
|
19
|
+
export async function findStacksProjects(dir, options) {
|
|
20
|
+
const dirWasExplicit = !!dir;
|
|
21
|
+
dir = dir || os.homedir();
|
|
22
|
+
const excludePatterns = dirWasExplicit ? alwaysExcludePatterns : [...alwaysExcludePatterns, ...homeOnlyExcludePatterns];
|
|
23
|
+
if (!options?.quiet) {
|
|
24
|
+
log.info(`Searching for Stacks projects in: ${italic(dir)}`);
|
|
25
|
+
log.info("This may take a few moments...");
|
|
26
|
+
console.log("");
|
|
27
|
+
console.log(italic(" Please note, while Stacks is searching for projects on your machine,"));
|
|
28
|
+
console.log(italic(" you may be asked for permissions to scan certain directories."));
|
|
29
|
+
console.log("");
|
|
30
|
+
log.debug(`Excluding directories: ${excludePatterns.join(", ")}`);
|
|
31
|
+
}
|
|
32
|
+
const foundProjects = await searchDirectory(dir, excludePatterns);
|
|
33
|
+
if (!foundProjects)
|
|
34
|
+
throw Error("No Stacks projects found");
|
|
35
|
+
return foundProjects;
|
|
36
|
+
}
|
|
37
|
+
async function searchDirectory(directory, excludePatterns) {
|
|
38
|
+
const foundProjects = [];
|
|
39
|
+
if (excludePatterns.some((pattern) => typeof pattern === "string" ? directory.includes(pattern) : pattern.test(directory)))
|
|
40
|
+
return foundProjects;
|
|
41
|
+
let items;
|
|
42
|
+
try {
|
|
43
|
+
items = await fs.readdir(directory, { withFileTypes: !0 });
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`Error reading directory ${directory}:`, error);
|
|
46
|
+
return foundProjects;
|
|
47
|
+
}
|
|
48
|
+
let buddyFileFound = !1, storageDirFound = !1;
|
|
49
|
+
for (const item of items) {
|
|
50
|
+
if (item.isFile() && item.name === targetFileName)
|
|
51
|
+
buddyFileFound = !0;
|
|
52
|
+
if (item.isDirectory()) {
|
|
53
|
+
const fullPath = path.join(directory, item.name);
|
|
54
|
+
if (item.name === "storage") {
|
|
55
|
+
const storagePath = path.join(fullPath, "framework/core/buddy");
|
|
56
|
+
try {
|
|
57
|
+
await fs.access(storagePath);
|
|
58
|
+
storageDirFound = !0;
|
|
59
|
+
} catch {}
|
|
60
|
+
}
|
|
61
|
+
const subDirProjects = await searchDirectory(fullPath, excludePatterns);
|
|
62
|
+
foundProjects.push(...subDirProjects);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (buddyFileFound && storageDirFound)
|
|
66
|
+
foundProjects.push(directory);
|
|
67
|
+
return foundProjects;
|
|
68
|
+
}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { handleError } from "@stacksjs/error-handling";
|
|
3
|
+
export function isGitClean() {
|
|
4
|
+
try {
|
|
5
|
+
execSync("git diff-index --quiet HEAD --");
|
|
6
|
+
return !0;
|
|
7
|
+
} catch (error) {
|
|
8
|
+
handleError(error);
|
|
9
|
+
return !1;
|
|
10
|
+
}
|
|
11
|
+
}
|
package/dist/glob.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { glob } from '@stacksjs/storage';
|
package/dist/glob.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { glob } from "@stacksjs/storage";
|
package/dist/hash.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { config } from "@stacksjs/config";
|
|
2
|
+
import { log } from "@stacksjs/logging";
|
|
3
|
+
import { path } from "@stacksjs/path";
|
|
4
|
+
import { hashPaths } from "@stacksjs/storage";
|
|
5
|
+
export function originRequestFunctionHash() {
|
|
6
|
+
try {
|
|
7
|
+
return hashPaths(path.cloudPath("src/edge"));
|
|
8
|
+
} catch (error) {
|
|
9
|
+
log.error("Are we in a Docker container? Failed to hash paths. Error below:");
|
|
10
|
+
log.error(error);
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function websiteSourceHash() {
|
|
15
|
+
const docsSrc = [
|
|
16
|
+
path.projectPath("docs"),
|
|
17
|
+
path.frameworkPath("docs/dist")
|
|
18
|
+
], websiteSrc = [
|
|
19
|
+
path.projectPath("resources/views"),
|
|
20
|
+
path.projectPath("resources/assets"),
|
|
21
|
+
path.projectPath("resources/lang"),
|
|
22
|
+
path.projectPath("resources/functions"),
|
|
23
|
+
path.projectPath("resources/components"),
|
|
24
|
+
path.projectPath("resources/modules"),
|
|
25
|
+
path.projectPath("resources/stores"),
|
|
26
|
+
path.frameworkPath("views/web")
|
|
27
|
+
];
|
|
28
|
+
return config.app.docMode === !0 ? hashPaths(docsSrc) : hashPaths(websiteSrc);
|
|
29
|
+
}
|
|
30
|
+
export function docsSourceHash() {
|
|
31
|
+
const docsSrc = [
|
|
32
|
+
path.projectPath("docs"),
|
|
33
|
+
path.frameworkPath("docs/dist")
|
|
34
|
+
];
|
|
35
|
+
return hashPaths(docsSrc);
|
|
36
|
+
}
|
package/dist/helpers.js
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { runAction } from "@stacksjs/actions";
|
|
2
|
+
import { log, runCommand } from "@stacksjs/cli";
|
|
3
|
+
import { app, ui } from "@stacksjs/config";
|
|
4
|
+
import { Action } from "@stacksjs/enums";
|
|
5
|
+
import { err, handleError, ok } from "@stacksjs/error-handling";
|
|
6
|
+
import { frameworkPath, projectPath } from "@stacksjs/path";
|
|
7
|
+
import { fs, readJsonFile, readPackageJson, readTextFile, writeTextFile } from "@stacksjs/storage";
|
|
8
|
+
export async function packageManager() {
|
|
9
|
+
const { packageManager } = await readPackageJson(frameworkPath("package.json"));
|
|
10
|
+
return packageManager;
|
|
11
|
+
}
|
|
12
|
+
export async function initProject() {
|
|
13
|
+
if (app.env !== "production")
|
|
14
|
+
log.info("Project not yet initialized, generating application key...");
|
|
15
|
+
else
|
|
16
|
+
handleError("Please run `buddy key:generate` to generate an application key");
|
|
17
|
+
const result = await runAction(Action.KeyGenerate, { cwd: projectPath() });
|
|
18
|
+
if (result.isErr)
|
|
19
|
+
return err(handleError(result.error));
|
|
20
|
+
log.info("Application key generated.");
|
|
21
|
+
return ok(result.value);
|
|
22
|
+
}
|
|
23
|
+
export async function ensureProjectIsInitialized() {
|
|
24
|
+
if (fs.existsSync(projectPath(".env")))
|
|
25
|
+
return await isAppKeySet();
|
|
26
|
+
if (fs.existsSync(projectPath(".env.example")))
|
|
27
|
+
fs.copyFileSync(projectPath(".env.example"), projectPath(".env"));
|
|
28
|
+
else
|
|
29
|
+
console.error("no .env.example file found");
|
|
30
|
+
return await isAppKeySet();
|
|
31
|
+
}
|
|
32
|
+
export async function installIfVersionMismatch() {}
|
|
33
|
+
export async function frameworkVersion() {
|
|
34
|
+
return (await readPackageJson(frameworkPath("package.json"))).version;
|
|
35
|
+
}
|
|
36
|
+
export async function isAppKeySet() {
|
|
37
|
+
const appKey = (await readTextFile(".env", projectPath())).data.split(`
|
|
38
|
+
`).find((line) => line.startsWith("APP_KEY="));
|
|
39
|
+
return !!(appKey && appKey.length > 16);
|
|
40
|
+
}
|
|
41
|
+
export function determineResetPreset(preset) {
|
|
42
|
+
if (preset === void 0 && ui.reset)
|
|
43
|
+
preset = ui.reset;
|
|
44
|
+
if (preset === null)
|
|
45
|
+
return [];
|
|
46
|
+
const resetImport = {
|
|
47
|
+
tailwind: 'import { tailwindPreflight as reset } from "@cwcss/crosswind"',
|
|
48
|
+
preflight: 'import { tailwindPreflight as reset } from "@cwcss/crosswind"',
|
|
49
|
+
forms: 'import { tailwindFormsPreflight as reset } from "@cwcss/crosswind"'
|
|
50
|
+
}[preset ?? "tailwind"];
|
|
51
|
+
return resetImport ? [resetImport] : [];
|
|
52
|
+
}
|
|
53
|
+
export function isManifest(obj) {
|
|
54
|
+
return obj && typeof obj === "object" && isOptionalString(obj.name) && isOptionalString(obj.version) && isOptionalString(obj.description);
|
|
55
|
+
}
|
|
56
|
+
export function isOptionalString(value) {
|
|
57
|
+
const type = typeof value;
|
|
58
|
+
return value === null || type === "undefined" || type === "string";
|
|
59
|
+
}
|
|
60
|
+
export async function setEnvValue(key, value) {
|
|
61
|
+
const file = await readTextFile(projectPath(".env")), escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), keyPattern = new RegExp(`^${escapedKey}=.*$`, "m"), nextValue = `${key}=${value}`, data = keyPattern.test(file.data) ? file.data.replace(keyPattern, nextValue) : `${file.data}${file.data.endsWith(`
|
|
62
|
+
`) ? "" : `
|
|
63
|
+
`}${nextValue}
|
|
64
|
+
`;
|
|
65
|
+
await writeTextFile({
|
|
66
|
+
path: projectPath(".env"),
|
|
67
|
+
data
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export async function runNpmScript(script, options) {
|
|
71
|
+
const { data: manifest } = await readJsonFile("package.json", frameworkPath());
|
|
72
|
+
if (isManifest(manifest) && hasScript(manifest, script))
|
|
73
|
+
return await runCommand(`bun run ${script}`, options);
|
|
74
|
+
return err(handleError(`The ${script} script does not exist in the package.json file.`));
|
|
75
|
+
}
|
|
76
|
+
export function hasScript(manifest, script) {
|
|
77
|
+
const scripts = manifest.scripts;
|
|
78
|
+
if (scripts && typeof scripts === "object")
|
|
79
|
+
return Boolean(scripts[script]);
|
|
80
|
+
return !1;
|
|
81
|
+
}
|
|
82
|
+
export function parseYaml(content) {
|
|
83
|
+
return Bun.YAML.parse(content);
|
|
84
|
+
}
|
|
85
|
+
export function determineDebugLevel(options) {
|
|
86
|
+
if (options?.verbose === !0)
|
|
87
|
+
return !0;
|
|
88
|
+
return app.debug === !0;
|
|
89
|
+
}
|
|
90
|
+
export function isIpv6(address) {
|
|
91
|
+
return address.family === "IPv6" || address.family === 6;
|
|
92
|
+
}
|
|
93
|
+
export function dumpYaml(content) {
|
|
94
|
+
const yaml = Bun.YAML;
|
|
95
|
+
if (typeof yaml.stringify === "function")
|
|
96
|
+
return yaml.stringify(content);
|
|
97
|
+
return JSON.stringify(content, null, 2);
|
|
98
|
+
}
|
|
99
|
+
export function loadYaml(content) {
|
|
100
|
+
return Bun.YAML.parse(content);
|
|
101
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
export * from "./clean";
|
|
2
|
+
export * from "./config";
|
|
3
|
+
export * from "./equal";
|
|
4
|
+
export * from "./errors";
|
|
5
|
+
export * from "./export-size";
|
|
6
|
+
export * from "./find";
|
|
7
|
+
export * from "./git";
|
|
8
|
+
export * from "./hash";
|
|
9
|
+
export * from "./helpers";
|
|
10
|
+
export * from "./macroable";
|
|
11
|
+
export * from "./safe-json";
|
|
12
|
+
export * from "./versions";
|
|
13
|
+
export * as browserUtils from "@stacksjs/browser";
|
|
14
|
+
export { clamp, notNullish, retry, useOnline } from "@stacksjs/browser";
|
|
15
|
+
export * from "./merge";
|
|
16
|
+
export * from "./detect";
|
|
17
|
+
export * from "./debounce";
|
|
18
|
+
export * from "./bytes";
|
|
19
|
+
export * from "./colors";
|
|
20
|
+
export * from "./markdown";
|
|
21
|
+
export * from "./size";
|
|
22
|
+
export * from "./observer";
|
|
23
|
+
export * from "./pipeline";
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
export class Macroable {
|
|
2
|
+
static macros = new Map;
|
|
3
|
+
static macro(name, fn, replace = !1) {
|
|
4
|
+
if (this.macros.has(name) && !replace)
|
|
5
|
+
throw Error(`Macro "${name}" is already registered`);
|
|
6
|
+
this.macros.set(name, fn);
|
|
7
|
+
Object.defineProperty(this.prototype, name, {
|
|
8
|
+
value: fn,
|
|
9
|
+
writable: !0,
|
|
10
|
+
configurable: !0,
|
|
11
|
+
enumerable: !1
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
static mixin(obj, replace = !0) {
|
|
15
|
+
const methods = Object.getOwnPropertyNames(obj);
|
|
16
|
+
for (const method of methods) {
|
|
17
|
+
if (method === "constructor")
|
|
18
|
+
continue;
|
|
19
|
+
if (this.macros.has(method) && !replace)
|
|
20
|
+
continue;
|
|
21
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, method);
|
|
22
|
+
if (descriptor && typeof descriptor.value === "function")
|
|
23
|
+
this.macro(method, descriptor.value, replace);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
static hasMacro(name) {
|
|
27
|
+
return this.macros.has(name);
|
|
28
|
+
}
|
|
29
|
+
static flushMacros() {
|
|
30
|
+
for (const name of this.macros.keys())
|
|
31
|
+
delete this.prototype[name];
|
|
32
|
+
this.macros.clear();
|
|
33
|
+
}
|
|
34
|
+
static getMacros() {
|
|
35
|
+
return Array.from(this.macros.keys());
|
|
36
|
+
}
|
|
37
|
+
callMacro(name, ...args) {
|
|
38
|
+
const macro = this.constructor.macros.get(name);
|
|
39
|
+
if (!macro)
|
|
40
|
+
throw Error(`Macro "${name}" is not registered`);
|
|
41
|
+
return macro.apply(this, args);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function createMacroable(BaseClass = class {
|
|
45
|
+
}) {
|
|
46
|
+
return class extends BaseClass {
|
|
47
|
+
static macros = new Map;
|
|
48
|
+
static macro(name, fn, replace = !1) {
|
|
49
|
+
if (this.macros.has(name) && !replace)
|
|
50
|
+
throw Error(`Macro "${name}" is already registered`);
|
|
51
|
+
this.macros.set(name, fn);
|
|
52
|
+
Object.defineProperty(this.prototype, name, {
|
|
53
|
+
value: fn,
|
|
54
|
+
writable: !0,
|
|
55
|
+
configurable: !0,
|
|
56
|
+
enumerable: !1
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
static mixin(obj, replace = !0) {
|
|
60
|
+
const methods = Object.getOwnPropertyNames(obj);
|
|
61
|
+
for (const method of methods) {
|
|
62
|
+
if (method === "constructor")
|
|
63
|
+
continue;
|
|
64
|
+
if (this.macros.has(method) && !replace)
|
|
65
|
+
continue;
|
|
66
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, method);
|
|
67
|
+
if (descriptor && typeof descriptor.value === "function")
|
|
68
|
+
this.macro(method, descriptor.value, replace);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
static hasMacro(name) {
|
|
72
|
+
return this.macros.has(name);
|
|
73
|
+
}
|
|
74
|
+
static flushMacros() {
|
|
75
|
+
for (const name of this.macros.keys())
|
|
76
|
+
delete this.prototype[name];
|
|
77
|
+
this.macros.clear();
|
|
78
|
+
}
|
|
79
|
+
static getMacros() {
|
|
80
|
+
return Array.from(this.macros.keys());
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function macroable(target) {
|
|
85
|
+
const macros = new Map;
|
|
86
|
+
target.macro = function(name, fn, replace = !1) {
|
|
87
|
+
if (macros.has(name) && !replace)
|
|
88
|
+
throw Error(`Macro "${name}" is already registered`);
|
|
89
|
+
macros.set(name, fn);
|
|
90
|
+
Object.defineProperty(target.prototype, name, {
|
|
91
|
+
value: fn,
|
|
92
|
+
writable: !0,
|
|
93
|
+
configurable: !0,
|
|
94
|
+
enumerable: !1
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
target.mixin = function(obj, replace = !0) {
|
|
98
|
+
const methods = Object.getOwnPropertyNames(obj);
|
|
99
|
+
for (const method of methods) {
|
|
100
|
+
if (method === "constructor")
|
|
101
|
+
continue;
|
|
102
|
+
if (macros.has(method) && !replace)
|
|
103
|
+
continue;
|
|
104
|
+
const descriptor = Object.getOwnPropertyDescriptor(obj, method);
|
|
105
|
+
if (descriptor && typeof descriptor.value === "function")
|
|
106
|
+
target.macro(method, descriptor.value, replace);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
target.hasMacro = function(name) {
|
|
110
|
+
return macros.has(name);
|
|
111
|
+
};
|
|
112
|
+
target.flushMacros = function() {
|
|
113
|
+
for (const name of macros.keys())
|
|
114
|
+
delete target.prototype[name];
|
|
115
|
+
macros.clear();
|
|
116
|
+
};
|
|
117
|
+
target.getMacros = function() {
|
|
118
|
+
return Array.from(macros.keys());
|
|
119
|
+
};
|
|
120
|
+
return target;
|
|
121
|
+
}
|
package/dist/markdown.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
export function markdownTable(table, options = {}) {
|
|
2
|
+
const {
|
|
3
|
+
align = [],
|
|
4
|
+
padding = !0,
|
|
5
|
+
delimiter = "|",
|
|
6
|
+
delimiterStart = !0,
|
|
7
|
+
delimiterEnd = !0,
|
|
8
|
+
alignDelimiter = "-"
|
|
9
|
+
} = options;
|
|
10
|
+
if (!table || table.length === 0)
|
|
11
|
+
return "";
|
|
12
|
+
const normalized = table.map((row) => row.map((cell) => {
|
|
13
|
+
if (cell === null || cell === void 0)
|
|
14
|
+
return "";
|
|
15
|
+
return String(cell);
|
|
16
|
+
})), columnCount = Math.max(...normalized.map((row) => row.length)), columnWidths = Array.from({ length: columnCount }).fill(0);
|
|
17
|
+
for (const row of normalized)
|
|
18
|
+
for (let i = 0;i < row.length; i++) {
|
|
19
|
+
const cellLength = row[i]?.length ?? 0;
|
|
20
|
+
if (cellLength > (columnWidths[i] ?? 0))
|
|
21
|
+
columnWidths[i] = cellLength;
|
|
22
|
+
}
|
|
23
|
+
const rows = [];
|
|
24
|
+
if (normalized.length > 0) {
|
|
25
|
+
const header = normalized[0] ?? [];
|
|
26
|
+
rows.push(buildRow(header, columnWidths, padding, delimiter, delimiterStart, delimiterEnd));
|
|
27
|
+
const separatorCells = columnWidths.map((width, index) => {
|
|
28
|
+
const alignment = normalizeAlignment(align[index]);
|
|
29
|
+
return buildSeparator(width, alignment, alignDelimiter);
|
|
30
|
+
});
|
|
31
|
+
rows.push(buildRow(separatorCells, columnWidths, padding, delimiter, delimiterStart, delimiterEnd));
|
|
32
|
+
for (let i = 1;i < normalized.length; i++) {
|
|
33
|
+
const dataRow = normalized[i] ?? [];
|
|
34
|
+
rows.push(buildRow(dataRow, columnWidths, padding, delimiter, delimiterStart, delimiterEnd));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return rows.join(`
|
|
38
|
+
`);
|
|
39
|
+
}
|
|
40
|
+
function buildRow(cells, columnWidths, padding, delimiter, delimiterStart, delimiterEnd) {
|
|
41
|
+
const paddedCells = cells.map((cell, index) => {
|
|
42
|
+
const width = columnWidths[index] ?? 0;
|
|
43
|
+
return cell.padEnd(width, " ");
|
|
44
|
+
}), space = padding ? " " : "";
|
|
45
|
+
let row = paddedCells.map((cell) => `${space}${cell}${space}`).join(delimiter);
|
|
46
|
+
if (delimiterStart)
|
|
47
|
+
row = delimiter + row;
|
|
48
|
+
if (delimiterEnd)
|
|
49
|
+
row = row + delimiter;
|
|
50
|
+
return row;
|
|
51
|
+
}
|
|
52
|
+
function buildSeparator(width, alignment, char) {
|
|
53
|
+
const minWidth = alignment === "center" ? 3 : alignment ? 2 : 1;
|
|
54
|
+
if (width < minWidth)
|
|
55
|
+
width = minWidth;
|
|
56
|
+
let separator = char.repeat(width);
|
|
57
|
+
if (alignment === "left")
|
|
58
|
+
separator = `:${separator.slice(1)}`;
|
|
59
|
+
else if (alignment === "right")
|
|
60
|
+
separator = separator.slice(0, -1) + ":";
|
|
61
|
+
else if (alignment === "center")
|
|
62
|
+
separator = `:${separator.slice(2)}:`;
|
|
63
|
+
return separator;
|
|
64
|
+
}
|
|
65
|
+
function normalizeAlignment(align) {
|
|
66
|
+
if (!align)
|
|
67
|
+
return null;
|
|
68
|
+
switch (align) {
|
|
69
|
+
case "l":
|
|
70
|
+
case "left":
|
|
71
|
+
return "left";
|
|
72
|
+
case "c":
|
|
73
|
+
case "center":
|
|
74
|
+
return "center";
|
|
75
|
+
case "r":
|
|
76
|
+
case "right":
|
|
77
|
+
return "right";
|
|
78
|
+
default:
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export function markdownTableFromObjects(objects, options = {}) {
|
|
83
|
+
if (!objects || objects.length === 0)
|
|
84
|
+
return "";
|
|
85
|
+
const keys = Array.from(new Set(objects.flatMap((obj) => Object.keys(obj)))), table = [
|
|
86
|
+
keys,
|
|
87
|
+
...objects.map((obj) => keys.map((key) => obj[key]))
|
|
88
|
+
];
|
|
89
|
+
return markdownTable(table, options);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { markdownTable as default };
|
package/dist/merge.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function merge(...objects) {
|
|
2
|
+
const result = {};
|
|
3
|
+
for (const obj of objects) {
|
|
4
|
+
if (!obj || typeof obj !== "object")
|
|
5
|
+
continue;
|
|
6
|
+
for (const key in obj) {
|
|
7
|
+
const value = obj[key], existing = result[key];
|
|
8
|
+
if (value === void 0)
|
|
9
|
+
continue;
|
|
10
|
+
if (Array.isArray(value))
|
|
11
|
+
result[key] = Array.isArray(existing) ? [...existing, ...value] : [...value];
|
|
12
|
+
else if (value && typeof value === "object" && !isSpecialObject(value))
|
|
13
|
+
result[key] = merge(existing || {}, value);
|
|
14
|
+
else
|
|
15
|
+
result[key] = value;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
export function createMerger(defaults) {
|
|
21
|
+
return (...objects) => {
|
|
22
|
+
return merge(defaults, ...objects);
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function mergeDefaults(obj, ...defaults) {
|
|
26
|
+
return merge({}, ...defaults, obj);
|
|
27
|
+
}
|
|
28
|
+
function isSpecialObject(obj) {
|
|
29
|
+
if (obj instanceof Date)
|
|
30
|
+
return !0;
|
|
31
|
+
if (obj instanceof RegExp)
|
|
32
|
+
return !0;
|
|
33
|
+
if (obj instanceof Error)
|
|
34
|
+
return !0;
|
|
35
|
+
if (obj instanceof Promise)
|
|
36
|
+
return !0;
|
|
37
|
+
if (obj instanceof Map)
|
|
38
|
+
return !0;
|
|
39
|
+
if (obj instanceof Set)
|
|
40
|
+
return !0;
|
|
41
|
+
if (obj instanceof WeakMap)
|
|
42
|
+
return !0;
|
|
43
|
+
if (obj instanceof WeakSet)
|
|
44
|
+
return !0;
|
|
45
|
+
if (ArrayBuffer.isView(obj))
|
|
46
|
+
return !0;
|
|
47
|
+
return !1;
|
|
48
|
+
}
|
|
49
|
+
export const defu = mergeDefaults, defuArrayFn = merge;
|
|
50
|
+
|
|
51
|
+
export { merge as default };
|
package/dist/observer.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export function isResizeObserverSupported() {
|
|
2
|
+
return typeof window < "u" && "ResizeObserver" in window;
|
|
3
|
+
}
|
|
4
|
+
export function getResizeObserver() {
|
|
5
|
+
if (isResizeObserverSupported())
|
|
6
|
+
return window.ResizeObserver;
|
|
7
|
+
return class ResizeObserverPolyfill {
|
|
8
|
+
callback;
|
|
9
|
+
observedElements = new Set;
|
|
10
|
+
rafId = null;
|
|
11
|
+
constructor(callback) {
|
|
12
|
+
this.callback = callback;
|
|
13
|
+
}
|
|
14
|
+
observe(target) {
|
|
15
|
+
if (!this.observedElements.has(target)) {
|
|
16
|
+
this.observedElements.add(target);
|
|
17
|
+
this.scheduleCheck();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
unobserve(target) {
|
|
21
|
+
this.observedElements.delete(target);
|
|
22
|
+
if (this.observedElements.size === 0 && this.rafId !== null) {
|
|
23
|
+
(typeof cancelAnimationFrame < "u" ? cancelAnimationFrame : clearTimeout)(this.rafId);
|
|
24
|
+
this.rafId = null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
disconnect() {
|
|
28
|
+
this.observedElements.clear();
|
|
29
|
+
if (this.rafId !== null) {
|
|
30
|
+
(typeof cancelAnimationFrame < "u" ? cancelAnimationFrame : clearTimeout)(this.rafId);
|
|
31
|
+
this.rafId = null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
scheduleCheck() {
|
|
35
|
+
if (this.rafId !== null)
|
|
36
|
+
return;
|
|
37
|
+
const raf = typeof requestAnimationFrame < "u" ? requestAnimationFrame : setTimeout;
|
|
38
|
+
this.rafId = raf(() => {
|
|
39
|
+
this.check();
|
|
40
|
+
this.rafId = null;
|
|
41
|
+
if (this.observedElements.size > 0)
|
|
42
|
+
this.scheduleCheck();
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
check() {
|
|
46
|
+
const entries = [];
|
|
47
|
+
for (const element of this.observedElements) {
|
|
48
|
+
const rect = element.getBoundingClientRect(), entry = {
|
|
49
|
+
target: element,
|
|
50
|
+
contentRect: rect,
|
|
51
|
+
borderBoxSize: [{ inlineSize: rect.width, blockSize: rect.height }],
|
|
52
|
+
contentBoxSize: [{ inlineSize: rect.width, blockSize: rect.height }],
|
|
53
|
+
devicePixelContentBoxSize: [{ inlineSize: rect.width, blockSize: rect.height }]
|
|
54
|
+
};
|
|
55
|
+
entries.push(entry);
|
|
56
|
+
}
|
|
57
|
+
if (entries.length > 0)
|
|
58
|
+
this.callback(entries, this);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export function createResizeObserver(callback, target) {
|
|
63
|
+
const observer = new (getResizeObserver())(callback), targets = Array.isArray(target) ? target : [target];
|
|
64
|
+
for (const element of targets)
|
|
65
|
+
observer.observe(element);
|
|
66
|
+
return () => {
|
|
67
|
+
observer.disconnect();
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function observeElementSize(element, callback) {
|
|
71
|
+
return createResizeObserver((entries) => {
|
|
72
|
+
const entry = entries.find((e) => e.target === element);
|
|
73
|
+
if (entry)
|
|
74
|
+
callback(entry);
|
|
75
|
+
}, element);
|
|
76
|
+
}
|
|
77
|
+
export const ResizeObserver = getResizeObserver();
|
|
78
|
+
export default ResizeObserver;
|
package/dist/pipeline.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class Pipeline {
|
|
2
|
+
passable;
|
|
3
|
+
pipes = [];
|
|
4
|
+
method = "handle";
|
|
5
|
+
static send(passable) {
|
|
6
|
+
const pipeline = new Pipeline;
|
|
7
|
+
pipeline.passable = passable;
|
|
8
|
+
return pipeline;
|
|
9
|
+
}
|
|
10
|
+
through(pipes) {
|
|
11
|
+
this.pipes = pipes;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
pipe(...pipes) {
|
|
15
|
+
this.pipes.push(...pipes);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
via(method) {
|
|
19
|
+
this.method = method;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
then(destination) {
|
|
23
|
+
return this.pipes.reduceRight((next, pipe) => {
|
|
24
|
+
return (passable) => {
|
|
25
|
+
if (typeof pipe === "function")
|
|
26
|
+
return pipe(passable, next);
|
|
27
|
+
const handler = pipe[this.method];
|
|
28
|
+
if (typeof handler === "function")
|
|
29
|
+
return handler.call(pipe, passable, next);
|
|
30
|
+
return next(passable);
|
|
31
|
+
};
|
|
32
|
+
}, destination)(this.passable);
|
|
33
|
+
}
|
|
34
|
+
thenReturn() {
|
|
35
|
+
return this.then((passable) => passable);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export function safeJsonParse(text, defaultValue) {
|
|
2
|
+
if (typeof text !== "string" || text.length === 0)
|
|
3
|
+
return defaultValue;
|
|
4
|
+
try {
|
|
5
|
+
return JSON.parse(text);
|
|
6
|
+
} catch {
|
|
7
|
+
return defaultValue;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function safeJsonParseResult(text) {
|
|
11
|
+
if (typeof text !== "string")
|
|
12
|
+
return { ok: !1, reason: "not-string" };
|
|
13
|
+
if (text.length === 0)
|
|
14
|
+
return { ok: !1, reason: "empty" };
|
|
15
|
+
try {
|
|
16
|
+
return { ok: !0, value: JSON.parse(text) };
|
|
17
|
+
} catch (err) {
|
|
18
|
+
return { ok: !1, reason: "malformed", error: err };
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function safeJsonStringify(value, space) {
|
|
22
|
+
const seen = new WeakSet;
|
|
23
|
+
return JSON.stringify(value, (_key, v) => {
|
|
24
|
+
if (typeof v === "bigint")
|
|
25
|
+
return v.toString();
|
|
26
|
+
if (v && typeof v === "object") {
|
|
27
|
+
if (seen.has(v))
|
|
28
|
+
return "[Circular]";
|
|
29
|
+
seen.add(v);
|
|
30
|
+
}
|
|
31
|
+
return v;
|
|
32
|
+
}, space);
|
|
33
|
+
}
|
package/dist/size.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { formatBytes } from "./bytes";
|
|
4
|
+
export async function getFileSize(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
return (await stat(filePath)).size;
|
|
7
|
+
} catch {
|
|
8
|
+
return 0;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export async function getExportsSize(distPath) {
|
|
12
|
+
const exports = [];
|
|
13
|
+
let totalSize = 0;
|
|
14
|
+
try {
|
|
15
|
+
const files = await getAllJsFiles(distPath);
|
|
16
|
+
for (const file of files) {
|
|
17
|
+
const size = await getFileSize(file.path);
|
|
18
|
+
totalSize += size;
|
|
19
|
+
exports.push({
|
|
20
|
+
name: file.name,
|
|
21
|
+
size,
|
|
22
|
+
readable: formatBytes(size)
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
} catch (error) {}
|
|
26
|
+
return {
|
|
27
|
+
totalSize,
|
|
28
|
+
totalReadable: formatBytes(totalSize),
|
|
29
|
+
exports: exports.sort((a, b) => b.size - a.size)
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
async function getAllJsFiles(dir) {
|
|
33
|
+
const files = [];
|
|
34
|
+
try {
|
|
35
|
+
const entries = await Bun.$.throws(!1)`find ${dir} -type f \\( -name "*.js" -o -name "*.mjs" -o -name "*.cjs" \\)`.text();
|
|
36
|
+
for (const entry of entries.split(`
|
|
37
|
+
`).filter(Boolean)) {
|
|
38
|
+
const name = entry.replace(dir, "").replace(/^\//, "");
|
|
39
|
+
files.push({ name, path: entry });
|
|
40
|
+
}
|
|
41
|
+
} catch {}
|
|
42
|
+
return files;
|
|
43
|
+
}
|
|
44
|
+
export function estimateGzipSize(size) {
|
|
45
|
+
return Math.floor(size * 0.3);
|
|
46
|
+
}
|
|
47
|
+
export function estimateBrotliSize(size) {
|
|
48
|
+
return Math.floor(size * 0.25);
|
|
49
|
+
}
|
|
50
|
+
export function formatExportSizes(result) {
|
|
51
|
+
if (result.exports.length === 0)
|
|
52
|
+
return "No exports found";
|
|
53
|
+
const lines = ["Export Sizes:", ""], maxNameLength = Math.max(...result.exports.map((e) => e.name.length));
|
|
54
|
+
for (const exp of result.exports) {
|
|
55
|
+
const name = exp.name.padEnd(maxNameLength, " ");
|
|
56
|
+
lines.push(` ${name} ${exp.readable}`);
|
|
57
|
+
}
|
|
58
|
+
lines.push("");
|
|
59
|
+
lines.push(`Total: ${result.totalReadable}`);
|
|
60
|
+
lines.push(`Estimated gzipped: ${formatBytes(estimateGzipSize(result.totalSize))}`);
|
|
61
|
+
lines.push(`Estimated brotli: ${formatBytes(estimateBrotliSize(result.totalSize))}`);
|
|
62
|
+
return lines.join(`
|
|
63
|
+
`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { getExportsSize as default };
|
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
var __dirname = "";
|
|
2
|
+
import { resolve } from "@stacksjs/path";
|
|
3
|
+
import { fs } from "@stacksjs/storage";
|
|
4
|
+
import { kebabCase } from "@stacksjs/strings";
|
|
5
|
+
const ignore = ["readme-md"];
|
|
6
|
+
export const components = fs.readdirSync(resolve(__dirname, "./resources/components")).map((item) => kebabCase(item.replace(/\.(stx|vue)/g, ""))).filter((item) => !ignore.includes(item)), functions = fs.readdirSync(resolve(__dirname, "./resources/functions")).map((item) => kebabCase(item.replace(/.ts/g, ""))).filter((item) => !ignore.includes(item));
|
package/dist/versions.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { version } from "../package.json";
|
|
2
|
+
export const semver = Bun.semver;
|
|
3
|
+
export function isVersionGreaterThan(version, compareVersion) {
|
|
4
|
+
return Bun.semver.order(version, compareVersion) === 1;
|
|
5
|
+
}
|
|
6
|
+
export function isVersionLessThan(version, compareVersion) {
|
|
7
|
+
return Bun.semver.order(version, compareVersion) === -1;
|
|
8
|
+
}
|
|
9
|
+
export function isVersionEqual(version, compareVersion) {
|
|
10
|
+
return Bun.semver.order(version, compareVersion) === 0;
|
|
11
|
+
}
|
|
12
|
+
export function isVersionGreaterThanOrEqual(version, compareVersion) {
|
|
13
|
+
return Bun.semver.order(version, compareVersion) >= 0;
|
|
14
|
+
}
|
|
15
|
+
export function isVersionLessThanOrEqual(version, compareVersion) {
|
|
16
|
+
return Bun.semver.order(version, compareVersion) <= 0;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { version };
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@stacksjs/utils",
|
|
3
3
|
"type": "module",
|
|
4
4
|
"sideEffects": false,
|
|
5
|
-
"version": "0.70.
|
|
5
|
+
"version": "0.70.90",
|
|
6
6
|
"description": "The Stacks helper functions.",
|
|
7
7
|
"author": "Chris Breuer",
|
|
8
8
|
"contributors": [
|
|
@@ -58,20 +58,20 @@
|
|
|
58
58
|
"size": "bun scripts/export-size.ts"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@stacksjs/browser": "0.70.
|
|
61
|
+
"@stacksjs/browser": "0.70.90"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@stacksjs/actions": "0.70.
|
|
65
|
-
"@stacksjs/arrays": "0.70.
|
|
66
|
-
"@stacksjs/cli": "0.70.
|
|
67
|
-
"@stacksjs/config": "0.70.
|
|
64
|
+
"@stacksjs/actions": "0.70.90",
|
|
65
|
+
"@stacksjs/arrays": "0.70.90",
|
|
66
|
+
"@stacksjs/cli": "0.70.90",
|
|
67
|
+
"@stacksjs/config": "0.70.90",
|
|
68
68
|
"better-dx": "^0.2.16",
|
|
69
69
|
"filesize": "^11.0.22",
|
|
70
70
|
"markdown-table": "^3.0.4",
|
|
71
|
-
"@stacksjs/lint": "0.70.
|
|
72
|
-
"@stacksjs/path": "0.70.
|
|
73
|
-
"@stacksjs/storage": "0.70.
|
|
74
|
-
"@stacksjs/strings": "0.70.
|
|
75
|
-
"@stacksjs/types": "0.70.
|
|
71
|
+
"@stacksjs/lint": "0.70.90",
|
|
72
|
+
"@stacksjs/path": "0.70.90",
|
|
73
|
+
"@stacksjs/storage": "0.70.90",
|
|
74
|
+
"@stacksjs/strings": "0.70.90",
|
|
75
|
+
"@stacksjs/types": "0.70.90"
|
|
76
76
|
}
|
|
77
77
|
}
|