zard-cli 1.0.0-beta.9 → 1.1.0-alpha.0
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/README.md +60 -188
- package/commands/add/component-installer.d.ts +4 -1
- package/commands/add/component-installer.d.ts.map +1 -1
- package/commands/add/component-installer.js +33 -5
- package/commands/add/component-installer.js.map +1 -1
- package/commands/add/component-selector.d.ts +6 -0
- package/commands/add/component-selector.d.ts.map +1 -1
- package/commands/add/component-selector.js +9 -27
- package/commands/add/component-selector.js.map +1 -1
- package/commands/add/dark-mode-setup.d.ts +2 -0
- package/commands/add/dark-mode-setup.d.ts.map +1 -1
- package/commands/add/dark-mode-setup.js +5 -11
- package/commands/add/dark-mode-setup.js.map +1 -1
- package/commands/add/dependency-resolver.d.ts +1 -1
- package/commands/add/dependency-resolver.d.ts.map +1 -1
- package/commands/add/dependency-resolver.js +5 -6
- package/commands/add/dependency-resolver.js.map +1 -1
- package/commands/add/index.d.ts.map +1 -1
- package/commands/add/index.js +127 -85
- package/commands/add/index.js.map +1 -1
- package/commands/add/wizard.d.ts +31 -0
- package/commands/add/wizard.d.ts.map +1 -0
- package/commands/add/wizard.js +289 -0
- package/commands/add/wizard.js.map +1 -0
- package/commands/init/config-prompter.d.ts +59 -56
- package/commands/init/config-prompter.d.ts.map +1 -1
- package/commands/init/config-prompter.js +76 -74
- package/commands/init/config-prompter.js.map +1 -1
- package/commands/init/dependencies.d.ts +1 -8
- package/commands/init/dependencies.d.ts.map +1 -1
- package/commands/init/dependencies.js +36 -16
- package/commands/init/dependencies.js.map +1 -1
- package/commands/init/index.d.ts.map +1 -1
- package/commands/init/index.js +132 -86
- package/commands/init/index.js.map +1 -1
- package/commands/init/project-kind.d.ts +82 -0
- package/commands/init/project-kind.d.ts.map +1 -0
- package/commands/init/project-kind.js +166 -0
- package/commands/init/project-kind.js.map +1 -0
- package/commands/init/steps.d.ts +16 -0
- package/commands/init/steps.d.ts.map +1 -0
- package/commands/init/steps.js +151 -0
- package/commands/init/steps.js.map +1 -0
- package/commands/init/tailwind-setup.d.ts +9 -2
- package/commands/init/tailwind-setup.d.ts.map +1 -1
- package/commands/init/tailwind-setup.js +33 -9
- package/commands/init/tailwind-setup.js.map +1 -1
- package/commands/init/theme-loader.d.ts.map +1 -1
- package/commands/init/theme-loader.js +1 -3
- package/commands/init/theme-loader.js.map +1 -1
- package/commands/init/tsconfig-updater.d.ts +8 -1
- package/commands/init/tsconfig-updater.d.ts.map +1 -1
- package/commands/init/tsconfig-updater.js +30 -11
- package/commands/init/tsconfig-updater.js.map +1 -1
- package/commands/init/update-angular-config.d.ts.map +1 -1
- package/commands/init/update-angular-config.js +28 -47
- package/commands/init/update-angular-config.js.map +1 -1
- package/commands/init/vite-setup.d.ts +10 -0
- package/commands/init/vite-setup.d.ts.map +1 -0
- package/commands/init/vite-setup.js +60 -0
- package/commands/init/vite-setup.js.map +1 -0
- package/commands/init/wizard.d.ts +30 -0
- package/commands/init/wizard.d.ts.map +1 -0
- package/commands/init/wizard.js +560 -0
- package/commands/init/wizard.js.map +1 -0
- package/core/registry/registry-data.d.ts.map +1 -1
- package/core/registry/registry-data.js +359 -61
- package/core/registry/registry-data.js.map +1 -1
- package/core/themes/theme-definitions.d.ts +5 -5
- package/core/themes/theme-definitions.d.ts.map +1 -1
- package/core/themes/theme-definitions.js +15 -11
- package/core/themes/theme-definitions.js.map +1 -1
- package/index.js +40 -4
- package/index.js.map +1 -1
- package/package.json +58 -61
- package/ui/blocks.d.ts +70 -0
- package/ui/blocks.d.ts.map +1 -0
- package/ui/blocks.js +116 -0
- package/ui/blocks.js.map +1 -0
- package/ui/brand.d.ts +14 -0
- package/ui/brand.d.ts.map +1 -0
- package/ui/brand.js +35 -0
- package/ui/brand.js.map +1 -0
- package/ui/engine/animation/index.d.ts +39 -0
- package/ui/engine/animation/index.d.ts.map +1 -0
- package/ui/engine/animation/index.js +103 -0
- package/ui/engine/animation/index.js.map +1 -0
- package/ui/engine/ansi/index.d.ts +52 -0
- package/ui/engine/ansi/index.d.ts.map +1 -0
- package/ui/engine/ansi/index.js +117 -0
- package/ui/engine/ansi/index.js.map +1 -0
- package/ui/engine/components/index.d.ts +211 -0
- package/ui/engine/components/index.d.ts.map +1 -0
- package/ui/engine/components/index.js +109 -0
- package/ui/engine/components/index.js.map +1 -0
- package/ui/engine/cursor/index.d.ts +17 -0
- package/ui/engine/cursor/index.d.ts.map +1 -0
- package/ui/engine/cursor/index.js +41 -0
- package/ui/engine/cursor/index.js.map +1 -0
- package/ui/engine/diff/index.d.ts +27 -0
- package/ui/engine/diff/index.d.ts.map +1 -0
- package/ui/engine/diff/index.js +57 -0
- package/ui/engine/diff/index.js.map +1 -0
- package/ui/engine/events/index.d.ts +24 -0
- package/ui/engine/events/index.d.ts.map +1 -0
- package/ui/engine/events/index.js +60 -0
- package/ui/engine/events/index.js.map +1 -0
- package/ui/engine/focus/index.d.ts +25 -0
- package/ui/engine/focus/index.d.ts.map +1 -0
- package/ui/engine/focus/index.js +77 -0
- package/ui/engine/focus/index.js.map +1 -0
- package/ui/engine/frame/index.d.ts +48 -0
- package/ui/engine/frame/index.d.ts.map +1 -0
- package/ui/engine/frame/index.js +0 -0
- package/ui/engine/frame/index.js.map +1 -0
- package/ui/engine/index.d.ts +28 -0
- package/ui/engine/index.d.ts.map +1 -0
- package/ui/engine/index.js +28 -0
- package/ui/engine/index.js.map +1 -0
- package/ui/engine/input/index.d.ts +36 -0
- package/ui/engine/input/index.d.ts.map +1 -0
- package/ui/engine/input/index.js +224 -0
- package/ui/engine/input/index.js.map +1 -0
- package/ui/engine/layout/index.d.ts +42 -0
- package/ui/engine/layout/index.d.ts.map +1 -0
- package/ui/engine/layout/index.js +241 -0
- package/ui/engine/layout/index.js.map +1 -0
- package/ui/engine/renderer/index.d.ts +43 -0
- package/ui/engine/renderer/index.d.ts.map +1 -0
- package/ui/engine/renderer/index.js +619 -0
- package/ui/engine/renderer/index.js.map +1 -0
- package/ui/engine/scheduler/index.d.ts +22 -0
- package/ui/engine/scheduler/index.d.ts.map +1 -0
- package/ui/engine/scheduler/index.js +77 -0
- package/ui/engine/scheduler/index.js.map +1 -0
- package/ui/engine/screen/index.d.ts +39 -0
- package/ui/engine/screen/index.d.ts.map +1 -0
- package/ui/engine/screen/index.js +255 -0
- package/ui/engine/screen/index.js.map +1 -0
- package/ui/engine/terminal/index.d.ts +38 -0
- package/ui/engine/terminal/index.d.ts.map +1 -0
- package/ui/engine/terminal/index.js +104 -0
- package/ui/engine/terminal/index.js.map +1 -0
- package/ui/engine/testing/index.d.ts +27 -0
- package/ui/engine/testing/index.d.ts.map +1 -0
- package/ui/engine/testing/index.js +63 -0
- package/ui/engine/testing/index.js.map +1 -0
- package/ui/engine/theme/index.d.ts +27 -0
- package/ui/engine/theme/index.d.ts.map +1 -0
- package/ui/engine/theme/index.js +129 -0
- package/ui/engine/theme/index.js.map +1 -0
- package/ui/engine/utils/index.d.ts +12 -0
- package/ui/engine/utils/index.d.ts.map +1 -0
- package/ui/engine/utils/index.js +143 -0
- package/ui/engine/utils/index.js.map +1 -0
- package/ui/gate.d.ts +19 -0
- package/ui/gate.d.ts.map +1 -0
- package/ui/gate.js +36 -0
- package/ui/gate.js.map +1 -0
- package/ui/index.d.ts +18 -0
- package/ui/index.d.ts.map +1 -0
- package/ui/index.js +18 -0
- package/ui/index.js.map +1 -0
- package/ui/log-sink.d.ts +24 -0
- package/ui/log-sink.d.ts.map +1 -0
- package/ui/log-sink.js +35 -0
- package/ui/log-sink.js.map +1 -0
- package/ui/output.d.ts +14 -0
- package/ui/output.d.ts.map +1 -0
- package/ui/output.js +28 -0
- package/ui/output.js.map +1 -0
- package/ui/report.d.ts +30 -0
- package/ui/report.d.ts.map +1 -0
- package/ui/report.js +45 -0
- package/ui/report.js.map +1 -0
- package/ui/runner.d.ts +57 -0
- package/ui/runner.d.ts.map +1 -0
- package/ui/runner.js +119 -0
- package/ui/runner.js.map +1 -0
- package/ui/style.d.ts +24 -0
- package/ui/style.d.ts.map +1 -0
- package/ui/style.js +44 -0
- package/ui/style.js.map +1 -0
- package/ui/testing/fake-tty.d.ts +26 -0
- package/ui/testing/fake-tty.d.ts.map +1 -0
- package/ui/testing/fake-tty.js +61 -0
- package/ui/testing/fake-tty.js.map +1 -0
- package/ui/text-input.d.ts +30 -0
- package/ui/text-input.d.ts.map +1 -0
- package/ui/text-input.js +87 -0
- package/ui/text-input.js.map +1 -0
- package/ui/theme.d.ts +10 -0
- package/ui/theme.d.ts.map +1 -0
- package/ui/theme.js +20 -0
- package/ui/theme.js.map +1 -0
- package/utils/config.d.ts +48 -69
- package/utils/config.d.ts.map +1 -1
- package/utils/config.js +43 -7
- package/utils/config.js.map +1 -1
- package/utils/errors.d.ts +16 -0
- package/utils/errors.d.ts.map +1 -0
- package/utils/errors.js +31 -0
- package/utils/errors.js.map +1 -0
- package/utils/get-package-info.js +4 -4
- package/utils/get-package-info.js.map +1 -1
- package/utils/get-project-info.d.ts +30 -0
- package/utils/get-project-info.d.ts.map +1 -1
- package/utils/get-project-info.js +195 -6
- package/utils/get-project-info.js.map +1 -1
- package/utils/http-client.d.ts +8 -0
- package/utils/http-client.d.ts.map +1 -0
- package/utils/http-client.js +68 -0
- package/utils/http-client.js.map +1 -0
- package/utils/logger.d.ts +16 -1
- package/utils/logger.d.ts.map +1 -1
- package/utils/logger.js +104 -12
- package/utils/logger.js.map +1 -1
- package/utils/package-manager.d.ts +44 -1
- package/utils/package-manager.d.ts.map +1 -1
- package/utils/package-manager.js +210 -14
- package/utils/package-manager.js.map +1 -1
- package/utils/registry.d.ts +14 -2
- package/utils/registry.d.ts.map +1 -1
- package/utils/registry.js +52 -24
- package/utils/registry.js.map +1 -1
- package/utils/source-file.d.ts +40 -0
- package/utils/source-file.d.ts.map +1 -0
- package/utils/source-file.js +104 -0
- package/utils/source-file.js.map +1 -0
- package/utils/theme-selector.d.ts +1 -1
- package/utils/theme-selector.d.ts.map +1 -1
- package/utils/theme-selector.js +6 -6
- package/utils/theme-selector.js.map +1 -1
- package/utils/fetch-component.d.ts +0 -3
- package/utils/fetch-component.d.ts.map +0 -1
- package/utils/fetch-component.js +0 -75
- package/utils/fetch-component.js.map +0 -1
package/commands/add/index.js
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
import { installComponent } from '../../commands/add/component-installer.js';
|
|
1
|
+
import { installComponent, validateTargetPath } from '../../commands/add/component-installer.js';
|
|
2
2
|
import { selectComponents } from '../../commands/add/component-selector.js';
|
|
3
3
|
import { updateProvideZardWithDarkMode } from '../../commands/add/dark-mode-setup.js';
|
|
4
|
-
import {
|
|
4
|
+
import { getAllComponentNames, getTargetDir, resolveDependencies, } from '../../commands/add/dependency-resolver.js';
|
|
5
|
+
import { runAddWizard } from '../../commands/add/wizard.js';
|
|
6
|
+
import { indexHtmlFor } from '../../commands/init/project-kind.js';
|
|
5
7
|
import { injectThemeScript } from '../../commands/init/theme-loader.js';
|
|
8
|
+
import { isInteractive, printReport, WizardCancelledError } from '../../ui/index.js';
|
|
6
9
|
import { getConfig, resolveConfigPaths } from '../../utils/config.js';
|
|
10
|
+
import { CliError } from '../../utils/errors.js';
|
|
7
11
|
import { getProjectInfo } from '../../utils/get-project-info.js';
|
|
8
12
|
import { logger, spinner } from '../../utils/logger.js';
|
|
9
|
-
import {
|
|
10
|
-
import chalk from 'chalk';
|
|
13
|
+
import { filterInstalledPackages, installPackagesWithRetry } from '../../utils/package-manager.js';
|
|
11
14
|
import { Command } from 'commander';
|
|
12
15
|
import { existsSync } from 'node:fs';
|
|
13
16
|
import * as path from 'node:path';
|
|
14
|
-
import prompts from 'prompts';
|
|
15
17
|
export const add = new Command()
|
|
16
18
|
.name('add')
|
|
17
19
|
.description('add a component to your project')
|
|
@@ -24,114 +26,154 @@ export const add = new Command()
|
|
|
24
26
|
.action(async (components, options) => {
|
|
25
27
|
const cwd = path.resolve(options.cwd);
|
|
26
28
|
validateWorkingDirectory(cwd);
|
|
29
|
+
if (options.path) {
|
|
30
|
+
validateTargetPath(path.resolve(cwd, options.path), cwd);
|
|
31
|
+
}
|
|
27
32
|
const config = await loadConfiguration(cwd);
|
|
28
|
-
await validateProject(cwd);
|
|
33
|
+
const projectInfo = await validateProject(cwd);
|
|
29
34
|
const resolvedConfig = await resolveConfigPaths(cwd, config);
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
const preselected = await selectComponents(components, options.all);
|
|
36
|
+
warnOnPrereleaseAngular(projectInfo.angularVersionRaw);
|
|
37
|
+
const actions = {
|
|
38
|
+
loadNames: () => getAllComponentNames(),
|
|
39
|
+
resolve: async (names) => {
|
|
40
|
+
const { componentsToInstall, dependenciesToInstall } = await resolveDependencies(names, resolvedConfig, cwd, options);
|
|
41
|
+
return {
|
|
42
|
+
components: componentsToInstall,
|
|
43
|
+
dependencies: resolveCompatibleVersions(dependenciesToInstall, projectInfo.angularVersion),
|
|
44
|
+
};
|
|
45
|
+
},
|
|
46
|
+
installDependencies: (packages) => installDependencies(packages, cwd, config.packageManager),
|
|
47
|
+
installComponent: (component) => installComponent(component.name, getTargetDir(component, resolvedConfig, cwd, options.path), resolvedConfig, {
|
|
48
|
+
customPath: Boolean(options.path),
|
|
49
|
+
}),
|
|
50
|
+
setupDarkMode: async (indexHtml) => {
|
|
51
|
+
await injectThemeScript(cwd, indexHtml);
|
|
52
|
+
await updateProvideZardWithDarkMode(cwd, resolvedConfig);
|
|
53
|
+
},
|
|
54
|
+
defaultIndexHtml: indexHtmlFor(config.projectType, config.baseUrl),
|
|
55
|
+
};
|
|
56
|
+
if (!isInteractive()) {
|
|
57
|
+
await runHeadless(preselected, options, actions);
|
|
36
58
|
return;
|
|
37
59
|
}
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
60
|
+
try {
|
|
61
|
+
const { installed, logs } = await runAddWizard({
|
|
62
|
+
preselected,
|
|
63
|
+
skipConfirmation: options.yes,
|
|
64
|
+
...actions,
|
|
65
|
+
});
|
|
66
|
+
reportSuccess(installed, logs);
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
if (error instanceof WizardCancelledError) {
|
|
70
|
+
printReport({ status: 'cancelled', headline: error.message, notes: ['No files were written.'] });
|
|
41
71
|
process.exit(0);
|
|
42
72
|
}
|
|
73
|
+
throw error;
|
|
43
74
|
}
|
|
44
|
-
await installDependencies(dependenciesToInstall, cwd, config.packageManager);
|
|
45
|
-
await installComponents(componentsToInstall, cwd, resolvedConfig, options);
|
|
46
|
-
const isDarkModeBeingInstalled = componentsToInstall.some(c => c.name === 'dark-mode');
|
|
47
|
-
if (isDarkModeBeingInstalled) {
|
|
48
|
-
await setupDarkMode(cwd, resolvedConfig);
|
|
49
|
-
}
|
|
50
|
-
logger.break();
|
|
51
|
-
logger.success('Done!');
|
|
52
75
|
});
|
|
76
|
+
/**
|
|
77
|
+
* Caminho sem UI — CI, pipes e terminais não interativos.
|
|
78
|
+
*
|
|
79
|
+
* Sem alguém para escolher na lista, os componentes precisam vir por argumento
|
|
80
|
+
* ou via `--all`; a confirmação é dispensada porque não há como respondê-la.
|
|
81
|
+
*/
|
|
82
|
+
async function runHeadless(preselected, options, actions) {
|
|
83
|
+
if (!preselected.length) {
|
|
84
|
+
throw new CliError('No components specified. Pass the component names or --all when running without an interactive terminal.', 'NO_COMPONENTS');
|
|
85
|
+
}
|
|
86
|
+
const resolveSpinner = spinner('Resolving components...').start();
|
|
87
|
+
const { components, dependencies } = await actions.resolve(preselected);
|
|
88
|
+
resolveSpinner.stop();
|
|
89
|
+
if (components.length === 0) {
|
|
90
|
+
logger.info('All components already installed.');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (dependencies.length) {
|
|
94
|
+
const depsSpinner = spinner('Installing dependencies...').start();
|
|
95
|
+
await actions.installDependencies(dependencies);
|
|
96
|
+
depsSpinner.succeed('Dependencies installed');
|
|
97
|
+
}
|
|
98
|
+
const installed = [];
|
|
99
|
+
const failed = [];
|
|
100
|
+
for (const component of components) {
|
|
101
|
+
const componentSpinner = spinner(`Installing ${component.name}...`).start();
|
|
102
|
+
try {
|
|
103
|
+
await actions.installComponent(component);
|
|
104
|
+
installed.push(component.name);
|
|
105
|
+
componentSpinner.succeed(component.name);
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
failed.push(component.name);
|
|
109
|
+
componentSpinner.fail(component.name);
|
|
110
|
+
logger.debug(`Failed to install ${component.name}: ${error instanceof Error ? error.message : error}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (components.some(component => component.name === 'dark-mode')) {
|
|
114
|
+
logger.warn('Dark mode needs an index.html path; run `zard-cli add dark-mode` interactively to configure it.');
|
|
115
|
+
}
|
|
116
|
+
if (failed.length) {
|
|
117
|
+
throw new CliError(`Failed to install: ${failed.join(', ')}`, 'INSTALL_FAILED');
|
|
118
|
+
}
|
|
119
|
+
reportSuccess(installed, []);
|
|
120
|
+
}
|
|
121
|
+
function reportSuccess(installed, logs) {
|
|
122
|
+
if (!installed.length) {
|
|
123
|
+
printReport({ status: 'success', headline: 'All components are already installed.', logs });
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
printReport({
|
|
127
|
+
status: 'success',
|
|
128
|
+
headline: `Installed ${installed.length} component${installed.length > 1 ? 's' : ''}.`,
|
|
129
|
+
items: [...installed],
|
|
130
|
+
logs,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
53
133
|
function validateWorkingDirectory(cwd) {
|
|
54
134
|
if (!existsSync(cwd)) {
|
|
55
|
-
|
|
56
|
-
process.exit(1);
|
|
135
|
+
throw new CliError(`The path ${cwd} does not exist. Please try again.`, 'INVALID_CWD');
|
|
57
136
|
}
|
|
58
137
|
}
|
|
59
138
|
async function loadConfiguration(cwd) {
|
|
60
139
|
const config = await getConfig(cwd);
|
|
61
140
|
if (!config) {
|
|
62
|
-
|
|
63
|
-
process.exit(1);
|
|
141
|
+
throw new CliError('Configuration not found. Please run `zard-cli init` first.', 'CONFIG_NOT_FOUND');
|
|
64
142
|
}
|
|
65
143
|
return config;
|
|
66
144
|
}
|
|
67
145
|
async function validateProject(cwd) {
|
|
68
146
|
const projectInfo = await getProjectInfo(cwd);
|
|
69
147
|
if (projectInfo.framework !== 'angular') {
|
|
70
|
-
|
|
71
|
-
process.exit(1);
|
|
148
|
+
throw new CliError('This project does not appear to be an Angular project.', 'NOT_ANGULAR');
|
|
72
149
|
}
|
|
73
150
|
return projectInfo;
|
|
74
151
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
name: 'proceed',
|
|
79
|
-
message: `Ready to install ${componentsCount} component(s) and ${dependenciesCount} dependencies. Proceed?`,
|
|
80
|
-
initial: true,
|
|
81
|
-
});
|
|
82
|
-
return proceed;
|
|
83
|
-
}
|
|
84
|
-
async function installDependencies(dependenciesToInstall, cwd, packageManager) {
|
|
85
|
-
if (dependenciesToInstall.size === 0)
|
|
86
|
-
return;
|
|
87
|
-
const depsSpinner = spinner('Installing dependencies...').start();
|
|
88
|
-
await installPackages(Array.from(dependenciesToInstall), cwd, packageManager, false);
|
|
89
|
-
depsSpinner.succeed('Dependencies installed');
|
|
90
|
-
}
|
|
91
|
-
async function installComponents(componentsToInstall, cwd, resolvedConfig, options) {
|
|
92
|
-
const installSpinner = spinner('Installing components...').start();
|
|
93
|
-
const installed = [];
|
|
94
|
-
const failed = [];
|
|
95
|
-
for (const component of componentsToInstall) {
|
|
96
|
-
try {
|
|
97
|
-
installSpinner.text = `Installing ${component.name}...`;
|
|
98
|
-
const targetDir = getTargetDir(component, resolvedConfig, cwd, options.path);
|
|
99
|
-
await installComponent(component.name, targetDir, resolvedConfig);
|
|
100
|
-
installed.push(component.name);
|
|
101
|
-
}
|
|
102
|
-
catch (error) {
|
|
103
|
-
failed.push(component.name);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (failed.length > 0) {
|
|
107
|
-
installSpinner.fail(`Failed to install: ${failed.join(', ')}`);
|
|
108
|
-
}
|
|
109
|
-
else {
|
|
110
|
-
installSpinner.succeed(`Installed ${installed.length} component${installed.length > 1 ? 's' : ''}`);
|
|
152
|
+
function warnOnPrereleaseAngular(angularVersionRaw) {
|
|
153
|
+
if (angularVersionRaw && /-(rc|next|canary)/.test(angularVersionRaw)) {
|
|
154
|
+
logger.warn(`You are using a pre-release version of Angular (${angularVersionRaw}). Some dependencies may have compatibility issues.`);
|
|
111
155
|
}
|
|
112
156
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
157
|
+
const ANGULAR_VERSION_PACKAGES = ['embla-carousel-angular'];
|
|
158
|
+
function resolveCompatibleVersions(dependencies, angularVersion) {
|
|
159
|
+
const angularMajor = angularVersion ? parseInt(angularVersion.split('.')[0], 10) : null;
|
|
160
|
+
return Array.from(dependencies).map(dep => {
|
|
161
|
+
if (angularMajor && ANGULAR_VERSION_PACKAGES.includes(dep)) {
|
|
162
|
+
return `${dep}@^${angularMajor}.0.0`;
|
|
163
|
+
}
|
|
164
|
+
return dep;
|
|
121
165
|
});
|
|
122
|
-
|
|
123
|
-
|
|
166
|
+
}
|
|
167
|
+
async function installDependencies(packages, cwd, packageManager) {
|
|
168
|
+
if (packages.length === 0)
|
|
169
|
+
return;
|
|
170
|
+
// Um projeto já inicializado costuma ter todas elas: sem o filtro, cada `add`
|
|
171
|
+
// pagaria uma revalidação completa da árvore para não instalar nada.
|
|
172
|
+
const missing = await filterInstalledPackages(packages, cwd);
|
|
173
|
+
if (missing.length === 0) {
|
|
174
|
+
logger.debug(`Dependencies already installed: ${packages.join(', ')}`);
|
|
124
175
|
return;
|
|
125
176
|
}
|
|
126
|
-
|
|
127
|
-
try {
|
|
128
|
-
await injectThemeScript(cwd, indexFile);
|
|
129
|
-
await updateProvideZardWithDarkMode(cwd, resolvedConfig);
|
|
130
|
-
darkModeSpinner.succeed('Dark mode configured');
|
|
131
|
-
}
|
|
132
|
-
catch (error) {
|
|
133
|
-
darkModeSpinner.fail('Failed to configure dark mode');
|
|
134
|
-
logger.error(error);
|
|
135
|
-
}
|
|
177
|
+
await installPackagesWithRetry(missing, cwd, packageManager, false);
|
|
136
178
|
}
|
|
137
179
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/add/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/add/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type ComponentMeta } from '../../commands/add/dependency-resolver.js';
|
|
2
|
+
import { type LogRecord } from '../../ui/index.js';
|
|
3
|
+
export interface AddWizardOptions {
|
|
4
|
+
/** Componentes já informados na linha de comando — pulam a seleção. */
|
|
5
|
+
readonly preselected: readonly string[];
|
|
6
|
+
/** Carrega os nomes disponíveis; só é chamado quando há seleção a fazer. */
|
|
7
|
+
loadNames(): Promise<string[]>;
|
|
8
|
+
resolve(names: string[]): Promise<{
|
|
9
|
+
components: ComponentMeta[];
|
|
10
|
+
dependencies: string[];
|
|
11
|
+
}>;
|
|
12
|
+
/** Pula a confirmação (`--yes`). */
|
|
13
|
+
readonly skipConfirmation: boolean;
|
|
14
|
+
installDependencies(packages: string[]): Promise<void>;
|
|
15
|
+
installComponent(component: ComponentMeta): Promise<void>;
|
|
16
|
+
/** Só é chamado quando dark-mode entra na instalação. */
|
|
17
|
+
setupDarkMode(indexHtml: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Onde o index.html deve estar, segundo o tipo de projeto configurado.
|
|
20
|
+
*
|
|
21
|
+
* Um `src/index.html` fixo só existe no app Angular único: num workspace ele
|
|
22
|
+
* está sob `apps/<app>/`, e no Analog é a página de entrada do Vite, na raiz.
|
|
23
|
+
*/
|
|
24
|
+
readonly defaultIndexHtml: string;
|
|
25
|
+
}
|
|
26
|
+
export interface AddWizardResult {
|
|
27
|
+
readonly installed: readonly string[];
|
|
28
|
+
readonly logs: readonly LogRecord[];
|
|
29
|
+
}
|
|
30
|
+
export declare function runAddWizard(options: AddWizardOptions): Promise<AddWizardResult>;
|
|
31
|
+
//# sourceMappingURL=wizard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wizard.d.ts","sourceRoot":"","sources":["../../../src/commands/add/wizard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAuBL,KAAK,SAAS,EAKf,MAAM,kBAAkB,CAAC;AA6B1B,MAAM,WAAW,gBAAgB;IAC/B,uEAAuE;IACvE,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,4EAA4E;IAC5E,SAAS,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,aAAa,EAAE,CAAC;QAAC,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC3F,oCAAoC;IACpC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;IACnC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvD,gBAAgB,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,yDAAyD;IACzD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD;;;;;OAKG;IACH,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,QAAQ,CAAC,IAAI,EAAE,SAAS,SAAS,EAAE,CAAC;CACrC;AAID,wBAAsB,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,eAAe,CAAC,CAwKtF"}
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
import { answeredLine, checkList, commandHeader, confirmField, controls, createGate, editInput, hint, page, progress, question, resultPanel, runWizard, screen, spacer, startInput, taskHeader, taskList, text, textField, } from '../../ui/index.js';
|
|
2
|
+
const DARK_MODE = 'dark-mode';
|
|
3
|
+
export async function runAddWizard(options) {
|
|
4
|
+
const state = {
|
|
5
|
+
phase: options.preselected.length ? 'resolving' : 'selecting',
|
|
6
|
+
names: [],
|
|
7
|
+
filter: '',
|
|
8
|
+
visible: [],
|
|
9
|
+
cursor: 0,
|
|
10
|
+
selected: new Set(),
|
|
11
|
+
componentCount: 0,
|
|
12
|
+
dependencyCount: 0,
|
|
13
|
+
confirmValue: true,
|
|
14
|
+
tasks: [],
|
|
15
|
+
tasksDone: 0,
|
|
16
|
+
taskStartedAt: 0,
|
|
17
|
+
indexHtml: startInput(options.defaultIndexHtml),
|
|
18
|
+
transcript: [],
|
|
19
|
+
failure: null,
|
|
20
|
+
installed: [],
|
|
21
|
+
};
|
|
22
|
+
const selection = createGate();
|
|
23
|
+
const confirmation = createGate();
|
|
24
|
+
const darkMode = createGate();
|
|
25
|
+
const finish = createGate();
|
|
26
|
+
const applyFilter = () => {
|
|
27
|
+
const term = state.filter.trim().toLowerCase();
|
|
28
|
+
state.visible = state.names
|
|
29
|
+
.map((_, index) => index)
|
|
30
|
+
.filter(index => !term || state.names[index].toLowerCase().includes(term));
|
|
31
|
+
state.cursor = Math.min(state.cursor, Math.max(0, state.visible.length - 1));
|
|
32
|
+
};
|
|
33
|
+
const onKey = (event, ctx) => {
|
|
34
|
+
if (state.phase === 'selecting') {
|
|
35
|
+
handleSelectionKey(event, state, applyFilter, selection);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (state.phase === 'confirming') {
|
|
39
|
+
if (event.key === 'left' || event.key === 'right')
|
|
40
|
+
state.confirmValue = !state.confirmValue;
|
|
41
|
+
else if (event.key === 'y' || event.key === 'Y')
|
|
42
|
+
confirmation.settle(true);
|
|
43
|
+
else if (event.key === 'n' || event.key === 'N' || event.key === 'escape')
|
|
44
|
+
confirmation.settle(false);
|
|
45
|
+
else if (event.key === 'enter')
|
|
46
|
+
confirmation.settle(state.confirmValue);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (state.phase === 'darkMode') {
|
|
50
|
+
if (event.key === 'enter') {
|
|
51
|
+
darkMode.settle(state.indexHtml.value.trim() || options.defaultIndexHtml);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (event.key === 'escape') {
|
|
55
|
+
darkMode.settle(null);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const edited = editInput(state.indexHtml, event);
|
|
59
|
+
if (edited)
|
|
60
|
+
state.indexHtml = edited;
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (state.phase === 'done' || state.phase === 'failed') {
|
|
64
|
+
if (event.key === 'enter')
|
|
65
|
+
finish.settle(undefined);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
void ctx;
|
|
69
|
+
};
|
|
70
|
+
const run = async (ctx) => {
|
|
71
|
+
let names;
|
|
72
|
+
if (options.preselected.length) {
|
|
73
|
+
names = [...options.preselected];
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
state.names = await options.loadNames();
|
|
77
|
+
applyFilter();
|
|
78
|
+
ctx.refresh();
|
|
79
|
+
names = await selection.wait();
|
|
80
|
+
if (!names.length) {
|
|
81
|
+
ctx.cancel('No components selected.');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
state.transcript.push(['components', names.join(', ')]);
|
|
85
|
+
}
|
|
86
|
+
state.phase = 'resolving';
|
|
87
|
+
ctx.refresh();
|
|
88
|
+
const { components, dependencies } = await options.resolve(names);
|
|
89
|
+
if (components.length === 0) {
|
|
90
|
+
state.phase = 'done';
|
|
91
|
+
state.installed = [];
|
|
92
|
+
ctx.refresh();
|
|
93
|
+
await finish.wait();
|
|
94
|
+
ctx.done([]);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
state.componentCount = components.length;
|
|
98
|
+
state.dependencyCount = dependencies.length;
|
|
99
|
+
if (!options.skipConfirmation) {
|
|
100
|
+
state.phase = 'confirming';
|
|
101
|
+
ctx.refresh();
|
|
102
|
+
if (!(await confirmation.wait())) {
|
|
103
|
+
ctx.cancel();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
state.transcript.push(['install', `${components.length} component(s), ${dependencies.length} dependencies`]);
|
|
107
|
+
}
|
|
108
|
+
state.phase = 'installing';
|
|
109
|
+
state.tasks = [
|
|
110
|
+
...(dependencies.length ? [{ label: 'dependencies', note: dependencies.join(', ') }] : []),
|
|
111
|
+
...components.map(component => ({ label: component.name, note: 'component source' })),
|
|
112
|
+
];
|
|
113
|
+
state.tasksDone = 0;
|
|
114
|
+
state.taskStartedAt = Date.now();
|
|
115
|
+
ctx.refresh();
|
|
116
|
+
if (dependencies.length) {
|
|
117
|
+
await options.installDependencies(dependencies);
|
|
118
|
+
state.tasksDone++;
|
|
119
|
+
state.taskStartedAt = Date.now();
|
|
120
|
+
ctx.refresh();
|
|
121
|
+
}
|
|
122
|
+
const failed = [];
|
|
123
|
+
for (const component of components) {
|
|
124
|
+
try {
|
|
125
|
+
await options.installComponent(component);
|
|
126
|
+
state.installed.push(component.name);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
failed.push(component.name);
|
|
130
|
+
state.failure = `${component.name}: ${error instanceof Error ? error.message : String(error)}`;
|
|
131
|
+
}
|
|
132
|
+
state.tasksDone++;
|
|
133
|
+
state.taskStartedAt = Date.now();
|
|
134
|
+
ctx.refresh();
|
|
135
|
+
}
|
|
136
|
+
if (components.some(component => component.name === DARK_MODE)) {
|
|
137
|
+
state.phase = 'darkMode';
|
|
138
|
+
ctx.refresh();
|
|
139
|
+
const indexHtml = await darkMode.wait();
|
|
140
|
+
if (indexHtml) {
|
|
141
|
+
state.transcript.push(['index.html', indexHtml]);
|
|
142
|
+
await options.setupDarkMode(indexHtml);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
state.phase = failed.length ? 'failed' : 'done';
|
|
146
|
+
ctx.refresh();
|
|
147
|
+
await finish.wait();
|
|
148
|
+
ctx.done(state.installed);
|
|
149
|
+
};
|
|
150
|
+
const result = await runWizard({
|
|
151
|
+
view: () => buildView(state),
|
|
152
|
+
onKey,
|
|
153
|
+
run,
|
|
154
|
+
});
|
|
155
|
+
return { installed: result.value, logs: result.logs };
|
|
156
|
+
}
|
|
157
|
+
function handleSelectionKey(event, state, applyFilter, selection) {
|
|
158
|
+
const total = state.visible.length;
|
|
159
|
+
if (event.key === 'up') {
|
|
160
|
+
state.cursor = total ? (state.cursor - 1 + total) % total : 0;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (event.key === 'down') {
|
|
164
|
+
state.cursor = total ? (state.cursor + 1) % total : 0;
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (event.key === ' ' || event.key === 'space') {
|
|
168
|
+
const index = state.visible[state.cursor];
|
|
169
|
+
if (index !== undefined) {
|
|
170
|
+
if (state.selected.has(index))
|
|
171
|
+
state.selected.delete(index);
|
|
172
|
+
else
|
|
173
|
+
state.selected.add(index);
|
|
174
|
+
}
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (event.ctrl && event.key === 'a') {
|
|
178
|
+
// Alterna tudo que está visível, respeitando o filtro corrente.
|
|
179
|
+
const allSelected = state.visible.every(index => state.selected.has(index));
|
|
180
|
+
for (const index of state.visible) {
|
|
181
|
+
if (allSelected)
|
|
182
|
+
state.selected.delete(index);
|
|
183
|
+
else
|
|
184
|
+
state.selected.add(index);
|
|
185
|
+
}
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (event.key === 'enter') {
|
|
189
|
+
selection.settle([...state.selected].sort((a, b) => a - b).map(index => state.names[index]));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
if (event.key === 'backspace') {
|
|
193
|
+
state.filter = [...state.filter].slice(0, -1).join('');
|
|
194
|
+
applyFilter();
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
if (event.key.length === 1 && !event.ctrl && !event.alt) {
|
|
198
|
+
state.filter += event.key;
|
|
199
|
+
applyFilter();
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Janela deslizante da lista: mantém o cursor sempre visível. */
|
|
203
|
+
const VISIBLE_ROWS = 10;
|
|
204
|
+
function windowOf(state) {
|
|
205
|
+
if (state.visible.length <= VISIBLE_ROWS)
|
|
206
|
+
return { slice: state.visible, offset: 0 };
|
|
207
|
+
const half = Math.floor(VISIBLE_ROWS / 2);
|
|
208
|
+
const max = state.visible.length - VISIBLE_ROWS;
|
|
209
|
+
const offset = Math.max(0, Math.min(state.cursor - half, max));
|
|
210
|
+
return { slice: state.visible.slice(offset, offset + VISIBLE_ROWS), offset };
|
|
211
|
+
}
|
|
212
|
+
function buildView(state) {
|
|
213
|
+
const body = [commandHeader('add', 'Add components to your project'), text('')];
|
|
214
|
+
for (const [label, value] of state.transcript)
|
|
215
|
+
body.push(answeredLine(label, value));
|
|
216
|
+
if (state.transcript.length)
|
|
217
|
+
body.push(text(''));
|
|
218
|
+
if (state.phase === 'selecting') {
|
|
219
|
+
const { slice, offset } = windowOf(state);
|
|
220
|
+
const choices = slice.map(index => ({ label: state.names[index] }));
|
|
221
|
+
const localCursor = state.cursor - offset;
|
|
222
|
+
const localSelected = new Set(slice.map((index, position) => (state.selected.has(index) ? position : -1)).filter(position => position >= 0));
|
|
223
|
+
body.push(question('Which components would you like to add?'));
|
|
224
|
+
body.push(textField(state.filter));
|
|
225
|
+
if (choices.length) {
|
|
226
|
+
body.push(...checkList(choices, localCursor, localSelected));
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
body.push(hint('No component matches this filter.'));
|
|
230
|
+
}
|
|
231
|
+
body.push(text(''));
|
|
232
|
+
body.push(hint(`${state.selected.size} selected · ${state.visible.length} of ${state.names.length} shown`));
|
|
233
|
+
body.push(spacer());
|
|
234
|
+
body.push(controls([
|
|
235
|
+
['↑/↓', 'move'],
|
|
236
|
+
['space', 'select'],
|
|
237
|
+
['ctrl+a', 'toggle all'],
|
|
238
|
+
['enter', 'confirm'],
|
|
239
|
+
]));
|
|
240
|
+
}
|
|
241
|
+
else if (state.phase === 'resolving') {
|
|
242
|
+
body.push(taskHeader('Resolving components and dependencies…', false));
|
|
243
|
+
body.push(spacer());
|
|
244
|
+
}
|
|
245
|
+
else if (state.phase === 'confirming') {
|
|
246
|
+
body.push(question(`Ready to install ${state.componentCount} component(s) and ${state.dependencyCount} dependencies. Proceed?`));
|
|
247
|
+
body.push(confirmField(state.confirmValue));
|
|
248
|
+
body.push(hint('Existing files are kept unless you passed --overwrite.'));
|
|
249
|
+
body.push(spacer());
|
|
250
|
+
body.push(controls([
|
|
251
|
+
['y/n · ←/→', 'toggle'],
|
|
252
|
+
['enter', 'confirm'],
|
|
253
|
+
]));
|
|
254
|
+
}
|
|
255
|
+
else if (state.phase === 'darkMode') {
|
|
256
|
+
body.push(question('Where is your index.html file?'));
|
|
257
|
+
body.push(textField(state.indexHtml.value, state.indexHtml.caret));
|
|
258
|
+
body.push(hint('Dark mode injects a small script there to apply the theme before first paint.'));
|
|
259
|
+
body.push(spacer());
|
|
260
|
+
body.push(controls([
|
|
261
|
+
['enter', 'confirm'],
|
|
262
|
+
['esc', 'skip'],
|
|
263
|
+
]));
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
body.push(...installBlock(state));
|
|
267
|
+
body.push(spacer());
|
|
268
|
+
body.push(controls([['enter', state.phase === 'failed' ? 'exit' : 'finish']]));
|
|
269
|
+
}
|
|
270
|
+
return screen(page(...body));
|
|
271
|
+
}
|
|
272
|
+
function installBlock(state) {
|
|
273
|
+
const allDone = state.tasksDone >= state.tasks.length;
|
|
274
|
+
const nodes = [];
|
|
275
|
+
if (state.tasks.length) {
|
|
276
|
+
nodes.push(taskHeader(state.phase === 'failed' ? 'Finished with errors' : 'Installing…', allDone), text(''), ...taskList(state.tasks, state.tasksDone, state.phase === 'installing' ? Date.now() - state.taskStartedAt : undefined), text(''), progress(state.tasksDone, state.tasks.length), text(''));
|
|
277
|
+
}
|
|
278
|
+
if (state.phase === 'failed') {
|
|
279
|
+
nodes.push(resultPanel('danger', state.failure ?? 'Some components could not be installed.'));
|
|
280
|
+
}
|
|
281
|
+
else if (state.installed.length) {
|
|
282
|
+
nodes.push(resultPanel('success', `Installed ${state.installed.length} component${state.installed.length > 1 ? 's' : ''}.`));
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
nodes.push(resultPanel('success', 'All components are already installed.'));
|
|
286
|
+
}
|
|
287
|
+
return nodes;
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=wizard.js.map
|