@reliverse/dler 1.7.52 → 1.7.54

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.
@@ -128,8 +128,14 @@ async function compareFileStructures(srcDir, distDir) {
128
128
  onlyFiles: true,
129
129
  dot: true
130
130
  });
131
- const srcSet = new Set(srcFiles);
132
- const distSet = new Set(distFiles);
131
+ const filteredSrcFiles = srcFiles.filter(
132
+ (file) => !file.endsWith(".test.ts") && !file.endsWith(".test.js")
133
+ );
134
+ const filteredDistFiles = distFiles.filter(
135
+ (file) => !file.endsWith(".test.ts") && !file.endsWith(".test.js")
136
+ );
137
+ const srcSet = new Set(filteredSrcFiles);
138
+ const distSet = new Set(filteredDistFiles);
133
139
  const onlyInSrc = [...srcSet].filter((x) => !distSet.has(x));
134
140
  const onlyInDist = [...distSet].filter((x) => !srcSet.has(x));
135
141
  if (onlyInSrc.length > 0 || onlyInDist.length > 0) {
@@ -8,7 +8,7 @@ import stripJsonComments from "strip-json-comments";
8
8
  import { isBinaryExt } from "../../libs/sdk/sdk-impl/utils/binary.js";
9
9
  const WHITELABEL_DEFAULT = "DLER";
10
10
  const TEMPLATE_VAR = (name, whitelabel) => `${whitelabel}_TPL_${name.toUpperCase()}`;
11
- const TPLS_DIR = "templates";
11
+ const TPLS_DIR = "packed";
12
12
  const BINARIES_DIR = "binaries";
13
13
  export const escapeTemplateString = (str) => str.replace(/`/g, "\\`").replace(/\\\${/g, "\\u0024{").replace(/\$\{/g, "\\${").replace(/\\\{\{/g, "{{").replace(/\\\}\}/g, "}}").replace(/\r?\n/g, "\\n");
14
14
  export const unescapeTemplateString = (str) => str.replace(/\\n/g, "\n").replace(/\\u0024\{/g, "\\${").replace(/\\\\`/g, "`").replace(/\\\\/g, "\\");
@@ -1,20 +1,20 @@
1
1
  import type { RseConfig } from "./rse-types";
2
2
  export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
3
+ version?: string | undefined;
3
4
  $schema?: "./schema.json" | "https://reliverse.org/schema.json" | undefined;
4
5
  projectName?: string | undefined;
5
6
  projectAuthor?: string | undefined;
6
7
  projectDescription?: string | undefined;
7
- version?: string | undefined;
8
8
  projectLicense?: string | undefined;
9
9
  projectRepository?: string | undefined;
10
10
  projectDomain?: string | undefined;
11
11
  projectGitService?: "none" | "github" | "gitlab" | "bitbucket" | undefined;
12
12
  projectDeployService?: "none" | "vercel" | "netlify" | "railway" | "deno" | undefined;
13
- projectPackageManager?: "npm" | "pnpm" | "bun" | "yarn" | undefined;
13
+ projectPackageManager?: "npm" | "bun" | "yarn" | "pnpm" | undefined;
14
14
  projectState?: "creating" | "created" | undefined;
15
- projectCategory?: "cli" | "unknown" | "website" | "vscode" | "browser" | "library" | "mobile" | undefined;
15
+ projectCategory?: "browser" | "cli" | "unknown" | "website" | "vscode" | "library" | "mobile" | undefined;
16
16
  projectSubcategory?: "unknown" | "e-commerce" | "tool" | undefined;
17
- projectFramework?: "rempts" | "npm-jsr" | "unknown" | "vscode" | "nextjs" | "vite" | "svelte" | "remix" | "astro" | "nuxt" | "solid" | "qwik" | "vue" | "wxt" | "lynx" | "react-native" | "expo" | "capacitor" | "ionic" | "electron" | "tauri" | "neutralino" | "citty" | "commander" | "cac" | "meow" | "yargs" | "webextension" | "browser-extension" | undefined;
17
+ projectFramework?: "npm-jsr" | "vue" | "rempts" | "svelte" | "unknown" | "vscode" | "nextjs" | "vite" | "remix" | "astro" | "nuxt" | "solid" | "qwik" | "wxt" | "lynx" | "react-native" | "expo" | "capacitor" | "ionic" | "electron" | "tauri" | "neutralino" | "citty" | "commander" | "cac" | "meow" | "yargs" | "webextension" | "browser-extension" | undefined;
18
18
  projectTemplate?: "unknown" | "blefnk/relivator-nextjs-template" | "blefnk/relivator-docker-template" | "blefnk/next-react-ts-src-minimal" | "blefnk/all-in-one-nextjs-template" | "blefnk/create-t3-app" | "blefnk/create-next-app" | "blefnk/astro-starlight-template" | "blefnk/versator-nextjs-template" | "blefnk/relivator-lynxjs-template" | "blefnk/relivator-react-native-template" | "reliverse/template-browser-extension" | "microsoft/vscode-extension-samples" | "microsoft/vscode-extension-template" | "rsetarter-template" | "blefnk/deno-cli-tutorial" | undefined;
19
19
  projectTemplateDate?: string | undefined;
20
20
  features?: {
@@ -38,15 +38,15 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
38
38
  analytics?: "unknown" | "vercel" | undefined;
39
39
  authentication?: "unknown" | "better-auth" | "clerk" | "next-auth" | "supabase-auth" | "auth0" | undefined;
40
40
  api?: "rest" | "unknown" | "hono" | "trpc" | "graphql" | undefined;
41
- testing?: "unknown" | "bun" | "vitest" | "jest" | "playwright" | "cypress" | undefined;
41
+ testing?: "bun" | "jest" | "vitest" | "unknown" | "playwright" | "cypress" | undefined;
42
42
  stateManagement?: "unknown" | "zustand" | "jotai" | "redux-toolkit" | undefined;
43
43
  formManagement?: "unknown" | "react-hook-form" | "formik" | undefined;
44
- styling?: "unknown" | "tailwind" | "styled-components" | "css-modules" | "sass" | undefined;
44
+ styling?: "sass" | "unknown" | "tailwind" | "styled-components" | "css-modules" | undefined;
45
45
  uiComponents?: "unknown" | "shadcn-ui" | "chakra-ui" | "material-ui" | undefined;
46
46
  databaseLibrary?: "unknown" | "drizzle" | "prisma" | "supabase" | undefined;
47
- databaseProvider?: "sqlite" | "unknown" | "pg" | "mysql" | "mongodb" | undefined;
48
- linting?: "unknown" | "eslint" | undefined;
49
- formatting?: "unknown" | "biome" | undefined;
47
+ databaseProvider?: "sqlite" | "pg" | "unknown" | "mysql" | "mongodb" | undefined;
48
+ linting?: "eslint" | "unknown" | undefined;
49
+ formatting?: "biome" | "unknown" | undefined;
50
50
  payment?: "unknown" | "stripe" | undefined;
51
51
  monitoring?: "unknown" | "sentry" | undefined;
52
52
  logging?: "unknown" | "axiom" | undefined;
@@ -57,7 +57,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
57
57
  documentation?: "unknown" | "starlight" | "nextra" | undefined;
58
58
  icons?: "unknown" | "lucide" | undefined;
59
59
  mail?: "unknown" | "resend" | undefined;
60
- cache?: "unknown" | "redis" | undefined;
60
+ cache?: "redis" | "unknown" | undefined;
61
61
  storage?: "unknown" | "cloudflare" | undefined;
62
62
  cdn?: "unknown" | "cloudflare" | undefined;
63
63
  cms?: "unknown" | "contentlayer" | undefined;
@@ -67,7 +67,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
67
67
  dates?: "unknown" | "dayjs" | undefined;
68
68
  markdown?: "unknown" | "mdx" | undefined;
69
69
  security?: "unknown" | "auth" | undefined;
70
- routing?: "unknown" | "next" | "react-router" | "tanstack-router" | undefined;
70
+ routing?: "next" | "unknown" | "react-router" | "tanstack-router" | undefined;
71
71
  } | undefined;
72
72
  codeStyle?: {
73
73
  lineWidth?: number | undefined;
@@ -75,7 +75,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
75
75
  indentStyle?: "space" | "tab" | undefined;
76
76
  quoteMark?: "single" | "double" | undefined;
77
77
  semicolons?: boolean | undefined;
78
- trailingComma?: "none" | "es5" | "all" | undefined;
78
+ trailingComma?: "none" | "all" | "es5" | undefined;
79
79
  bracketSpacing?: boolean | undefined;
80
80
  arrowParens?: "always" | "avoid" | undefined;
81
81
  tabWidth?: number | undefined;
@@ -83,7 +83,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
83
83
  dontRemoveComments?: boolean | undefined;
84
84
  shouldAddComments?: boolean | undefined;
85
85
  typeOrInterface?: "type" | "interface" | "mixed" | undefined;
86
- importOrRequire?: "mixed" | "import" | "require" | undefined;
86
+ importOrRequire?: "import" | "require" | "mixed" | undefined;
87
87
  cjsToEsm?: boolean | undefined;
88
88
  modernize?: {
89
89
  replaceFs?: boolean | undefined;
@@ -96,7 +96,7 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
96
96
  importSymbol?: string | undefined;
97
97
  } | undefined;
98
98
  monorepo?: {
99
- type?: "none" | "turborepo" | "nx" | "pnpm" | "bun" | undefined;
99
+ type?: "none" | "bun" | "pnpm" | "turborepo" | "nx" | undefined;
100
100
  packages?: string[] | undefined;
101
101
  sharedPackages?: string[] | undefined;
102
102
  } | undefined;
@@ -111,9 +111,9 @@ export declare const defineConfigRse: (userConfig?: Partial<RseConfig>) => {
111
111
  customReposOnNewProject?: boolean | undefined;
112
112
  envComposerOpenBrowser?: boolean | undefined;
113
113
  repoBranch?: string | undefined;
114
- repoPrivacy?: "unknown" | "public" | "private" | undefined;
114
+ repoPrivacy?: "private" | "public" | "unknown" | undefined;
115
115
  projectArchitecture?: "unknown" | "fullstack" | "separated" | undefined;
116
- projectRuntime?: "bun" | "deno" | "node" | undefined;
116
+ projectRuntime?: "bun" | "node" | "deno" | undefined;
117
117
  skipPromptsUseAutoBehavior?: boolean | undefined;
118
118
  deployBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
119
119
  depsBehavior?: "prompt" | "autoYes" | "autoNo" | undefined;
@@ -1,5 +1,6 @@
1
1
  import { isAbsolute, normalize, relative, resolve } from "@reliverse/pathkit";
2
2
  import { relinka } from "@reliverse/relinka";
3
+ import { useSpinner } from "@reliverse/rempts";
3
4
  import { defu } from "defu";
4
5
  import { createHooks } from "hookable";
5
6
  import { createJiti } from "jiti";
@@ -10,7 +11,6 @@ import prettyMilliseconds from "pretty-ms";
10
11
  import { glob } from "tinyglobby";
11
12
  import { createPerfTimer, getElapsedPerfTime } from "../../../utils/utils-perf.js";
12
13
  import { copyBuild } from "./copy/copy-mod.js";
13
- import { useSpinner } from "./mkdist/mkdist-impl/utils/spinner.js";
14
14
  import { mkdistBuild } from "./mkdist/mkdist-mod.js";
15
15
  import { rollupBuild } from "./rollup/build.js";
16
16
  import { typesBuild } from "./untyped/untyped-mod.js";
@@ -1,11 +1,11 @@
1
1
  import { resolve, extname, join, basename, dirname } from "@reliverse/pathkit";
2
+ import { useSpinner } from "@reliverse/rempts";
2
3
  import defu from "defu";
3
4
  import fsp from "node:fs/promises";
4
5
  import { glob } from "tinyglobby";
5
6
  import { createLoader } from "./loader.js";
6
7
  import { getDeclarations, normalizeCompilerOptions } from "./utils/dts.js";
7
8
  import { copyFileWithStream } from "./utils/fs.js";
8
- import { useSpinner } from "./utils/spinner.js";
9
9
  import { getVueDeclarations } from "./utils/vue-dts.js";
10
10
  export async function mkdist(options = {}) {
11
11
  return await useSpinner.withTiming(
@@ -1,8 +1,8 @@
1
1
  import { relative, dirname as pathDirname } from "@reliverse/pathkit";
2
2
  import { relinka } from "@reliverse/relinka";
3
+ import { useSpinner } from "@reliverse/rempts";
3
4
  import { rmdir, symlink, warn } from "../utils.js";
4
5
  import { mkdist } from "./mkdist-impl/make.js";
5
- import { useSpinner } from "./mkdist-impl/utils/spinner.js";
6
6
  export async function mkdistBuild(ctx) {
7
7
  const entries = ctx.options.entries.filter((e) => e.builder === "mkdist");
8
8
  if (entries.length === 0) {
@@ -1,5 +1,5 @@
1
1
  import { endPrompt, startPrompt } from "@reliverse/rempts";
2
- const version = "1.7.52";
2
+ const version = "1.7.54";
3
3
  export async function showStartPrompt(isDev) {
4
4
  await startPrompt({
5
5
  titleColor: "inverse",
@@ -16,7 +16,6 @@ export { mkdist } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/mak
16
16
  export type { DeclarationOutput } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/dts.js";
17
17
  export { normalizeCompilerOptions, getDeclarations, extractDeclarations, augmentWithDiagnostics, } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/dts.js";
18
18
  export { copyFileWithStream } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/fs.js";
19
- export { useSpinner } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/spinner.js";
20
19
  export { getVueDeclarations } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/vue-dts.js";
21
20
  export { mkdistBuild } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-mod.js";
22
21
  export { rollupBuild } from "./sdk-impl/build/bundlers/unified/rollup/build.js";
@@ -24,7 +24,6 @@ export {
24
24
  augmentWithDiagnostics
25
25
  } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/dts.js";
26
26
  export { copyFileWithStream } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/fs.js";
27
- export { useSpinner } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/spinner.js";
28
27
  export { getVueDeclarations } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-impl/utils/vue-dts.js";
29
28
  export { mkdistBuild } from "./sdk-impl/build/bundlers/unified/mkdist/mkdist-mod.js";
30
29
  export { rollupBuild } from "./sdk-impl/build/bundlers/unified/rollup/build.js";
package/package.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "@reliverse/relico": "^1.1.2",
7
7
  "@reliverse/relifso": "^1.4.5",
8
8
  "@reliverse/relinka": "^1.4.7",
9
- "@reliverse/rempts": "^1.7.28",
9
+ "@reliverse/rempts": "^1.7.29",
10
10
  "@reliverse/runtime": "^1.0.3",
11
11
  "@rollup/plugin-alias": "^5.1.1",
12
12
  "@rollup/plugin-commonjs": "^28.0.6",
@@ -32,7 +32,6 @@
32
32
  "magic-string": "^0.30.17",
33
33
  "mlly": "^1.7.4",
34
34
  "nypm": "^0.6.0",
35
- "ora": "^8.2.0",
36
35
  "p-all": "^5.0.0",
37
36
  "p-map": "^7.0.3",
38
37
  "pkg-types": "^2.1.0",
@@ -54,7 +53,7 @@
54
53
  "license": "MIT",
55
54
  "name": "@reliverse/dler",
56
55
  "type": "module",
57
- "version": "1.7.52",
56
+ "version": "1.7.54",
58
57
  "keywords": [
59
58
  "reliverse",
60
59
  "cli",
@@ -1,99 +0,0 @@
1
- import { type Color, type Options as OraOptions } from "ora";
2
- interface SpinnerOptions {
3
- text: string;
4
- color?: Color;
5
- spinner?: OraOptions["spinner"];
6
- successText?: string;
7
- failText?: string;
8
- prefixText?: string;
9
- silent?: boolean;
10
- hideCursor?: boolean;
11
- }
12
- interface ProgressOptions {
13
- current: number;
14
- total: number;
15
- format?: "percentage" | "count" | "both";
16
- }
17
- interface SpinnerControls {
18
- start: (text?: string) => SpinnerControls;
19
- stop: () => void;
20
- setText: (text: string) => void;
21
- setProgress: (progress: ProgressOptions) => void;
22
- succeed: (text?: string) => void;
23
- fail: (text?: string) => void;
24
- warn: (text?: string) => void;
25
- info: (text?: string) => void;
26
- isSpinning: () => boolean;
27
- clear: () => void;
28
- getElapsedTime: () => number;
29
- pause: () => void;
30
- resume: () => void;
31
- dispose: () => void;
32
- }
33
- /**
34
- * Creates a terminal spinner with enhanced controls and styling options.
35
- *
36
- * @example
37
- * ```typescript
38
- * // Basic usage
39
- * const spinner = useSpinner({ text: "Loading..." }).start();
40
- * spinner.stop();
41
- *
42
- * // With progress tracking
43
- * const spinner = useSpinner({ text: "Processing files..." }).start();
44
- * for (let i = 0; i < files.length; i++) {
45
- * spinner.setProgress({ current: i + 1, total: files.length });
46
- * await processFile(files[i]);
47
- * }
48
- * spinner.succeed();
49
- *
50
- * // With custom color and spinner
51
- * const spinner = useSpinner({
52
- * text: "Processing...",
53
- * color: "cyan",
54
- * spinner: "dots"
55
- * }).start();
56
- *
57
- * // With success/failure states
58
- * const spinner = useSpinner({
59
- * text: "Uploading...",
60
- * successText: "Upload complete!",
61
- * failText: "Upload failed!"
62
- * }).start();
63
- * try {
64
- * await uploadFile();
65
- * spinner.succeed();
66
- * } catch (error) {
67
- * spinner.fail();
68
- * }
69
- *
70
- * // Using the wrapper for async operations
71
- * await useSpinner.promise(
72
- * async (spinner) => {
73
- * await longOperation();
74
- * spinner.setProgress({ current: 50, total: 100 });
75
- * },
76
- * {
77
- * text: "Working...",
78
- * successText: "Done!",
79
- * failText: "Failed!"
80
- * }
81
- * );
82
- * ```
83
- */
84
- export declare function useSpinner(options: SpinnerOptions): SpinnerControls;
85
- export declare namespace useSpinner {
86
- var promise: <T>(operation: (spinner: SpinnerControls) => Promise<T>, options: SpinnerOptions) => Promise<T>;
87
- var nested: (parentOptions: SpinnerOptions) => {
88
- start: () => {
89
- child: (childOptions: SpinnerOptions) => SpinnerControls;
90
- finish: (success: boolean, text?: string) => void;
91
- dispose: () => void;
92
- };
93
- };
94
- var withTiming: <T>(operation: (spinner: SpinnerControls) => Promise<T>, options: SpinnerOptions) => Promise<{
95
- result: T;
96
- duration: number;
97
- }>;
98
- }
99
- export {};
@@ -1,206 +0,0 @@
1
- import ora from "ora";
2
- function isInteractive() {
3
- return process.stdout.isTTY && !process.env.CI && !process.env.GITHUB_ACTIONS && !process.env.GITLAB_CI && !process.env.BUILDKITE && process.env.TERM !== "dumb";
4
- }
5
- function formatProgress(options) {
6
- const { current, total, format = "both" } = options;
7
- const percentage = Math.round(current / total * 100);
8
- switch (format) {
9
- case "percentage":
10
- return `${percentage}%`;
11
- case "count":
12
- return `${current}/${total}`;
13
- case "both":
14
- return `${current}/${total} (${percentage}%)`;
15
- default:
16
- return `${current}/${total}`;
17
- }
18
- }
19
- export function useSpinner(options) {
20
- let spinnerInstance = null;
21
- const interactive = isInteractive();
22
- const state = {
23
- isActive: false,
24
- isPaused: false,
25
- startTime: null,
26
- pausedTime: 0,
27
- text: options.text
28
- };
29
- const controls = {
30
- start: (text) => {
31
- if (text) {
32
- options.text = text;
33
- state.text = text;
34
- }
35
- if (options.silent || !interactive) {
36
- console.log(options.prefixText ? `${options.prefixText} ${options.text}` : options.text);
37
- state.isActive = true;
38
- state.startTime = Date.now();
39
- return controls;
40
- }
41
- if (!spinnerInstance) {
42
- spinnerInstance = ora({
43
- text: options.text,
44
- color: options.color,
45
- spinner: options.spinner,
46
- hideCursor: options.hideCursor,
47
- prefixText: options.prefixText
48
- });
49
- } else {
50
- spinnerInstance.text = options.text;
51
- }
52
- spinnerInstance.start();
53
- state.isActive = true;
54
- state.startTime = Date.now();
55
- return controls;
56
- },
57
- stop: () => {
58
- if (spinnerInstance) {
59
- spinnerInstance.stop();
60
- }
61
- state.isActive = false;
62
- },
63
- setText: (text) => {
64
- state.text = text;
65
- if (spinnerInstance && !state.isPaused) {
66
- spinnerInstance.text = text;
67
- } else if (options.silent || !interactive) {
68
- console.log(options.prefixText ? `${options.prefixText} ${text}` : text);
69
- }
70
- options.text = text;
71
- },
72
- setProgress: (progress) => {
73
- const progressText = formatProgress(progress);
74
- const newText = `${state.text} [${progressText}]`;
75
- if (spinnerInstance && !state.isPaused) {
76
- spinnerInstance.text = newText;
77
- } else if (options.silent || !interactive) {
78
- console.log(options.prefixText ? `${options.prefixText} ${newText}` : newText);
79
- }
80
- },
81
- succeed: (text) => {
82
- const successText = text ?? options.successText ?? state.text;
83
- if (spinnerInstance) {
84
- spinnerInstance.succeed(successText);
85
- } else {
86
- console.log(`\u2713 ${successText}`);
87
- }
88
- state.isActive = false;
89
- },
90
- fail: (text) => {
91
- const failText = text ?? options.failText ?? state.text;
92
- if (spinnerInstance) {
93
- spinnerInstance.fail(failText);
94
- } else {
95
- console.error(`\u2717 ${failText}`);
96
- }
97
- state.isActive = false;
98
- },
99
- warn: (text) => {
100
- const warnText = text ?? state.text;
101
- if (spinnerInstance) {
102
- spinnerInstance.warn(warnText);
103
- } else {
104
- console.warn(`\u26A0 ${warnText}`);
105
- }
106
- },
107
- info: (text) => {
108
- const infoText = text ?? state.text;
109
- if (spinnerInstance) {
110
- spinnerInstance.info(infoText);
111
- } else {
112
- console.info(`\u2139 ${infoText}`);
113
- }
114
- },
115
- isSpinning: () => {
116
- return state.isActive && !state.isPaused;
117
- },
118
- clear: () => {
119
- if (spinnerInstance) {
120
- spinnerInstance.clear();
121
- }
122
- },
123
- getElapsedTime: () => {
124
- if (!state.startTime) return 0;
125
- const currentTime = Date.now();
126
- return currentTime - state.startTime - state.pausedTime;
127
- },
128
- pause: () => {
129
- if (state.isActive && !state.isPaused) {
130
- if (spinnerInstance) {
131
- spinnerInstance.stop();
132
- }
133
- state.isPaused = true;
134
- }
135
- },
136
- resume: () => {
137
- if (state.isActive && state.isPaused) {
138
- if (spinnerInstance) {
139
- spinnerInstance.start();
140
- }
141
- state.isPaused = false;
142
- }
143
- },
144
- dispose: () => {
145
- if (spinnerInstance) {
146
- spinnerInstance.stop();
147
- spinnerInstance = null;
148
- }
149
- state.isActive = false;
150
- state.isPaused = false;
151
- }
152
- };
153
- return controls;
154
- }
155
- useSpinner.promise = async (operation, options) => {
156
- const spinner = useSpinner(options).start();
157
- try {
158
- const result = await operation(spinner);
159
- spinner.succeed();
160
- return result;
161
- } catch (error) {
162
- spinner.fail();
163
- throw error;
164
- } finally {
165
- spinner.dispose();
166
- }
167
- };
168
- useSpinner.nested = (parentOptions) => {
169
- const parentSpinner = useSpinner({
170
- ...parentOptions,
171
- silent: true
172
- // Parent is silent, children will show progress
173
- });
174
- return {
175
- start: () => {
176
- parentSpinner.start();
177
- return {
178
- child: (childOptions) => useSpinner(childOptions),
179
- finish: (success, text) => {
180
- if (success) {
181
- parentSpinner.succeed(text);
182
- } else {
183
- parentSpinner.fail(text);
184
- }
185
- },
186
- dispose: () => parentSpinner.dispose()
187
- };
188
- }
189
- };
190
- };
191
- useSpinner.withTiming = async (operation, options) => {
192
- const spinner = useSpinner(options).start();
193
- const startTime = Date.now();
194
- try {
195
- const result = await operation(spinner);
196
- const duration = Date.now() - startTime;
197
- spinner.succeed(`${options.successText || options.text} (${duration}ms)`);
198
- return { result, duration };
199
- } catch (error) {
200
- const duration = Date.now() - startTime;
201
- spinner.fail(`${options.failText || options.text} (failed after ${duration}ms)`);
202
- throw error;
203
- } finally {
204
- spinner.dispose();
205
- }
206
- };