@stacksjs/utils 0.70.88 → 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.d.ts +42 -0
- package/dist/bytes.js +55 -0
- package/dist/clean.d.ts +1 -0
- package/dist/clean.js +13 -0
- package/dist/colors.d.ts +146 -0
- package/dist/colors.js +100 -0
- package/dist/config.d.ts +23 -0
- package/dist/config.js +23 -0
- package/dist/debounce.d.ts +29 -0
- package/dist/debounce.js +77 -0
- package/dist/detect.d.ts +35 -0
- package/dist/detect.js +65 -0
- package/dist/equal.d.ts +13 -0
- package/dist/equal.js +27 -0
- package/dist/errors.d.ts +65 -0
- package/dist/errors.js +44 -0
- package/dist/export-size.d.ts +2 -0
- package/dist/export-size.js +1 -0
- package/dist/find.d.ts +4 -0
- package/dist/find.js +68 -0
- package/dist/git.d.ts +1 -0
- package/dist/git.js +11 -0
- package/dist/glob.d.ts +1 -0
- package/dist/glob.js +1 -0
- package/dist/hash.d.ts +3 -0
- package/dist/hash.js +36 -0
- package/dist/helpers.d.ts +53 -0
- package/dist/helpers.js +101 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +23 -0
- package/dist/macroable.d.ts +28 -0
- package/dist/macroable.js +121 -0
- package/dist/markdown.d.ts +46 -0
- package/dist/markdown.js +92 -0
- package/dist/merge.d.ts +20 -0
- package/dist/merge.js +51 -0
- package/dist/observer.d.ts +64 -0
- package/dist/observer.js +78 -0
- package/dist/pipeline.d.ts +13 -0
- package/dist/pipeline.js +37 -0
- package/dist/safe-json.d.ts +49 -0
- package/dist/safe-json.js +33 -0
- package/dist/size.d.ts +37 -0
- package/dist/size.js +66 -0
- package/dist/utils.d.ts +2 -0
- package/dist/utils.js +6 -0
- package/dist/versions.d.ts +8 -0
- package/dist/versions.js +19 -0
- package/package.json +11 -11
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error-handling helpers (stacksjs/stacks#1875 T-1).
|
|
3
|
+
*
|
|
4
|
+
* Background: a `catch (e: any)` block lets you reach `e.message`
|
|
5
|
+
* without a typecheck — but the thrown value isn't guaranteed to be
|
|
6
|
+
* an `Error`. Strings, numbers, plain objects, and even `null` can
|
|
7
|
+
* be thrown. `e.message` on a string returns `undefined`; on `null`
|
|
8
|
+
* it throws TypeError. `${e}` works but loses stack trace info.
|
|
9
|
+
*
|
|
10
|
+
* These helpers let catch blocks type `e` as `unknown` (the safe
|
|
11
|
+
* TypeScript default) and pull a useful string / stack out without
|
|
12
|
+
* branching at every site.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* Pull a human-readable message out of an unknown thrown value.
|
|
16
|
+
*
|
|
17
|
+
* Resolution order:
|
|
18
|
+
* 1. `Error.message` — the common case
|
|
19
|
+
* 2. plain-object `.message` — duck-typing for error-like values
|
|
20
|
+
* from across a serialization boundary (HTTP responses, IPC, etc.)
|
|
21
|
+
* 3. `String(e)` — covers strings, numbers, booleans
|
|
22
|
+
* 4. `'Unknown error'` — for `null` / `undefined` thrown values
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* try {
|
|
27
|
+
* await someAsyncOp()
|
|
28
|
+
* }
|
|
29
|
+
* catch (e: unknown) {
|
|
30
|
+
* log.error(`Failed: ${getErrorMessage(e)}`)
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function getErrorMessage(e: unknown): string;
|
|
35
|
+
/**
|
|
36
|
+
* Pull a stack trace out of an unknown thrown value, returning
|
|
37
|
+
* `undefined` when one isn't available. Useful for log enrichment
|
|
38
|
+
* without forcing the caller to narrow `e` first.
|
|
39
|
+
*/
|
|
40
|
+
export declare function getErrorStack(e: unknown): string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* Pull a `.code` string out of an unknown thrown value. Common across
|
|
43
|
+
* AWS SDK errors (`'AlreadyExistsException'`, `'NoSuchEntity'`, …),
|
|
44
|
+
* Node fs errors (`'ENOENT'`, `'EACCES'`, …), and many HTTP-client
|
|
45
|
+
* libraries. Returns `undefined` when the input doesn't carry a
|
|
46
|
+
* string code, so callers can default-handle.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getErrorCode(e: unknown): string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Pull an HTTP-style status code (`.statusCode` or `.status`) out of an
|
|
51
|
+
* unknown thrown value. AWS SDK errors use `.statusCode`; fetch/Node
|
|
52
|
+
* errors often use `.status`. Returns `undefined` when neither is a
|
|
53
|
+
* finite number — same default-handling pattern as `getErrorCode`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function getErrorStatusCode(e: unknown): number | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Coerce an unknown thrown value into a real `Error`. The thrown
|
|
58
|
+
* value is preserved on `.cause` (ES2022) when the input was a
|
|
59
|
+
* non-Error so debugging tools can still surface it. Idempotent —
|
|
60
|
+
* passing in an Error returns it unchanged.
|
|
61
|
+
*
|
|
62
|
+
* Use this when downstream APIs require an `Error` instance (e.g.
|
|
63
|
+
* tracing SDKs that want `captureException(Error)`).
|
|
64
|
+
*/
|
|
65
|
+
export declare function toError(e: unknown): Error;
|
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.d.ts
ADDED
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.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function isGitClean(): boolean;
|
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.d.ts
ADDED
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
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AddressInfo } from 'node:net';
|
|
2
|
+
import type { CliOptions, Manifest, Subprocess } from '@stacksjs/types';
|
|
3
|
+
import type { NpmScript } from '@stacksjs/enums';
|
|
4
|
+
import type { Result } from '@stacksjs/error-handling';
|
|
5
|
+
// Bun has native YAML support via Bun.YAML
|
|
6
|
+
// import { semver } from './versions'
|
|
7
|
+
export declare function packageManager(): Promise<string>;
|
|
8
|
+
export declare function initProject(): Promise<Result<Subprocess, Error>>;
|
|
9
|
+
export declare function ensureProjectIsInitialized(): Promise<boolean>;
|
|
10
|
+
export declare function installIfVersionMismatch(): Promise<void>;
|
|
11
|
+
export declare function frameworkVersion(): Promise<string>;
|
|
12
|
+
export declare function isAppKeySet(): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Determines the utilized reset preset.
|
|
15
|
+
*
|
|
16
|
+
* @url https://github.com/cwcss/crosswind
|
|
17
|
+
* @param preset
|
|
18
|
+
*/
|
|
19
|
+
export declare function determineResetPreset(preset?: string | null): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Determines whether the specified value is a package manifest.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isManifest(obj: any): obj is Manifest;
|
|
24
|
+
/**
|
|
25
|
+
* Determines whether the specified value is a string, null, or undefined.
|
|
26
|
+
*/
|
|
27
|
+
export declare function isOptionalString(value: any): value is string | null | undefined;
|
|
28
|
+
export declare function setEnvValue(key: string, value: string): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Runs the specified NPM script in the package.json file.
|
|
31
|
+
*/
|
|
32
|
+
export declare function runNpmScript(script: NpmScript, options?: CliOptions): Promise<Result<Subprocess, Error>>;
|
|
33
|
+
/**
|
|
34
|
+
* Determines whether the specified NPM script exists in the given manifest.
|
|
35
|
+
*/
|
|
36
|
+
export declare function hasScript(manifest: Manifest, script: NpmScript): boolean;
|
|
37
|
+
export declare function parseYaml(content: any): any;
|
|
38
|
+
/**
|
|
39
|
+
* Determines the level of debugging.
|
|
40
|
+
*
|
|
41
|
+
* The debug level is determined by the following:
|
|
42
|
+
* 1. The --verbose flag
|
|
43
|
+
* 2. The debug property in the app configuration
|
|
44
|
+
*
|
|
45
|
+
* Currently, we don't support a custom debug level,
|
|
46
|
+
* though, we would like to in the future.
|
|
47
|
+
*
|
|
48
|
+
* @param options
|
|
49
|
+
*/
|
|
50
|
+
export declare function determineDebugLevel(options?: CliOptions): boolean;
|
|
51
|
+
export declare function isIpv6(address: AddressInfo): boolean;
|
|
52
|
+
export declare function dumpYaml(content: any): string;
|
|
53
|
+
export declare function loadYaml(content: string): any;
|
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.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
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
|
+
// Native utility replacements
|
|
16
|
+
export * from './merge';
|
|
17
|
+
export * from './detect';
|
|
18
|
+
export * from './debounce';
|
|
19
|
+
export * from './bytes';
|
|
20
|
+
export * from './colors';
|
|
21
|
+
export * from './markdown';
|
|
22
|
+
export * from './size';
|
|
23
|
+
export * from './observer';
|
|
24
|
+
export * from './pipeline';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
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,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a macroable class
|
|
3
|
+
*/
|
|
4
|
+
export declare function createMacroable<T extends new (..._args: any[]) => any>(BaseClass?: T): T & MacroableConstructor;
|
|
5
|
+
/**
|
|
6
|
+
* Mixin for adding macroable functionality to existing classes
|
|
7
|
+
*/
|
|
8
|
+
export declare function macroable<T extends new (..._args: any[]) => any>(target: T): T & MacroableConstructor;
|
|
9
|
+
/**
|
|
10
|
+
* Native Macroable implementation
|
|
11
|
+
* Inspired by Laravel's Macroable trait - allows adding methods dynamically to classes
|
|
12
|
+
*/
|
|
13
|
+
export declare interface MacroableConstructor {
|
|
14
|
+
new (...args: any[]): any
|
|
15
|
+
macro(name: string, fn: Function, replace?: boolean): void
|
|
16
|
+
mixin(obj: Record<string, any>, replace?: boolean): void
|
|
17
|
+
hasMacro(name: string): boolean
|
|
18
|
+
flushMacros(): void
|
|
19
|
+
getMacros(): string[]
|
|
20
|
+
}
|
|
21
|
+
export declare class Macroable {
|
|
22
|
+
static macro(name: string, fn: Function, replace?: boolean): void;
|
|
23
|
+
static mixin(obj: Record<string, any>, replace?: boolean): void;
|
|
24
|
+
static hasMacro(name: string): boolean;
|
|
25
|
+
static flushMacros(): void;
|
|
26
|
+
static getMacros(): string[];
|
|
27
|
+
protected callMacro(name: string, ...args: any[]): any;
|
|
28
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate a markdown table from a 2D array
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```ts
|
|
6
|
+
* const table = markdownTable([
|
|
7
|
+
* ['Name', 'Age', 'City'],
|
|
8
|
+
* ['Alice', 30, 'NYC'],
|
|
9
|
+
* ['Bob', 25, 'LA']
|
|
10
|
+
* ])
|
|
11
|
+
* // | Name | Age | City |
|
|
12
|
+
* // | ----- | --- | ---- |
|
|
13
|
+
* // | Alice | 30 | NYC |
|
|
14
|
+
* // | Bob | 25 | LA |
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function markdownTable(table: Table, options?: MarkdownTableOptions): string;
|
|
18
|
+
/**
|
|
19
|
+
* Create a markdown table from objects
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const data = [
|
|
24
|
+
* { name: 'Alice', age: 30 },
|
|
25
|
+
* { name: 'Bob', age: 25 }
|
|
26
|
+
* ]
|
|
27
|
+
* const table = markdownTableFromObjects(data)
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function markdownTableFromObjects<T extends Record<string, any>>(objects: T[], options?: MarkdownTableOptions): string;
|
|
31
|
+
/**
|
|
32
|
+
* Markdown table generation (markdown-table replacement)
|
|
33
|
+
*/
|
|
34
|
+
export declare interface MarkdownTableOptions {
|
|
35
|
+
align?: Array<'l' | 'c' | 'r' | 'left' | 'center' | 'right' | null>
|
|
36
|
+
padding?: boolean
|
|
37
|
+
delimiter?: string
|
|
38
|
+
delimiterStart?: boolean
|
|
39
|
+
delimiterEnd?: boolean
|
|
40
|
+
alignDelimiter?: string
|
|
41
|
+
}
|
|
42
|
+
declare type CellValue = string | number | boolean | null | undefined;
|
|
43
|
+
declare type Row = CellValue[];
|
|
44
|
+
declare type Table = Row[];
|
|
45
|
+
// Alias
|
|
46
|
+
export { markdownTable as default };
|