@atomic-ehr/codegen 0.0.1-canary.20250822114054.4ca1428 → 0.0.1-canary.20250822150706.c3b8669
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/builder.d.ts +3 -3
- package/dist/api/builder.d.ts.map +1 -1
- package/dist/api/builder.js +374 -0
- package/dist/api/generators/base/BaseGenerator.d.ts +4 -4
- package/dist/api/generators/base/BaseGenerator.d.ts.map +1 -1
- package/dist/api/generators/base/BaseGenerator.js +572 -0
- package/dist/api/generators/base/FileManager.d.ts +2 -2
- package/dist/api/generators/base/FileManager.d.ts.map +1 -1
- package/dist/api/generators/base/FileManager.js +204 -0
- package/dist/api/generators/base/PythonTypeMapper.d.ts +2 -2
- package/dist/api/generators/base/PythonTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/PythonTypeMapper.js +71 -0
- package/dist/api/generators/base/TemplateEngine.d.ts +1 -1
- package/dist/api/generators/base/TemplateEngine.d.ts.map +1 -1
- package/dist/api/generators/base/TemplateEngine.js +133 -0
- package/dist/api/generators/base/TypeMapper.js +153 -0
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.d.ts.map +1 -1
- package/dist/api/generators/base/TypeScriptTypeMapper.js +232 -0
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts +4 -4
- package/dist/api/generators/base/builders/DirectoryBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/DirectoryBuilder.js +215 -0
- package/dist/api/generators/base/builders/FileBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/FileBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/FileBuilder.js +408 -0
- package/dist/api/generators/base/builders/IndexBuilder.d.ts +2 -2
- package/dist/api/generators/base/builders/IndexBuilder.d.ts.map +1 -1
- package/dist/api/generators/base/builders/IndexBuilder.js +290 -0
- package/dist/api/generators/base/enhanced-errors.d.ts +2 -2
- package/dist/api/generators/base/enhanced-errors.d.ts.map +1 -1
- package/dist/api/generators/base/enhanced-errors.js +259 -0
- package/dist/api/generators/base/error-handler.d.ts +1 -1
- package/dist/api/generators/base/error-handler.d.ts.map +1 -1
- package/dist/api/generators/base/error-handler.js +243 -0
- package/dist/api/generators/base/errors.d.ts +2 -2
- package/dist/api/generators/base/errors.d.ts.map +1 -1
- package/dist/api/generators/base/errors.js +694 -0
- package/dist/api/generators/base/index.d.ts +22 -22
- package/dist/api/generators/base/index.d.ts.map +1 -1
- package/dist/api/generators/base/index.js +161 -0
- package/dist/api/generators/base/types.d.ts +2 -2
- package/dist/api/generators/base/types.d.ts.map +1 -1
- package/dist/api/generators/base/types.js +12 -0
- package/dist/api/generators/rest-client.d.ts +2 -2
- package/dist/api/generators/rest-client.d.ts.map +1 -1
- package/dist/api/generators/rest-client.js +847 -0
- package/dist/api/generators/search-parameter-enhancer.d.ts +1 -1
- package/dist/api/generators/search-parameter-enhancer.d.ts.map +1 -1
- package/dist/api/generators/search-parameter-enhancer.js +801 -0
- package/dist/api/generators/types.js +4 -0
- package/dist/api/generators/typescript.d.ts +3 -3
- package/dist/api/generators/typescript.d.ts.map +1 -1
- package/dist/api/generators/typescript.js +537 -0
- package/dist/api/generators/validation-generator.js +632 -0
- package/dist/api/index.d.ts +10 -10
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +51 -0
- package/dist/cli/commands/generate/typescript.d.ts +1 -1
- package/dist/cli/commands/generate/typescript.d.ts.map +1 -1
- package/dist/cli/commands/generate/typescript.js +52 -0
- package/dist/cli/commands/generate.d.ts +5 -12
- package/dist/cli/commands/generate.d.ts.map +1 -1
- package/dist/cli/commands/generate.js +158 -0
- package/dist/cli/commands/index.d.ts +2 -1
- package/dist/cli/commands/index.d.ts.map +1 -1
- package/dist/cli/commands/index.js +100 -0
- package/dist/cli/commands/typeschema/generate.js +130 -0
- package/dist/cli/commands/typeschema.js +48 -0
- package/dist/cli/index.js +12 -8664
- package/dist/cli/utils/log.d.ts +2 -2
- package/dist/cli/utils/log.d.ts.map +1 -1
- package/dist/cli/utils/log.js +23 -0
- package/dist/cli/utils/prompts.js +224 -0
- package/dist/cli/utils/spinner.js +270 -0
- package/dist/config.js +703 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +84 -40
- package/dist/logger.js +290 -0
- package/dist/typeschema/cache.d.ts +2 -2
- package/dist/typeschema/cache.d.ts.map +1 -1
- package/dist/typeschema/cache.js +285 -0
- package/dist/typeschema/core/binding.d.ts +1 -1
- package/dist/typeschema/core/binding.d.ts.map +1 -1
- package/dist/typeschema/core/binding.js +187 -0
- package/dist/typeschema/core/field-builder.d.ts +1 -1
- package/dist/typeschema/core/field-builder.d.ts.map +1 -1
- package/dist/typeschema/core/field-builder.js +259 -0
- package/dist/typeschema/core/identifier.js +117 -0
- package/dist/typeschema/core/nested-types.d.ts +1 -1
- package/dist/typeschema/core/nested-types.d.ts.map +1 -1
- package/dist/typeschema/core/nested-types.js +111 -0
- package/dist/typeschema/core/transformer.d.ts +2 -2
- package/dist/typeschema/core/transformer.d.ts.map +1 -1
- package/dist/typeschema/core/transformer.js +345 -0
- package/dist/typeschema/generator.d.ts +3 -3
- package/dist/typeschema/generator.d.ts.map +1 -1
- package/dist/typeschema/generator.js +352 -0
- package/dist/typeschema/index.d.ts +14 -14
- package/dist/typeschema/index.d.ts.map +1 -1
- package/dist/typeschema/index.js +92 -0
- package/dist/typeschema/parser.d.ts +2 -2
- package/dist/typeschema/parser.d.ts.map +1 -1
- package/dist/typeschema/parser.js +310 -0
- package/dist/typeschema/profile/processor.d.ts +1 -1
- package/dist/typeschema/profile/processor.d.ts.map +1 -1
- package/dist/typeschema/profile/processor.js +268 -0
- package/dist/typeschema/schema.js +456 -0
- package/dist/typeschema/type-schema.types.js +39 -0
- package/dist/typeschema/types.js +4 -0
- package/dist/typeschema/utils.d.ts +1 -1
- package/dist/typeschema/utils.d.ts.map +1 -1
- package/dist/typeschema/utils.js +13 -0
- package/dist/typeschema/value-set/processor.d.ts +1 -1
- package/dist/typeschema/value-set/processor.d.ts.map +1 -1
- package/dist/typeschema/value-set/processor.js +168 -0
- package/dist/utils/codegen-logger.js +204 -0
- package/dist/utils.js +42 -0
- package/package.json +15 -4
- package/dist/index-fgcebdva.js +0 -8515
package/dist/cli/utils/log.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI Utilities - Re-exports from main utils with spinner support
|
|
3
3
|
*/
|
|
4
|
-
import { createSpinner } from "./spinner";
|
|
5
|
-
export { type CodegenLogger, complete, configure, createLogger, debug, dim, error, header, info, type LogOptions, list, plain, progress, section, step, success, table, warn, } from "../../utils/codegen-logger";
|
|
4
|
+
import { createSpinner } from "./spinner.js";
|
|
5
|
+
export { type CodegenLogger, complete, configure, createLogger, debug, dim, error, header, info, type LogOptions, list, plain, progress, section, step, success, table, warn, } from "../../utils/codegen-logger.js";
|
|
6
6
|
export { createSpinner };
|
|
7
7
|
/**
|
|
8
8
|
* Run a task with a spinner
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../../src/cli/utils/log.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAG7C,OAAO,EACN,KAAK,aAAa,EAClB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,KAAK,EACL,GAAG,EACH,KAAK,EACL,MAAM,EACN,IAAI,EACJ,KAAK,UAAU,EACf,IAAI,EACJ,KAAK,EACL,QAAQ,EACR,OAAO,EACP,IAAI,EACJ,OAAO,EACP,KAAK,EACL,IAAI,GACJ,MAAM,+BAA+B,CAAC;AAGvC,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB;;GAEG;AACH,wBAAsB,WAAW,CAAC,CAAC,EAClC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EACnB,OAAO,EAAE,MAAM,EACf,cAAc,CAAC,EAAE,MAAM,GACrB,OAAO,CAAC,CAAC,CAAC,CAUZ"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Utilities - Re-exports from main utils with spinner support
|
|
3
|
+
*/
|
|
4
|
+
import { createSpinner } from "./spinner.js";
|
|
5
|
+
// Re-export all logger functions from the main utils
|
|
6
|
+
export { complete, configure, createLogger, debug, dim, error, header, info, list, plain, progress, section, step, success, table, warn, } from "../../utils/codegen-logger.js";
|
|
7
|
+
// Export CLI-specific utilities
|
|
8
|
+
export { createSpinner };
|
|
9
|
+
/**
|
|
10
|
+
* Run a task with a spinner
|
|
11
|
+
*/
|
|
12
|
+
export async function withSpinner(promise, message, successMessage) {
|
|
13
|
+
const spinner = createSpinner(message).start();
|
|
14
|
+
try {
|
|
15
|
+
const result = await promise;
|
|
16
|
+
spinner.succeed(successMessage || message);
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
spinner.fail(`Failed: ${message}`);
|
|
21
|
+
throw error;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Prompts Utility
|
|
3
|
+
*
|
|
4
|
+
* Interactive prompts for better CLI user experience
|
|
5
|
+
*/
|
|
6
|
+
import { checkbox, confirm, input, select } from "@inquirer/prompts";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
/**
|
|
9
|
+
* Prompt for project initialization
|
|
10
|
+
*/
|
|
11
|
+
export async function promptInitConfig() {
|
|
12
|
+
console.log(pc.bold(pc.blue("\n🚀 Initialize Atomic Codegen Project\n")));
|
|
13
|
+
const projectName = await input({
|
|
14
|
+
message: "Project name:",
|
|
15
|
+
default: "my-fhir-types",
|
|
16
|
+
validate: (value) => {
|
|
17
|
+
if (!value.trim())
|
|
18
|
+
return "Project name is required";
|
|
19
|
+
if (!/^[a-z0-9-_]+$/i.test(value)) {
|
|
20
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
21
|
+
}
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
const description = await input({
|
|
26
|
+
message: "Project description (optional):",
|
|
27
|
+
default: "",
|
|
28
|
+
});
|
|
29
|
+
const outputDir = await input({
|
|
30
|
+
message: "Output directory for generated code:",
|
|
31
|
+
default: "./generated",
|
|
32
|
+
});
|
|
33
|
+
const generators = await checkbox({
|
|
34
|
+
message: "Select generators to use:",
|
|
35
|
+
choices: [
|
|
36
|
+
{ name: "TypeScript", value: "typescript", checked: true },
|
|
37
|
+
{ name: "Python", value: "python" },
|
|
38
|
+
{ name: "REST Client", value: "rest-client" },
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
const packageManager = (await select({
|
|
42
|
+
message: "Package manager:",
|
|
43
|
+
choices: [
|
|
44
|
+
{ name: "Bun", value: "bun" },
|
|
45
|
+
{ name: "npm", value: "npm" },
|
|
46
|
+
{ name: "Yarn", value: "yarn" },
|
|
47
|
+
{ name: "pnpm", value: "pnpm" },
|
|
48
|
+
],
|
|
49
|
+
default: "bun",
|
|
50
|
+
}));
|
|
51
|
+
const typescript = await confirm({
|
|
52
|
+
message: "Use TypeScript for configuration?",
|
|
53
|
+
default: true,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
projectName,
|
|
57
|
+
description,
|
|
58
|
+
outputDir,
|
|
59
|
+
generators,
|
|
60
|
+
packageManager,
|
|
61
|
+
typescript,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Prompt for FHIR package selection
|
|
66
|
+
*/
|
|
67
|
+
export async function promptFHIRPackage() {
|
|
68
|
+
const packageId = await select({
|
|
69
|
+
message: "Select FHIR package:",
|
|
70
|
+
choices: [
|
|
71
|
+
{ name: "FHIR R4 Core", value: "hl7.fhir.r4.core" },
|
|
72
|
+
{ name: "FHIR R5 Core", value: "hl7.fhir.r5.core" },
|
|
73
|
+
{ name: "US Core", value: "hl7.fhir.us.core" },
|
|
74
|
+
{ name: "Custom package...", value: "custom" },
|
|
75
|
+
],
|
|
76
|
+
});
|
|
77
|
+
let finalPackageId = packageId;
|
|
78
|
+
let version;
|
|
79
|
+
if (packageId === "custom") {
|
|
80
|
+
finalPackageId = await input({
|
|
81
|
+
message: "Enter package ID (e.g., hl7.fhir.us.core):",
|
|
82
|
+
validate: (value) => {
|
|
83
|
+
if (!value.trim())
|
|
84
|
+
return "Package ID is required";
|
|
85
|
+
return true;
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
version = await input({
|
|
89
|
+
message: "Package version (optional):",
|
|
90
|
+
default: "",
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
const includeProfiles = await confirm({
|
|
94
|
+
message: "Include profiles in generation?",
|
|
95
|
+
default: false,
|
|
96
|
+
});
|
|
97
|
+
let profiles = [];
|
|
98
|
+
if (includeProfiles) {
|
|
99
|
+
const profileSelection = await select({
|
|
100
|
+
message: "Profile selection:",
|
|
101
|
+
choices: [
|
|
102
|
+
{ name: "All profiles", value: "all" },
|
|
103
|
+
{ name: "None", value: "none" },
|
|
104
|
+
],
|
|
105
|
+
default: "none",
|
|
106
|
+
});
|
|
107
|
+
if (profileSelection === "all") {
|
|
108
|
+
profiles = ["*"];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return {
|
|
112
|
+
packageId: finalPackageId,
|
|
113
|
+
version: version || undefined,
|
|
114
|
+
profiles,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Prompt for generator configuration
|
|
119
|
+
*/
|
|
120
|
+
export async function promptGeneratorConfig(generatorId) {
|
|
121
|
+
const config = {};
|
|
122
|
+
switch (generatorId) {
|
|
123
|
+
case "typescript":
|
|
124
|
+
config.moduleFormat = await select({
|
|
125
|
+
message: "Module format:",
|
|
126
|
+
choices: [
|
|
127
|
+
{ name: "ESM", value: "esm" },
|
|
128
|
+
{ name: "CommonJS", value: "cjs" },
|
|
129
|
+
{ name: "Both", value: "both" },
|
|
130
|
+
],
|
|
131
|
+
default: "esm",
|
|
132
|
+
});
|
|
133
|
+
config.strict = await confirm({
|
|
134
|
+
message: "Enable strict TypeScript checks?",
|
|
135
|
+
default: true,
|
|
136
|
+
});
|
|
137
|
+
config.generateIndex = await confirm({
|
|
138
|
+
message: "Generate index files?",
|
|
139
|
+
default: true,
|
|
140
|
+
});
|
|
141
|
+
break;
|
|
142
|
+
case "python":
|
|
143
|
+
config.style = await select({
|
|
144
|
+
message: "Python style:",
|
|
145
|
+
choices: [
|
|
146
|
+
{ name: "Dataclasses", value: "dataclass" },
|
|
147
|
+
{ name: "Pydantic", value: "pydantic" },
|
|
148
|
+
{ name: "Plain classes", value: "plain" },
|
|
149
|
+
],
|
|
150
|
+
default: "dataclass",
|
|
151
|
+
});
|
|
152
|
+
config.typeHints = await confirm({
|
|
153
|
+
message: "Include type hints?",
|
|
154
|
+
default: true,
|
|
155
|
+
});
|
|
156
|
+
break;
|
|
157
|
+
case "rest-client":
|
|
158
|
+
config.httpClient = await select({
|
|
159
|
+
message: "HTTP client library:",
|
|
160
|
+
choices: [
|
|
161
|
+
{ name: "Fetch (native)", value: "fetch" },
|
|
162
|
+
{ name: "Axios", value: "axios" },
|
|
163
|
+
{ name: "Node fetch", value: "node-fetch" },
|
|
164
|
+
],
|
|
165
|
+
default: "fetch",
|
|
166
|
+
});
|
|
167
|
+
config.authentication = await select({
|
|
168
|
+
message: "Authentication type:",
|
|
169
|
+
choices: [
|
|
170
|
+
{ name: "None", value: "none" },
|
|
171
|
+
{ name: "Bearer token", value: "bearer" },
|
|
172
|
+
{ name: "Basic auth", value: "basic" },
|
|
173
|
+
{ name: "OAuth2", value: "oauth2" },
|
|
174
|
+
],
|
|
175
|
+
default: "none",
|
|
176
|
+
});
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
return config;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Prompt for confirmation with custom message
|
|
183
|
+
*/
|
|
184
|
+
export async function promptConfirm(message, defaultValue = false) {
|
|
185
|
+
return await confirm({
|
|
186
|
+
message,
|
|
187
|
+
default: defaultValue,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Prompt for text input with validation
|
|
192
|
+
*/
|
|
193
|
+
export async function promptInput(message, options) {
|
|
194
|
+
return await input({
|
|
195
|
+
message,
|
|
196
|
+
default: options?.default,
|
|
197
|
+
validate: options?.validate,
|
|
198
|
+
transformer: options?.transform,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Show success message
|
|
203
|
+
*/
|
|
204
|
+
export function showSuccess(message) {
|
|
205
|
+
console.log(pc.green(`✅ ${message}`));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Show error message
|
|
209
|
+
*/
|
|
210
|
+
export function showError(message) {
|
|
211
|
+
console.log(pc.red(`❌ ${message}`));
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Show warning message
|
|
215
|
+
*/
|
|
216
|
+
export function showWarning(message) {
|
|
217
|
+
console.log(pc.yellow(`⚠️ ${message}`));
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Show info message
|
|
221
|
+
*/
|
|
222
|
+
export function showInfo(message) {
|
|
223
|
+
console.log(pc.blue(`ℹ️ ${message}`));
|
|
224
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Spinner and Progress Utilities
|
|
3
|
+
*
|
|
4
|
+
* Visual progress indicators for long-running operations
|
|
5
|
+
*/
|
|
6
|
+
import { performance } from "node:perf_hooks";
|
|
7
|
+
import ora from "ora";
|
|
8
|
+
import pc from "picocolors";
|
|
9
|
+
/**
|
|
10
|
+
* Task progress tracker
|
|
11
|
+
*/
|
|
12
|
+
export class ProgressTracker {
|
|
13
|
+
tasks = new Map();
|
|
14
|
+
currentSpinner = null;
|
|
15
|
+
/**
|
|
16
|
+
* Start a new task
|
|
17
|
+
*/
|
|
18
|
+
startTask(taskId, message) {
|
|
19
|
+
this.tasks.set(taskId, {
|
|
20
|
+
startTime: performance.now(),
|
|
21
|
+
status: "running",
|
|
22
|
+
});
|
|
23
|
+
if (this.currentSpinner) {
|
|
24
|
+
this.currentSpinner.stop();
|
|
25
|
+
}
|
|
26
|
+
this.currentSpinner = ora({
|
|
27
|
+
text: message,
|
|
28
|
+
spinner: "dots",
|
|
29
|
+
}).start();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Update task progress
|
|
33
|
+
*/
|
|
34
|
+
updateTask(taskId, message) {
|
|
35
|
+
const task = this.tasks.get(taskId);
|
|
36
|
+
if (!task || task.status !== "running")
|
|
37
|
+
return;
|
|
38
|
+
if (this.currentSpinner) {
|
|
39
|
+
this.currentSpinner.text = message;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Complete a task successfully
|
|
44
|
+
*/
|
|
45
|
+
completeTask(taskId, message) {
|
|
46
|
+
const task = this.tasks.get(taskId);
|
|
47
|
+
if (!task)
|
|
48
|
+
return;
|
|
49
|
+
const duration = Math.round(performance.now() - task.startTime);
|
|
50
|
+
task.status = "completed";
|
|
51
|
+
if (this.currentSpinner) {
|
|
52
|
+
const finalMessage = message || this.currentSpinner.text;
|
|
53
|
+
this.currentSpinner.succeed(`${finalMessage} ${pc.gray(`(${duration}ms)`)}`);
|
|
54
|
+
this.currentSpinner = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Fail a task
|
|
59
|
+
*/
|
|
60
|
+
failTask(taskId, error) {
|
|
61
|
+
const task = this.tasks.get(taskId);
|
|
62
|
+
if (!task)
|
|
63
|
+
return;
|
|
64
|
+
task.status = "failed";
|
|
65
|
+
if (this.currentSpinner) {
|
|
66
|
+
const errorMessage = error ? `: ${error}` : "";
|
|
67
|
+
this.currentSpinner.fail(this.currentSpinner.text + errorMessage);
|
|
68
|
+
this.currentSpinner = null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Stop all spinners
|
|
73
|
+
*/
|
|
74
|
+
stop() {
|
|
75
|
+
if (this.currentSpinner) {
|
|
76
|
+
this.currentSpinner.stop();
|
|
77
|
+
this.currentSpinner = null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Get task statistics
|
|
82
|
+
*/
|
|
83
|
+
getStats() {
|
|
84
|
+
let completed = 0;
|
|
85
|
+
let failed = 0;
|
|
86
|
+
let running = 0;
|
|
87
|
+
let pending = 0;
|
|
88
|
+
for (const task of this.tasks.values()) {
|
|
89
|
+
switch (task.status) {
|
|
90
|
+
case "completed":
|
|
91
|
+
completed++;
|
|
92
|
+
break;
|
|
93
|
+
case "failed":
|
|
94
|
+
failed++;
|
|
95
|
+
break;
|
|
96
|
+
case "running":
|
|
97
|
+
running++;
|
|
98
|
+
break;
|
|
99
|
+
case "pending":
|
|
100
|
+
pending++;
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
total: this.tasks.size,
|
|
106
|
+
completed,
|
|
107
|
+
failed,
|
|
108
|
+
running,
|
|
109
|
+
pending,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Simple spinner for single operations
|
|
115
|
+
*/
|
|
116
|
+
export class SimpleSpinner {
|
|
117
|
+
spinner;
|
|
118
|
+
constructor(message) {
|
|
119
|
+
this.spinner = ora({
|
|
120
|
+
text: message,
|
|
121
|
+
spinner: "dots",
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
start(message) {
|
|
125
|
+
if (message) {
|
|
126
|
+
this.spinner.text = message;
|
|
127
|
+
}
|
|
128
|
+
this.spinner.start();
|
|
129
|
+
return this;
|
|
130
|
+
}
|
|
131
|
+
update(message) {
|
|
132
|
+
this.spinner.text = message;
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
succeed(message) {
|
|
136
|
+
this.spinner.succeed(message);
|
|
137
|
+
}
|
|
138
|
+
fail(message) {
|
|
139
|
+
this.spinner.fail(message);
|
|
140
|
+
}
|
|
141
|
+
warn(message) {
|
|
142
|
+
this.spinner.warn(message);
|
|
143
|
+
}
|
|
144
|
+
info(message) {
|
|
145
|
+
this.spinner.info(message);
|
|
146
|
+
}
|
|
147
|
+
stop() {
|
|
148
|
+
this.spinner.stop();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Progress bar for batch operations
|
|
153
|
+
*/
|
|
154
|
+
export class ProgressBar {
|
|
155
|
+
total;
|
|
156
|
+
message;
|
|
157
|
+
current = 0;
|
|
158
|
+
barLength = 30;
|
|
159
|
+
startTime = performance.now();
|
|
160
|
+
constructor(total, message) {
|
|
161
|
+
this.total = total;
|
|
162
|
+
this.message = message;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Update progress
|
|
166
|
+
*/
|
|
167
|
+
update(current, additionalInfo) {
|
|
168
|
+
this.current = Math.min(current, this.total);
|
|
169
|
+
this.render(additionalInfo);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Increment progress by 1
|
|
173
|
+
*/
|
|
174
|
+
increment(additionalInfo) {
|
|
175
|
+
this.update(this.current + 1, additionalInfo);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Complete the progress bar
|
|
179
|
+
*/
|
|
180
|
+
complete(message) {
|
|
181
|
+
this.current = this.total;
|
|
182
|
+
this.render();
|
|
183
|
+
const duration = Math.round(performance.now() - this.startTime);
|
|
184
|
+
console.log(pc.green(`✅ ${message || this.message} ${pc.gray(`(${duration}ms)`)}`));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Render the progress bar
|
|
188
|
+
*/
|
|
189
|
+
render(additionalInfo) {
|
|
190
|
+
const percentage = Math.round((this.current / this.total) * 100);
|
|
191
|
+
const filled = Math.round((this.current / this.total) * this.barLength);
|
|
192
|
+
const empty = this.barLength - filled;
|
|
193
|
+
const bar = pc.green("█".repeat(filled)) + pc.gray("░".repeat(empty));
|
|
194
|
+
const progress = `${this.current}/${this.total}`;
|
|
195
|
+
const info = additionalInfo ? pc.gray(` ${additionalInfo}`) : "";
|
|
196
|
+
// Clear line and write progress
|
|
197
|
+
process.stdout.clearLine(0);
|
|
198
|
+
process.stdout.cursorTo(0);
|
|
199
|
+
process.stdout.write(`${this.message} ${bar} ${pc.cyan(progress)} ${pc.yellow(`${percentage}%`)}${info}`);
|
|
200
|
+
// Add newline when complete
|
|
201
|
+
if (this.current === this.total) {
|
|
202
|
+
process.stdout.write("\n");
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Create a simple spinner
|
|
208
|
+
*/
|
|
209
|
+
export function createSpinner(message) {
|
|
210
|
+
return new SimpleSpinner(message);
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Create a progress tracker for multiple tasks
|
|
214
|
+
*/
|
|
215
|
+
export function createProgressTracker() {
|
|
216
|
+
return new ProgressTracker();
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create a progress bar
|
|
220
|
+
*/
|
|
221
|
+
export function createProgressBar(total, message) {
|
|
222
|
+
return new ProgressBar(total, message);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Show a spinner for a promise
|
|
226
|
+
*/
|
|
227
|
+
export async function withSpinner(promise, options) {
|
|
228
|
+
const spinner = ora({
|
|
229
|
+
text: options.start,
|
|
230
|
+
spinner: "dots",
|
|
231
|
+
}).start();
|
|
232
|
+
try {
|
|
233
|
+
const result = await promise;
|
|
234
|
+
const successMessage = typeof options.success === "function"
|
|
235
|
+
? options.success(result)
|
|
236
|
+
: options.success || options.start;
|
|
237
|
+
spinner.succeed(successMessage);
|
|
238
|
+
return result;
|
|
239
|
+
}
|
|
240
|
+
catch (error) {
|
|
241
|
+
const failMessage = typeof options.fail === "function"
|
|
242
|
+
? options.fail(error)
|
|
243
|
+
: options.fail || `Failed: ${options.start}`;
|
|
244
|
+
spinner.fail(failMessage);
|
|
245
|
+
throw error;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Multi-step task execution with progress
|
|
250
|
+
*/
|
|
251
|
+
export async function executeSteps(steps) {
|
|
252
|
+
const results = [];
|
|
253
|
+
const progressBar = new ProgressBar(steps.length, "Executing tasks");
|
|
254
|
+
for (let i = 0; i < steps.length; i++) {
|
|
255
|
+
const step = steps[i];
|
|
256
|
+
progressBar.update(i, step?.name);
|
|
257
|
+
try {
|
|
258
|
+
const result = await step?.task();
|
|
259
|
+
if (result) {
|
|
260
|
+
results.push(result);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
progressBar.complete(`Failed at step: ${step?.name}`);
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
progressBar.complete("All tasks completed");
|
|
269
|
+
return results;
|
|
270
|
+
}
|