UNPKG

@settlemint/sdk-utils

Version:

Shared utilities and helper functions for SettleMint SDK modules

1 lines 1.08 MB
{"version":3,"file":"environment.cjs","names":["output: string","msg: string","message: string","code: number","output: string[]","command: string","args: string[]","options?: ExecuteCommandOptions","data: Buffer | string","msg: string","message: string","level: \"info\" | \"warn\"","title: string","items: Array<string | string[]>","msg: string","message: string","originalError: Error","options: SpinnerOptions<R>","error: Error","error","isInCi","spinner","val: string","s: string","value: string","maxLength: number","title: string","data: unknown[]","table","Table","initializer","config","array","set","nullish","object","path","Class","config","initializer","error","issue","path","parse","parseAsync","safeParse","safeParseAsync","cuid","cuid2","ulid","xid","ksuid","nanoid","duration","guid","uuid","version","email","_emoji","emoji","ipv4","ipv6","cidrv4","cidrv6","base64","base64url","e164","date","time","datetime","string","bigint","number","boolean","_null","_undefined","inst","result","checks","result","_","url","inst","base64","isObject","allowsEval","r","results","map","left","right","keyResult","valueResult","output","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","parsedType","error","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","error","parsedType","issue","parsedType","issue","Class","_undefined","_null","_void","types","_enum","_default","_catch","json","file","schema","ext","params","gen","date","issue","issues","def","check","string","number","boolean","bigint","date","types","issue","output","map","z","z4","schema: T","value: unknown","error","ApplicationAccessTokenSchema: ZodString","PersonalAccessTokenSchema: ZodString","AccessTokenSchema: ZodString","value: string","defaultValue: T | null","value: unknown","value","validateEnv: T","prod: boolean","path: string","path","error","cwd?: string","path: PathLike","path","balanced","expand","glob","regExpEscape","qmark","star","#hasMagic","#parent","#root","#options","#negs","#filledNegs","#parentIndex","#parts","#toString","#parseAST","i","acc","ext","#emptyExt","glob","hasMagic","#fillNegs","#parseGlob","#uflag","start","final","#partsToRegExp","ext","defaultPlatform","Minimatch","AST","list","set","file","partial","#constructing","#starts","#ttls","#sizes","#keyMap","#keyList","#valList","#next","#prev","#head","#tail","#free","#isBackgroundFetch","#backgroundFetch","#moveToTail","#indexes","#rindexes","#isStale","#max","#maxSize","#calculatedSize","#size","#fetchMethod","#memoMethod","#dispose","#disposeAfter","#hasFetchMethod","#disposed","#hasDispose","#hasDisposeAfter","#initializeSizeTracking","#initializeTTLTracking","#setItemTTL","#delete","#updateItemAge","#statusTTL","#removeItemSize","#requireSize","#addItemSize","#evict","#isValidIndex","v","aborted","bf","#connect","#clear","Stream","EventEmitter","StringDecoder","p","ret","res","rps","readdirCB","actualFS","#dev","#mode","#nlink","#uid","#gid","#rdev","#blksize","#ino","#size","#blocks","#atimeMs","#mtimeMs","#ctimeMs","#birthtimeMs","#atime","#mtime","#ctime","#birthtime","#matchName","#type","#children","#fullpath","#relative","#relativePosix","#fs","#depth","path","#resolveParts","cached","#fullpathPosix","p","#linkTarget","#realpath","#readlinkFail","#markENOENT","#markChildrenENOENT","#markENOTDIR","#readdirMaybePromoteChild","#readdirAddNewChild","#readdirPromoteChild","#applyStat","#lstatFail","#readdirCBInFlight","#onReaddirCB","#readdirFail","#readdirAddChild","#readdirSuccess","#callOnReaddirCB","#asyncReaddirInFlight","#markENOREALPATH","sep","fs","#resolveCache","#resolvePosixCache","filter","process","sync","win32","posix","#patternList","#globList","#index","#platform","#globString","#rest","#isAbsolute","#isUNC","#isDrive","#followGlobstar","defaultPlatform","cached","path","rest","path","#sep","#ignore","#onResume","#ignored","abs","#childrenIgnored","target","set","startDir: string","projectDir: string","workspace: string","match","error","packageJsonPath: string","obj: Record<string, unknown>","currentEnv: Record<string, unknown>","env: Partial<DotEnv>"],"sources":["../src/terminal/should-print.ts","../src/terminal/ascii.ts","../src/logging/mask-tokens.ts","../src/terminal/cancel.ts","../src/terminal/execute-command.ts","../src/terminal/intro.ts","../src/terminal/note.ts","../src/terminal/list.ts","../src/terminal/outro.ts","../src/terminal/spinner.ts","../src/string.ts","../src/terminal/table.ts","../../../node_modules/zod/dist/esm/v4/core/core.js","../../../node_modules/zod/dist/esm/v4/core/util.js","../../../node_modules/zod/dist/esm/v4/core/errors.js","../../../node_modules/zod/dist/esm/v4/core/parse.js","../../../node_modules/zod/dist/esm/v4/core/regexes.js","../../../node_modules/zod/dist/esm/v4/core/checks.js","../../../node_modules/zod/dist/esm/v4/core/doc.js","../../../node_modules/zod/dist/esm/v4/core/versions.js","../../../node_modules/zod/dist/esm/v4/core/schemas.js","../../../node_modules/zod/dist/esm/v4/locales/ar.js","../../../node_modules/zod/dist/esm/v4/locales/az.js","../../../node_modules/zod/dist/esm/v4/locales/be.js","../../../node_modules/zod/dist/esm/v4/locales/ca.js","../../../node_modules/zod/dist/esm/v4/locales/cs.js","../../../node_modules/zod/dist/esm/v4/locales/de.js","../../../node_modules/zod/dist/esm/v4/locales/en.js","../../../node_modules/zod/dist/esm/v4/locales/es.js","../../../node_modules/zod/dist/esm/v4/locales/fa.js","../../../node_modules/zod/dist/esm/v4/locales/fi.js","../../../node_modules/zod/dist/esm/v4/locales/fr.js","../../../node_modules/zod/dist/esm/v4/locales/fr-CA.js","../../../node_modules/zod/dist/esm/v4/locales/he.js","../../../node_modules/zod/dist/esm/v4/locales/hu.js","../../../node_modules/zod/dist/esm/v4/locales/id.js","../../../node_modules/zod/dist/esm/v4/locales/it.js","../../../node_modules/zod/dist/esm/v4/locales/ja.js","../../../node_modules/zod/dist/esm/v4/locales/kh.js","../../../node_modules/zod/dist/esm/v4/locales/ko.js","../../../node_modules/zod/dist/esm/v4/locales/mk.js","../../../node_modules/zod/dist/esm/v4/locales/ms.js","../../../node_modules/zod/dist/esm/v4/locales/nl.js","../../../node_modules/zod/dist/esm/v4/locales/no.js","../../../node_modules/zod/dist/esm/v4/locales/ota.js","../../../node_modules/zod/dist/esm/v4/locales/pl.js","../../../node_modules/zod/dist/esm/v4/locales/pt.js","../../../node_modules/zod/dist/esm/v4/locales/ru.js","../../../node_modules/zod/dist/esm/v4/locales/sl.js","../../../node_modules/zod/dist/esm/v4/locales/sv.js","../../../node_modules/zod/dist/esm/v4/locales/ta.js","../../../node_modules/zod/dist/esm/v4/locales/th.js","../../../node_modules/zod/dist/esm/v4/locales/tr.js","../../../node_modules/zod/dist/esm/v4/locales/ua.js","../../../node_modules/zod/dist/esm/v4/locales/ur.js","../../../node_modules/zod/dist/esm/v4/locales/vi.js","../../../node_modules/zod/dist/esm/v4/locales/zh-CN.js","../../../node_modules/zod/dist/esm/v4/locales/zh-TW.js","../../../node_modules/zod/dist/esm/v4/locales/index.js","../../../node_modules/zod/dist/esm/v4/core/registries.js","../../../node_modules/zod/dist/esm/v4/core/api.js","../../../node_modules/zod/dist/esm/v4/core/function.js","../../../node_modules/zod/dist/esm/v4/core/to-json-schema.js","../../../node_modules/zod/dist/esm/v4/core/json-schema.js","../../../node_modules/zod/dist/esm/v4/core/index.js","../../../node_modules/zod/dist/esm/v4/classic/iso.js","../../../node_modules/zod/dist/esm/v4/classic/errors.js","../../../node_modules/zod/dist/esm/v4/classic/parse.js","../../../node_modules/zod/dist/esm/v4/classic/schemas.js","../../../node_modules/zod/dist/esm/v4/classic/compat.js","../../../node_modules/zod/dist/esm/v4/classic/coerce.js","../../../node_modules/zod/dist/esm/v4/classic/external.js","../../../node_modules/zod/dist/esm/v4/classic/index.js","../../../node_modules/zod/dist/esm/v4/index.js","../src/validation/validate.ts","../src/validation/access-token.schema.ts","../src/json.ts","../src/validation/unique-name.schema.ts","../src/validation/url.schema.ts","../src/validation/dot-env.schema.ts","../src/validation/id.schema.ts","../src/environment/load-env.ts","../src/filesystem/project-root.ts","../src/filesystem/exists.ts","../../../node_modules/balanced-match/index.js","../../../node_modules/brace-expansion/index.js","../../../node_modules/minimatch/dist/esm/assert-valid-pattern.js","../../../node_modules/minimatch/dist/esm/brace-expressions.js","../../../node_modules/minimatch/dist/esm/unescape.js","../../../node_modules/minimatch/dist/esm/ast.js","../../../node_modules/minimatch/dist/esm/escape.js","../../../node_modules/minimatch/dist/esm/index.js","../../../node_modules/path-scurry/node_modules/lru-cache/dist/esm/index.js","../../../node_modules/minipass/dist/esm/index.js","../../../node_modules/path-scurry/dist/esm/index.js","../../../node_modules/glob/dist/esm/pattern.js","../../../node_modules/glob/dist/esm/ignore.js","../../../node_modules/glob/dist/esm/processor.js","../../../node_modules/glob/dist/esm/walker.js","../../../node_modules/glob/dist/esm/glob.js","../../../node_modules/glob/dist/esm/has-magic.js","../../../node_modules/glob/dist/esm/index.js","../src/filesystem/mono-repo.ts","../src/environment/write-env.ts"],"sourcesContent":["/**\n * Returns true if the terminal should print, false otherwise.\n * @returns true if the terminal should print, false otherwise.\n */\nexport function shouldPrint() {\n return process.env.SETTLEMINT_DISABLE_TERMINAL !== \"true\";\n}\n","import { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Prints the SettleMint ASCII art logo to the console in magenta color.\n * Used for CLI branding and visual identification.\n *\n * @example\n * import { ascii } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Prints the SettleMint logo\n * ascii();\n */\nexport const ascii = (): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\n magentaBright(`\n _________ __ __ .__ _____ .__ __\n / _____/ _____/ |__/ |_| | ____ / \\\\ |__| _____/ |_\n \\\\_____ \\\\_/ __ \\\\ __\\\\ __\\\\ | _/ __ \\\\ / \\\\ / \\\\| |/ \\\\ __\\\\\n / \\\\ ___/| | | | | |_\\\\ ___// Y \\\\ | | \\\\ |\n/_________/\\\\_____>__| |__| |____/\\\\_____>____|____/__|___|__/__|\n`),\n );\n};\n","/**\n * Masks sensitive SettleMint tokens in output text by replacing them with asterisks.\n * Handles personal access tokens (PAT), application access tokens (AAT), and service account tokens (SAT).\n *\n * @param output - The text string that may contain sensitive tokens\n * @returns The text with any sensitive tokens masked with asterisks\n * @example\n * import { maskTokens } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Masks a token in text\n * const masked = maskTokens(\"Token: sm_pat_****\"); // \"Token: ***\"\n */\nexport const maskTokens = (output: string): string => {\n return output.replace(/sm_(pat|aat|sat)_[0-9a-zA-Z]+/g, \"***\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { inverse, redBright } from \"yoctocolors\";\n\n/**\n * Error class used to indicate that the operation was cancelled.\n * This error is used to signal that the operation should be aborted.\n */\nexport class CancelError extends Error {}\n\n/**\n * Displays an error message in red inverse text and throws a CancelError.\n * Used to terminate execution with a visible error message.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The error message to display\n * @returns never - Function does not return as it throws an error\n * @example\n * import { cancel } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Exits process with error message\n * cancel(\"An error occurred\");\n */\nexport const cancel = (msg: string): never => {\n console.log(\"\");\n console.log(inverse(redBright(maskTokens(msg))));\n console.log(\"\");\n throw new CancelError(msg);\n};\n","import { type SpawnOptionsWithoutStdio, spawn } from \"node:child_process\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\n\n/**\n * Options for executing a command, extending SpawnOptionsWithoutStdio\n */\nexport interface ExecuteCommandOptions extends SpawnOptionsWithoutStdio {\n /** Whether to suppress output to stdout/stderr */\n silent?: boolean;\n}\n\n/**\n * Error class for command execution errors\n * @extends Error\n */\nexport class CommandError extends Error {\n /**\n * Constructs a new CommandError\n * @param message - The error message\n * @param code - The exit code of the command\n * @param output - The output of the command\n */\n constructor(\n message: string,\n public readonly code: number,\n public readonly output: string[],\n ) {\n super(message);\n }\n}\n\n/**\n * Executes a command with the given arguments in a child process.\n * Pipes stdin to the child process and captures stdout/stderr output.\n * Masks any sensitive tokens in the output before displaying or returning.\n *\n * @param command - The command to execute\n * @param args - Array of arguments to pass to the command\n * @param options - Options for customizing command execution\n * @returns Array of output strings from stdout and stderr\n * @throws {CommandError} If the process fails to start or exits with non-zero code\n * @example\n * import { executeCommand } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Execute git clone\n * await executeCommand(\"git\", [\"clone\", \"repo-url\"]);\n *\n * // Execute silently\n * await executeCommand(\"npm\", [\"install\"], { silent: true });\n */\nexport async function executeCommand(\n command: string,\n args: string[],\n options?: ExecuteCommandOptions,\n): Promise<string[]> {\n const { silent, ...spawnOptions } = options ?? {};\n const child = spawn(command, args, { ...spawnOptions, env: { ...process.env, ...options?.env } });\n process.stdin.pipe(child.stdin);\n const output: string[] = [];\n return new Promise((resolve, reject) => {\n child.stdout.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!silent) {\n process.stdout.write(maskedData);\n }\n output.push(maskedData);\n });\n child.stderr.on(\"data\", (data: Buffer | string) => {\n const maskedData = maskTokens(data.toString());\n if (!silent) {\n process.stderr.write(maskedData);\n }\n output.push(maskedData);\n });\n child.on(\"error\", (err) => {\n process.stdin.unpipe(child.stdin);\n reject(new CommandError(err.message, \"code\" in err && typeof err.code === \"number\" ? err.code : 1, output));\n });\n child.on(\"close\", (code) => {\n process.stdin.unpipe(child.stdin);\n if (code === 0 || code === null || code === 143) {\n resolve(output);\n return;\n }\n reject(new CommandError(`Command \"${command}\" exited with code ${code}`, code, output));\n });\n });\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { magentaBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays an introductory message in magenta text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as introduction\n * @example\n * import { intro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display intro message\n * intro(\"Starting deployment...\");\n */\nexport const intro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(magentaBright(maskTokens(msg)));\n console.log(\"\");\n};\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { yellowBright } from \"yoctocolors\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Displays a note message with optional warning level formatting.\n * Regular notes are displayed in normal text, while warnings are shown in yellow.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param message - The message to display as a note\n * @param level - The note level: \"info\" (default) or \"warn\" for warning styling\n * @example\n * import { note } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display info note\n * note(\"Operation completed successfully\");\n *\n * // Display warning note\n * note(\"Low disk space remaining\", \"warn\");\n */\nexport const note = (message: string, level: \"info\" | \"warn\" = \"info\"): void => {\n if (!shouldPrint()) {\n return;\n }\n const maskedMessage = maskTokens(message);\n\n console.log(\"\");\n if (level === \"warn\") {\n console.warn(yellowBright(maskedMessage));\n return;\n }\n\n console.log(maskedMessage);\n};\n","import { note } from \"./note.js\";\n\n/**\n * Displays a list of items in a formatted manner, supporting nested items.\n *\n * @param title - The title of the list\n * @param items - The items to display, can be strings or arrays for nested items\n * @returns The formatted list\n * @example\n * import { list } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Simple list\n * list(\"Use cases\", [\"use case 1\", \"use case 2\", \"use case 3\"]);\n *\n * // Nested list\n * list(\"Providers\", [\n * \"AWS\",\n * [\"us-east-1\", \"eu-west-1\"],\n * \"Azure\",\n * [\"eastus\", \"westeurope\"]\n * ]);\n */\nexport function list(title: string, items: Array<string | string[]>) {\n const formatItems = (items: Array<string | string[]>): string => {\n return items\n .map((item) => {\n if (Array.isArray(item)) {\n return item.map((subItem) => ` • ${subItem}`).join(\"\\n\");\n }\n return ` • ${item}`;\n })\n .join(\"\\n\");\n };\n\n return note(`${title}:\\n\\n${formatItems(items)}`);\n}\n","import { maskTokens } from \"@/logging/mask-tokens.js\";\nimport { shouldPrint } from \"@/terminal/should-print.js\";\nimport { greenBright, inverse } from \"yoctocolors\";\n\n/**\n * Displays a closing message in green inverted text with padding.\n * Any sensitive tokens in the message are masked before display.\n *\n * @param msg - The message to display as conclusion\n * @example\n * import { outro } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Display outro message\n * outro(\"Deployment completed successfully!\");\n */\nexport const outro = (msg: string): void => {\n if (!shouldPrint()) {\n return;\n }\n console.log(\"\");\n console.log(inverse(greenBright(maskTokens(msg))));\n console.log(\"\");\n};\n","import isInCi from \"is-in-ci\";\nimport yoctoSpinner, { type Spinner } from \"yocto-spinner\";\nimport { redBright } from \"yoctocolors\";\nimport { maskTokens } from \"../logging/mask-tokens.js\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n\n/**\n * Error class used to indicate that the spinner operation failed.\n * This error is used to signal that the operation should be aborted.\n */\nexport class SpinnerError extends Error {\n constructor(\n message: string,\n public readonly originalError: Error,\n ) {\n super(message);\n this.name = \"SpinnerError\";\n }\n}\n\n/**\n * Options for configuring the spinner behavior\n */\nexport interface SpinnerOptions<R> {\n /** Message to display when spinner starts */\n startMessage: string;\n /** Async task to execute while spinner is active */\n task: (spinner?: Spinner) => Promise<R>;\n /** Message to display when spinner completes successfully */\n stopMessage: string;\n}\n\n/**\n * Displays a loading spinner while executing an async task.\n * Shows progress with start/stop messages and handles errors.\n * Spinner is disabled in CI environments.\n *\n * @param options - Configuration options for the spinner\n * @returns The result from the executed task\n * @throws Will exit process with code 1 if task fails\n * @example\n * import { spinner } from \"@settlemint/sdk-utils/terminal\";\n *\n * // Show spinner during async task\n * const result = await spinner({\n * startMessage: \"Deploying...\",\n * task: async () => {\n * // Async work here\n * return \"success\";\n * },\n * stopMessage: \"Deployed successfully!\"\n * });\n */\nexport const spinner = async <R>(options: SpinnerOptions<R>): Promise<R> => {\n const handleError = (error: Error) => {\n const errorMessage = maskTokens(error.message);\n note(redBright(`${errorMessage}\\n\\n${error.stack}`));\n throw new SpinnerError(errorMessage, error);\n };\n if (isInCi || !shouldPrint()) {\n try {\n return await options.task();\n } catch (err) {\n return handleError(err as Error);\n }\n }\n const spinner = yoctoSpinner({ stream: process.stdout }).start(options.startMessage);\n try {\n const result = await options.task(spinner);\n spinner.success(options.stopMessage);\n // Ensure spinner success message renders before proceeding to avoid\n // terminal output overlap issues with subsequent messages\n await new Promise((resolve) => process.nextTick(resolve));\n return result;\n } catch (err) {\n spinner.error(redBright(`${options.startMessage} --> Error!`));\n return handleError(err as Error);\n }\n};\n","/**\n * Capitalizes the first letter of a string.\n *\n * @param val - The string to capitalize\n * @returns The input string with its first letter capitalized\n *\n * @example\n * import { capitalizeFirstLetter } from \"@settlemint/sdk-utils\";\n *\n * const capitalized = capitalizeFirstLetter(\"hello\");\n * // Returns: \"Hello\"\n */\nexport function capitalizeFirstLetter(val: string) {\n return String(val).charAt(0).toUpperCase() + String(val).slice(1);\n}\n\n/**\n * Converts a camelCase string to a human-readable string.\n *\n * @param s - The camelCase string to convert\n * @returns The human-readable string\n *\n * @example\n * import { camelCaseToWords } from \"@settlemint/sdk-utils\";\n *\n * const words = camelCaseToWords(\"camelCaseString\");\n * // Returns: \"Camel Case String\"\n */\nexport function camelCaseToWords(s: string) {\n const result = s.replace(/([a-z])([A-Z])/g, \"$1 $2\");\n const withSpaces = result.replace(/([A-Z])([a-z])/g, \" $1$2\");\n const capitalized = capitalizeFirstLetter(withSpaces);\n return capitalized.replace(/\\s+/g, \" \").trim();\n}\n\n/**\n * Replaces underscores and hyphens with spaces.\n *\n * @param s - The string to replace underscores and hyphens with spaces\n * @returns The input string with underscores and hyphens replaced with spaces\n *\n * @example\n * import { replaceUnderscoresAndHyphensWithSpaces } from \"@settlemint/sdk-utils\";\n *\n * const result = replaceUnderscoresAndHyphensWithSpaces(\"Already_Spaced-Second\");\n * // Returns: \"Already Spaced Second\"\n */\nexport function replaceUnderscoresAndHyphensWithSpaces(s: string) {\n return s.replace(/[-_]/g, \" \");\n}\n\n/**\n * Truncates a string to a maximum length and appends \"...\" if it is longer.\n *\n * @param value - The string to truncate\n * @param maxLength - The maximum length of the string\n * @returns The truncated string or the original string if it is shorter than the maximum length\n *\n * @example\n * import { truncate } from \"@settlemint/sdk-utils\";\n *\n * const truncated = truncate(\"Hello, world!\", 10);\n * // Returns: \"Hello, wor...\"\n */\nexport function truncate(value: string, maxLength: number) {\n if (value.length <= maxLength) {\n return value;\n }\n return `${value.slice(0, maxLength)}...`;\n}\n","import { camelCaseToWords } from \"@/string.js\";\nimport { Table } from \"console-table-printer\";\nimport { whiteBright } from \"yoctocolors\";\nimport { note } from \"./note.js\";\nimport { shouldPrint } from \"./should-print.js\";\n/**\n * Displays data in a formatted table in the terminal.\n *\n * @param title - Title to display above the table\n * @param data - Array of objects to display in table format\n * @example\n * import { table } from \"@settlemint/sdk-utils/terminal\";\n *\n * const data = [\n * { name: \"Item 1\", value: 100 },\n * { name: \"Item 2\", value: 200 }\n * ];\n *\n * table(\"My Table\", data);\n */\nexport function table(title: string, data: unknown[]): void {\n if (!shouldPrint()) {\n return;\n }\n\n note(title);\n\n if (!data || data.length === 0) {\n note(\"No data to display\");\n return;\n }\n\n const columnKeys = Object.keys(data[0] as Record<string, unknown>);\n const table = new Table({\n columns: columnKeys.map((key) => ({\n name: key,\n title: whiteBright(camelCaseToWords(key)),\n alignment: \"left\",\n })),\n });\n table.addRows(data);\n table.printTable();\n}\n","export /*@__NO_SIDE_EFFECTS__*/ function $constructor(name, initializer, params) {\n function init(inst, def) {\n var _a;\n Object.defineProperty(inst, \"_zod\", {\n value: inst._zod ?? {},\n enumerable: false,\n });\n (_a = inst._zod).traits ?? (_a.traits = new Set());\n inst._zod.traits.add(name);\n initializer(inst, def);\n // support prototype modifications\n for (const k in _.prototype) {\n if (!(k in inst))\n Object.defineProperty(inst, k, { value: _.prototype[k].bind(inst) });\n }\n inst._zod.constr = _;\n inst._zod.def = def;\n }\n // doesn't work if Parent has a constructor with arguments\n const Parent = params?.Parent ?? Object;\n class Definition extends Parent {\n }\n Object.defineProperty(Definition, \"name\", { value: name });\n function _(def) {\n var _a;\n const inst = params?.Parent ? new Definition() : this;\n init(inst, def);\n (_a = inst._zod).deferred ?? (_a.deferred = []);\n for (const fn of inst._zod.deferred) {\n fn();\n }\n return inst;\n }\n Object.defineProperty(_, \"init\", { value: init });\n Object.defineProperty(_, Symbol.hasInstance, {\n value: (inst) => {\n if (params?.Parent && inst instanceof params.Parent)\n return true;\n return inst?._zod?.traits?.has(name);\n },\n });\n Object.defineProperty(_, \"name\", { value: name });\n return _;\n}\n////////////////////////////// UTILITIES ///////////////////////////////////////\nexport const $brand = Symbol(\"zod_brand\");\nexport class $ZodAsyncError extends Error {\n constructor() {\n super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);\n }\n}\nexport const globalConfig = {};\nexport function config(newConfig) {\n if (newConfig)\n Object.assign(globalConfig, newConfig);\n return globalConfig;\n}\n","// functions\nexport function assertEqual(val) {\n return val;\n}\nexport function assertNotEqual(val) {\n return val;\n}\nexport function assertIs(_arg) { }\nexport function assertNever(_x) {\n throw new Error();\n}\nexport function assert(_) { }\nexport function getEnumValues(entries) {\n const numericValues = Object.values(entries).filter((v) => typeof v === \"number\");\n const values = Object.entries(entries)\n .filter(([k, _]) => numericValues.indexOf(+k) === -1)\n .map(([_, v]) => v);\n return values;\n}\nexport function joinValues(array, separator = \"|\") {\n return array.map((val) => stringifyPrimitive(val)).join(separator);\n}\nexport function jsonStringifyReplacer(_, value) {\n if (typeof value === \"bigint\")\n return value.toString();\n return value;\n}\nexport function cached(getter) {\n const set = false;\n return {\n get value() {\n if (!set) {\n const value = getter();\n Object.defineProperty(this, \"value\", { value });\n return value;\n }\n throw new Error(\"cached value already set\");\n },\n };\n}\nexport function nullish(input) {\n return input === null || input === undefined;\n}\nexport function cleanRegex(source) {\n const start = source.startsWith(\"^\") ? 1 : 0;\n const end = source.endsWith(\"$\") ? source.length - 1 : source.length;\n return source.slice(start, end);\n}\nexport function floatSafeRemainder(val, step) {\n const valDecCount = (val.toString().split(\".\")[1] || \"\").length;\n const stepDecCount = (step.toString().split(\".\")[1] || \"\").length;\n const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;\n const valInt = Number.parseInt(val.toFixed(decCount).replace(\".\", \"\"));\n const stepInt = Number.parseInt(step.toFixed(decCount).replace(\".\", \"\"));\n return (valInt % stepInt) / 10 ** decCount;\n}\nexport function defineLazy(object, key, getter) {\n const set = false;\n Object.defineProperty(object, key, {\n get() {\n if (!set) {\n const value = getter();\n object[key] = value;\n return value;\n }\n throw new Error(\"cached value already set\");\n },\n set(v) {\n Object.defineProperty(object, key, {\n value: v,\n // configurable: true,\n });\n // object[key] = v;\n },\n configurable: true,\n });\n}\nexport function assignProp(target, prop, value) {\n Object.defineProperty(target, prop, {\n value,\n writable: true,\n enumerable: true,\n configurable: true,\n });\n}\nexport function getElementAtPath(obj, path) {\n if (!path)\n return obj;\n return path.reduce((acc, key) => acc?.[key], obj);\n}\nexport function promiseAllObject(promisesObj) {\n const keys = Object.keys(promisesObj);\n const promises = keys.map((key) => promisesObj[key]);\n return Promise.all(promises).then((results) => {\n const resolvedObj = {};\n for (let i = 0; i < keys.length; i++) {\n resolvedObj[keys[i]] = results[i];\n }\n return resolvedObj;\n });\n}\nexport function randomString(length = 10) {\n const chars = \"abcdefghijklmnopqrstuvwxyz\";\n let str = \"\";\n for (let i = 0; i < length; i++) {\n str += chars[Math.floor(Math.random() * chars.length)];\n }\n return str;\n}\nexport function esc(str) {\n return JSON.stringify(str);\n}\nexport function isObject(data) {\n return typeof data === \"object\" && data !== null && !Array.isArray(data);\n}\nexport const allowsEval = cached(() => {\n try {\n const F = Function;\n new F(\"\");\n return true;\n }\n catch (_) {\n return false;\n }\n});\nfunction _isObject(o) {\n return Object.prototype.toString.call(o) === \"[object Object]\";\n}\nexport function isPlainObject(o) {\n if (isObject(o) === false)\n return false;\n // modified constructor\n const ctor = o.constructor;\n if (ctor === undefined)\n return true;\n // modified prototype\n const prot = ctor.prototype;\n if (isObject(prot) === false)\n return false;\n // ctor doesn't have static `isPrototypeOf`\n if (Object.prototype.hasOwnProperty.call(prot, \"isPrototypeOf\") === false) {\n return false;\n }\n return true;\n}\nexport function numKeys(data) {\n let keyCount = 0;\n for (const key in data) {\n if (Object.prototype.hasOwnProperty.call(data, key)) {\n keyCount++;\n }\n }\n return keyCount;\n}\nexport const getParsedType = (data) => {\n const t = typeof data;\n switch (t) {\n case \"undefined\":\n return \"undefined\";\n case \"string\":\n return \"string\";\n case \"number\":\n return Number.isNaN(data) ? \"nan\" : \"number\";\n case \"boolean\":\n return \"boolean\";\n case \"function\":\n return \"function\";\n case \"bigint\":\n return \"bigint\";\n case \"symbol\":\n return \"symbol\";\n case \"object\":\n if (Array.isArray(data)) {\n return \"array\";\n }\n if (data === null) {\n return \"null\";\n }\n if (data.then && typeof data.then === \"function\" && data.catch && typeof data.catch === \"function\") {\n return \"promise\";\n }\n if (typeof Map !== \"undefined\" && data instanceof Map) {\n return \"map\";\n }\n if (typeof Set !== \"undefined\" && data instanceof Set) {\n return \"set\";\n }\n if (typeof Date !== \"undefined\" && data instanceof Date) {\n return \"date\";\n }\n if (typeof File !== \"undefined\" && data instanceof File) {\n return \"file\";\n }\n return \"object\";\n default:\n throw new Error(`Unknown data type: ${t}`);\n }\n};\nexport const propertyKeyTypes = new Set([\"string\", \"number\", \"symbol\"]);\nexport const primitiveTypes = new Set([\"string\", \"number\", \"bigint\", \"boolean\", \"symbol\", \"undefined\"]);\nexport function escapeRegex(str) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n// zod-specific utils\nexport function clone(inst, def, params) {\n const cl = new inst._zod.constr(def ?? inst._zod.def);\n if (!def || params?.parent)\n cl._zod.parent = inst;\n return cl;\n}\nexport function normalizeParams(_params) {\n const params = _params;\n if (!params)\n return {};\n if (typeof params === \"string\")\n return { error: () => params };\n if (params?.message !== undefined) {\n if (params?.error !== undefined)\n throw new Error(\"Cannot specify both `message` and `error` params\");\n params.error = params.message;\n }\n delete params.message;\n if (typeof params.error === \"string\")\n return { ...params, error: () => params.error };\n return params;\n}\nexport function createTransparentProxy(getter) {\n let target;\n return new Proxy({}, {\n get(_, prop, receiver) {\n target ?? (target = getter());\n return Reflect.get(target, prop, receiver);\n },\n set(_, prop, value, receiver) {\n target ?? (target = getter());\n return Reflect.set(target, prop, value, receiver);\n },\n has(_, prop) {\n target ?? (target = getter());\n return Reflect.has(target, prop);\n },\n deleteProperty(_, prop) {\n target ?? (target = getter());\n return Reflect.deleteProperty(target, prop);\n },\n ownKeys(_) {\n target ?? (target = getter());\n return Reflect.ownKeys(target);\n },\n getOwnPropertyDescriptor(_, prop) {\n target ?? (target = getter());\n return Reflect.getOwnPropertyDescriptor(target, prop);\n },\n defineProperty(_, prop, descriptor) {\n target ?? (target = getter());\n return Reflect.defineProperty(target, prop, descriptor);\n },\n });\n}\nexport function stringifyPrimitive(value) {\n if (typeof value === \"bigint\")\n return value.toString() + \"n\";\n if (typeof value === \"string\")\n return `\"${value}\"`;\n return `${value}`;\n}\nexport function optionalKeys(shape) {\n return Object.keys(shape).filter((k) => {\n return shape[k]._zod.optin === \"optional\" && shape[k]._zod.optout === \"optional\";\n });\n}\nexport const NUMBER_FORMAT_RANGES = {\n safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],\n int32: [-2147483648, 2147483647],\n uint32: [0, 4294967295],\n float32: [-3.4028234663852886e38, 3.4028234663852886e38],\n float64: [-Number.MAX_VALUE, Number.MAX_VALUE],\n};\nexport const BIGINT_FORMAT_RANGES = {\n int64: [/* @__PURE__*/ BigInt(\"-9223372036854775808\"), /* @__PURE__*/ BigInt(\"9223372036854775807\")],\n uint64: [/* @__PURE__*/ BigInt(0), /* @__PURE__*/ BigInt(\"18446744073709551615\")],\n};\nexport function pick(schema, mask) {\n const newShape = {};\n const currDef = schema._zod.def; //.shape;\n for (const key in mask) {\n if (!(key in currDef.shape)) {\n throw new Error(`Unrecognized key: \"${key}\"`);\n }\n if (!mask[key])\n continue;\n // pick key\n newShape[key] = currDef.shape[key];\n }\n return clone(schema, {\n ...schema._zod.def,\n shape: newShape,\n checks: [],\n });\n}\nexport function omit(schema, mask) {\n const newShape = { ...schema._zod.def.shape };\n const currDef = schema._zod.def; //.shape;\n for (const key in mask) {\n if (!(key in currDef.shape)) {\n throw new Error(`Unrecognized key: \"${key}\"`);\n }\n if (!mask[key])\n continue;\n delete newShape[key];\n }\n return clone(schema, {\n ...schema._zod.def,\n shape: newShape,\n checks: [],\n });\n}\nexport function extend(schema, shape) {\n const def = {\n ...schema._zod.def,\n get shape() {\n const _shape = { ...schema._zod.def.shape, ...shape };\n assignProp(this, \"shape\", _shape); // self-caching\n return _shape;\n },\n checks: [], // delete existing checks\n };\n return clone(schema, def);\n}\nexport function merge(a, b) {\n return clone(a, {\n ...a._zod.def,\n get shape() {\n const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };\n assignProp(this, \"shape\", _shape); // self-caching\n return _shape;\n },\n catchall: b._zod.def.catchall,\n checks: [], // delete existing checks\n });\n}\nexport function partial(Class, schema, mask) {\n const oldShape = schema._zod.def.shape;\n const shape = { ...oldShape };\n if (mask) {\n for (const key in mask) {\n if (!(key in oldShape)) {\n throw new Error(`Unrecognized key: \"${key}\"`);\n }\n if (!mask[key])\n continue;\n shape[key] = Class\n ? new Class({\n type: \"optional\",\n innerType: oldShape[key],\n })\n : oldShape[key];\n }\n }\n else {\n for (const key in oldShape) {\n shape[key] = Class\n ? new Class({\n type: \"optional\",\n innerType: oldShape[key],\n })\n : oldShape[key];\n }\n }\n return clone(schema, {\n ...schema._zod.def,\n shape,\n checks: [],\n });\n}\nexport function required(Class, schema, mask) {\n const oldShape = schema._zod.def.shape;\n const shape = { ...oldShape };\n if (mask) {\n for (const key in mask) {\n if (!(key in shape)) {\n throw new Error(`Unrecognized key: \"${key}\"`);\n }\n if (!mask[key])\n continue;\n // overwrite with non-optional\n shape[key] = new Class({\n type: \"nonoptional\",\n innerType: oldShape[key],\n });\n }\n }\n else {\n for (const key in oldShape) {\n // overwrite with non-optional\n shape[key] = new Class({\n type: \"nonoptional\",\n innerType: oldShape[key],\n });\n }\n }\n return clone(schema, {\n ...schema._zod.def,\n shape,\n // optional: [],\n checks: [],\n });\n}\nexport function aborted(x, startIndex = 0) {\n for (let i = startIndex; i < x.issues.length; i++) {\n if (x.issues[i].continue !== true)\n return true;\n }\n return false;\n}\nexport function prefixIssues(path, issues) {\n return issues.map((iss) => {\n var _a;\n (_a = iss).path ?? (_a.path = []);\n iss.path.unshift(path);\n return iss;\n });\n}\nexport function unwrapMessage(message) {\n return typeof message === \"string\" ? message : message?.message;\n}\nexport function finalizeIssue(iss, ctx, config) {\n const full = { ...iss, path: iss.path ?? [] };\n // for backwards compatibility\n if (!iss.message) {\n const message = unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ??\n unwrapMessage(ctx?.error?.(iss)) ??\n unwrapMessage(config.customError?.(iss)) ??\n unwrapMessage(config.localeError?.(iss)) ??\n \"Invalid input\";\n full.message = message;\n }\n // delete (full as any).def;\n delete full.inst;\n delete full.continue;\n if (!ctx?.reportInput) {\n delete full.input;\n }\n return full;\n}\nexport function getSizableOrigin(input) {\n if (input instanceof Set)\n return \"set\";\n if (input instanceof Map)\n return \"map\";\n if (input instanceof File)\n return \"file\";\n return \"unknown\";\n}\nexport function getLengthableOrigin(input) {\n if (Array.isArray(input))\n return \"array\";\n if (typeof input === \"string\")\n return \"string\";\n return \"unknown\";\n}\nexport function issue(...args) {\n const [iss, input, inst] = args;\n if (typeof iss === \"string\") {\n return {\n message: iss,\n code: \"custom\",\n input,\n inst,\n };\n }\n return { ...iss };\n}\nexport function cleanEnum(obj) {\n return Object.entries(obj)\n .filter(([k, _]) => {\n // return true if NaN, meaning it's not a number, thus a string key\n return Number.isNaN(Number.parseInt(k, 10));\n })\n .map((el) => el[1]);\n}\n// instanceof\nexport class Class {\n constructor(..._args) { }\n}\n","import { $constructor } from \"./core.js\";\nimport * as util from \"./util.js\";\nconst initializer = (inst, def) => {\n inst.name = \"$ZodError\";\n Object.defineProperty(inst, \"_zod\", {\n value: inst._zod,\n enumerable: false,\n });\n Object.defineProperty(inst, \"issues\", {\n value: def,\n enumerable: false,\n });\n Object.defineProperty(inst, \"message\", {\n get() {\n return JSON.stringify(def, util.jsonStringifyReplacer, 2);\n },\n enumerable: true,\n // configurable: false,\n });\n};\nexport const $ZodError = $constructor(\"$ZodError\", initializer);\nexport const $ZodRealError = $constructor(\"$ZodError\", initializer, { Parent: Error });\nexport function flattenError(error, mapper = (issue) => issue.message) {\n const fieldErrors = {};\n const formErrors = [];\n for (const sub of error.issues) {\n if (sub.path.length > 0) {\n fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];\n fieldErrors[sub.path[0]].push(mapper(sub));\n }\n else {\n formErrors.push(mapper(sub));\n }\n }\n return { formErrors, fieldErrors };\n}\nexport function formatError(error, _mapper) {\n const mapper = _mapper ||\n function (issue) {\n return issue.message;\n };\n const fieldErrors = { _errors: [] };\n const processError = (error) => {\n for (const issue of error.issues) {\n if (issue.code === \"invalid_union\" && issue.errors.length) {\n issue.errors.map((issues) => processError({ issues }));\n }\n else if (issue.code === \"invalid_key\") {\n processError({ issues: issue.issues });\n }\n else if (issue.code === \"invalid_element\") {\n processError({ issues: issue.issues });\n }\n else if (issue.path.length === 0) {\n fieldErrors._errors.push(mapper(issue));\n }\n else {\n let curr = fieldErrors;\n let i = 0;\n while (i < issue.path.length) {\n const el = issue.path[i];\n const terminal = i === issue.path.length - 1;\n if (!terminal) {\n curr[el] = curr[el] || { _errors: [] };\n }\n else {\n curr[el] = curr[el] || { _errors: [] };\n curr[el]._errors.push(mapper(issue));\n }\n curr = curr[el];\n i++;\n }\n }\n }\n };\n processError(error);\n return fieldErrors;\n}\nexport function treeifyError(error, _mapper) {\n const mapper = _mapper ||\n function (issue) {\n return issue.message;\n };\n const result = { errors: [] };\n const processError = (error, path = []) => {\n var _a, _b;\n for (const issue of error.issues) {\n if (issue.code === \"invalid_union\" && issue.errors.length) {\n // regular union error\n issue.errors.map((issues) => processError({ issues }, issue.path));\n }\n else if (issue.code === \"invalid_key\") {\n processError({ issues: issue.issues }, issue.path);\n }\n else if (issue.code === \"invalid_element\") {\n processError({ issues: issue.issues }, issue.path);\n }\n else {\n const fullpath = [...path, ...issue.path];\n if (fullpath.length === 0) {\n result.errors.push(mapper(issue));\n continue;\n }\n let curr = result;\n let i = 0;\n while (i < fullpath.length) {\n const el = fullpath[i];\n const terminal = i === fullpath.length - 1;\n if (typeof el === \"string\") {\n curr.properties ?? (curr.properties = {});\n (_a = curr.properties)[el] ?? (_a[el] = { errors: [] });\n curr = curr.properties[el];\n }\n else {\n curr.items ?? (curr.items = []);\n (_b = curr.items)[el] ?? (_b[el] = { errors: [] });\n curr = curr.items[el];\n }\n if (terminal) {\n curr.errors.push(mapper(issue));\n }\n i++;\n }\n }\n }\n };\n processError(error);\n return result;\n}\n/** Format a ZodError as a human-readable string in the following form.\n *\n * From\n *\n * ```ts\n * ZodError {\n * issues: [\n * {\n * expected: 'string',\n * code: 'invalid_type',\n * path: [ 'username' ],\n * message: 'Invalid input: expected string'\n * },\n * {\n * expected: 'number',\n * code: 'invalid_type',\n * path: [ 'favoriteNumbers', 1 ],\n * message: 'Invalid input: expected number'\n * }\n * ];\n * }\n * ```\n *\n * to\n *\n * ```\n * username\n * ✖ Expected number, received string at \"username\n * favoriteNumbers[0]\n * ✖ Invalid input: expected number\n * ```\n */\nexport function toDotPath(path) {\n const segs = [];\n for (const seg of path) {\n if (typeof seg === \"number\")\n segs.push(`[${seg}]`);\n else if (typeof seg === \"symbol\")\n segs.push(`[${JSON.stringify(String(seg))}]`);\n else if (/[^\\w$]/.test(seg))\n segs.push(`[${JSON.stringify(seg)}]`);\n else {\n if (segs.length)\n segs.push(\".\");\n segs.push(seg);\n }\n }\n return segs.join(\"\");\n}\nexport function prettifyError(error) {\n const lines = [];\n // sort by path length\n const issues = [...error.issues].sort((a, b) => a.path.length - b.path.length);\n // Process each issue\n for (const issue of issues) {\n lines.push(`✖ ${issue.message}`);\n if (issue.path?.length)\n lines.push(` → at ${toDotPath(issue.path)}`);\n }\n // Convert Map to formatted string\n return lines.join(\"\\n\");\n}\n","import * as core from \"./core.js\";\nimport * as errors from \"./errors.js\";\nimport * as util from \"./util.js\";\nexport const _parse = (_Err) => (schema, value, _ctx, _params) => {\n const ctx = _ctx ? Object.assign(_ctx, { async: false }) : { async: false };\n const result = schema._zod.run({ value, issues: [] }, ctx);\n if (result instanceof Promise) {\n throw new core.$ZodAsyncError();\n }\n if (result.issues.length) {\n const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => util.finalizeIssue(iss, ctx, core.config())));\n Error.