@stacksjs/utils 0.70.88 → 0.70.91

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.
Files changed (49) hide show
  1. package/dist/bytes.d.ts +42 -0
  2. package/dist/bytes.js +55 -0
  3. package/dist/clean.d.ts +1 -0
  4. package/dist/clean.js +13 -0
  5. package/dist/colors.d.ts +146 -0
  6. package/dist/colors.js +100 -0
  7. package/dist/config.d.ts +23 -0
  8. package/dist/config.js +23 -0
  9. package/dist/debounce.d.ts +29 -0
  10. package/dist/debounce.js +77 -0
  11. package/dist/detect.d.ts +35 -0
  12. package/dist/detect.js +65 -0
  13. package/dist/equal.d.ts +13 -0
  14. package/dist/equal.js +27 -0
  15. package/dist/errors.d.ts +65 -0
  16. package/dist/errors.js +44 -0
  17. package/dist/export-size.d.ts +2 -0
  18. package/dist/export-size.js +1 -0
  19. package/dist/find.d.ts +4 -0
  20. package/dist/find.js +68 -0
  21. package/dist/git.d.ts +1 -0
  22. package/dist/git.js +11 -0
  23. package/dist/glob.d.ts +1 -0
  24. package/dist/glob.js +1 -0
  25. package/dist/hash.d.ts +3 -0
  26. package/dist/hash.js +36 -0
  27. package/dist/helpers.d.ts +53 -0
  28. package/dist/helpers.js +101 -0
  29. package/dist/index.d.ts +24 -0
  30. package/dist/index.js +23 -0
  31. package/dist/macroable.d.ts +28 -0
  32. package/dist/macroable.js +121 -0
  33. package/dist/markdown.d.ts +46 -0
  34. package/dist/markdown.js +92 -0
  35. package/dist/merge.d.ts +20 -0
  36. package/dist/merge.js +51 -0
  37. package/dist/observer.d.ts +64 -0
  38. package/dist/observer.js +78 -0
  39. package/dist/pipeline.d.ts +13 -0
  40. package/dist/pipeline.js +37 -0
  41. package/dist/safe-json.d.ts +49 -0
  42. package/dist/safe-json.js +33 -0
  43. package/dist/size.d.ts +37 -0
  44. package/dist/size.js +66 -0
  45. package/dist/utils.d.ts +2 -0
  46. package/dist/utils.js +6 -0
  47. package/dist/versions.d.ts +8 -0
  48. package/dist/versions.js +19 -0
  49. package/package.json +11 -11
@@ -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,2 @@
1
+ // Re-export from our native implementation
2
+ export { getExportsSize } from './size';
@@ -0,0 +1 @@
1
+ export { getExportsSize } from "./size";
package/dist/find.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare function findStacksProjects(dir?: string, options?: FindStacksProjectsOptions): Promise<string[]>;
2
+ declare interface FindStacksProjectsOptions {
3
+ quiet?: boolean
4
+ }
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
@@ -0,0 +1,3 @@
1
+ export declare function originRequestFunctionHash(): string | undefined;
2
+ export declare function websiteSourceHash(): string | undefined;
3
+ export declare function docsSourceHash(): string | undefined;
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;
@@ -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
+ }
@@ -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 };