generate-ui-cli 2.1.0 → 2.1.2
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 +1 -1
- package/dist/commands/angular.js +11 -9
- package/dist/commands/login.js +15 -2
- package/dist/generators/angular/feature.generator.js +35 -11
- package/dist/runtime/config.js +2 -2
- package/dist/telemetry.js +14 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -105,7 +105,7 @@ If your project uses custom routing, standalone components, or advanced layouts,
|
|
|
105
105
|
|
|
106
106
|
Defaults:
|
|
107
107
|
- `--schemas` defaults to the last generated path (stored in `~/.generateui/config.json`), otherwise `./src/generate-ui` (or `./frontend/src/generate-ui` / `./generate-ui`)
|
|
108
|
-
- `--features` defaults to `./src/app/features` when
|
|
108
|
+
- `--features` defaults to `./src/app/features` when `./src/app` exists; otherwise it errors and asks for `--features`
|
|
109
109
|
|
|
110
110
|
Optional paths:
|
|
111
111
|
|
package/dist/commands/angular.js
CHANGED
|
@@ -56,17 +56,19 @@ function resolveSchemasRoot(value, featuresRoot) {
|
|
|
56
56
|
}
|
|
57
57
|
function resolveFeaturesRoot(value) {
|
|
58
58
|
if (value) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
const resolved = path_1.default.resolve(process.cwd(), value);
|
|
60
|
+
const isSrcApp = path_1.default.basename(resolved) === 'app' &&
|
|
61
|
+
path_1.default.basename(path_1.default.dirname(resolved)) === 'src';
|
|
62
|
+
if (isSrcApp) {
|
|
63
|
+
return path_1.default.join(resolved, 'features');
|
|
64
|
+
}
|
|
65
|
+
return resolved;
|
|
64
66
|
}
|
|
65
|
-
const
|
|
66
|
-
if (fs_1.default.existsSync(
|
|
67
|
-
|
|
67
|
+
const srcAppRoot = path_1.default.resolve(process.cwd(), 'src', 'app');
|
|
68
|
+
if (!fs_1.default.existsSync(srcAppRoot)) {
|
|
69
|
+
throw new Error('Default features path not found: ./src/app. Provide --features /path/to/src/app (or /path/to/src/app/features)');
|
|
68
70
|
}
|
|
69
|
-
return path_1.default.
|
|
71
|
+
return path_1.default.join(srcAppRoot, 'features');
|
|
70
72
|
}
|
|
71
73
|
function inferSchemasRootFromFeatures(featuresRoot) {
|
|
72
74
|
const candidate = path_1.default.resolve(featuresRoot, '../../..', 'generate-ui');
|
package/dist/commands/login.js
CHANGED
|
@@ -8,6 +8,7 @@ const http_1 = __importDefault(require("http"));
|
|
|
8
8
|
const url_1 = require("url");
|
|
9
9
|
const promises_1 = require("readline/promises");
|
|
10
10
|
const config_1 = require("../runtime/config");
|
|
11
|
+
const user_config_1 = require("../runtime/user-config");
|
|
11
12
|
const open_browser_1 = require("../runtime/open-browser");
|
|
12
13
|
const token_1 = require("../license/token");
|
|
13
14
|
const permissions_1 = require("../license/permissions");
|
|
@@ -24,6 +25,12 @@ async function login(options) {
|
|
|
24
25
|
// Cached permissions will be refreshed on next online command.
|
|
25
26
|
}
|
|
26
27
|
const email = await promptEmail();
|
|
28
|
+
if (email) {
|
|
29
|
+
(0, user_config_1.updateUserConfig)((config) => ({
|
|
30
|
+
...config,
|
|
31
|
+
lastLoginEmail: email
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
27
34
|
await (0, telemetry_1.trackLogin)(email, options.telemetryEnabled);
|
|
28
35
|
console.log('✔ Login completo');
|
|
29
36
|
}
|
|
@@ -45,6 +52,7 @@ async function promptEmail() {
|
|
|
45
52
|
}
|
|
46
53
|
async function waitForLogin() {
|
|
47
54
|
return new Promise((resolve, reject) => {
|
|
55
|
+
let loginUrl = '';
|
|
48
56
|
const server = http_1.default.createServer((req, res) => {
|
|
49
57
|
const requestUrl = req.url || '/';
|
|
50
58
|
if (!requestUrl.startsWith('/callback')) {
|
|
@@ -132,7 +140,10 @@ async function waitForLogin() {
|
|
|
132
140
|
});
|
|
133
141
|
const timeout = setTimeout(() => {
|
|
134
142
|
server.close();
|
|
135
|
-
|
|
143
|
+
const help = loginUrl
|
|
144
|
+
? ` Ensure the login page is reachable and try again: ${loginUrl}`
|
|
145
|
+
: ` Ensure ${(0, config_1.getWebAuthUrl)()} and ${(0, config_1.getApiBaseUrl)()} are reachable.`;
|
|
146
|
+
reject(new Error(`Login timed out.${help}`));
|
|
136
147
|
}, LOGIN_TIMEOUT_MS);
|
|
137
148
|
server.listen(0, () => {
|
|
138
149
|
const address = server.address();
|
|
@@ -145,7 +156,9 @@ async function waitForLogin() {
|
|
|
145
156
|
const url = new url_1.URL((0, config_1.getWebAuthUrl)());
|
|
146
157
|
url.searchParams.set('redirect_uri', redirectUri);
|
|
147
158
|
url.searchParams.set('api_base', (0, config_1.getApiBaseUrl)());
|
|
148
|
-
|
|
159
|
+
loginUrl = url.toString();
|
|
160
|
+
console.log(`Open this URL to finish login: ${loginUrl}`);
|
|
161
|
+
(0, open_browser_1.openBrowser)(loginUrl);
|
|
149
162
|
});
|
|
150
163
|
});
|
|
151
164
|
}
|
|
@@ -473,8 +473,11 @@ export class ${name}Service {
|
|
|
473
473
|
|
|
474
474
|
.form-grid {
|
|
475
475
|
display: grid;
|
|
476
|
-
grid-template-columns: repeat(auto-fit, minmax(
|
|
477
|
-
gap:
|
|
476
|
+
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
477
|
+
gap: 16px;
|
|
478
|
+
width: 100%;
|
|
479
|
+
max-width: 960px;
|
|
480
|
+
margin: 0 auto;
|
|
478
481
|
}
|
|
479
482
|
|
|
480
483
|
.actions {
|
|
@@ -482,6 +485,7 @@ export class ${name}Service {
|
|
|
482
485
|
justify-content: flex-end;
|
|
483
486
|
gap: 14px;
|
|
484
487
|
margin-top: 20px;
|
|
488
|
+
flex-wrap: wrap;
|
|
485
489
|
}
|
|
486
490
|
|
|
487
491
|
.result {
|
|
@@ -583,6 +587,21 @@ export class ${name}Service {
|
|
|
583
587
|
border-radius: 6px;
|
|
584
588
|
box-shadow: 0 6px 12px rgba(15, 23, 42, 0.16);
|
|
585
589
|
}
|
|
590
|
+
|
|
591
|
+
@media (max-width: 720px) {
|
|
592
|
+
:host {
|
|
593
|
+
padding: 18px;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
.form-grid {
|
|
597
|
+
grid-template-columns: 1fr;
|
|
598
|
+
max-width: 100%;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.actions {
|
|
602
|
+
justify-content: stretch;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
586
605
|
`);
|
|
587
606
|
return {
|
|
588
607
|
path: toRouteSegment(name),
|
|
@@ -750,7 +769,7 @@ function buildComponentHtml(options) {
|
|
|
750
769
|
|
|
751
770
|
<textarea
|
|
752
771
|
*ngIf="isTextarea(field)"
|
|
753
|
-
rows="
|
|
772
|
+
rows="3"
|
|
754
773
|
[formControlName]="field.name"
|
|
755
774
|
[placeholder]="field.placeholder || field.label || field.name"
|
|
756
775
|
[class.invalid]="isInvalid(field)"
|
|
@@ -978,8 +997,8 @@ export class UiFieldComponent {
|
|
|
978
997
|
|
|
979
998
|
.ui-field {
|
|
980
999
|
display: grid;
|
|
981
|
-
gap:
|
|
982
|
-
font-size:
|
|
1000
|
+
gap: 6px;
|
|
1001
|
+
font-size: 12px;
|
|
983
1002
|
color: #374151;
|
|
984
1003
|
}
|
|
985
1004
|
|
|
@@ -1029,12 +1048,12 @@ export class UiFieldComponent {
|
|
|
1029
1048
|
:host ::ng-deep textarea,
|
|
1030
1049
|
:host ::ng-deep select {
|
|
1031
1050
|
width: 100%;
|
|
1032
|
-
min-height:
|
|
1033
|
-
border-radius:
|
|
1051
|
+
min-height: 2.6rem;
|
|
1052
|
+
border-radius: 8px;
|
|
1034
1053
|
border: 1px solid #e5e7eb;
|
|
1035
1054
|
background: #ffffff;
|
|
1036
|
-
padding: 0.
|
|
1037
|
-
font-size:
|
|
1055
|
+
padding: 0.6rem 0.8rem;
|
|
1056
|
+
font-size: 14px;
|
|
1038
1057
|
font-weight: 500;
|
|
1039
1058
|
box-shadow: none;
|
|
1040
1059
|
outline: none;
|
|
@@ -1061,14 +1080,19 @@ export class UiFieldComponent {
|
|
|
1061
1080
|
}
|
|
1062
1081
|
|
|
1063
1082
|
:host ::ng-deep select {
|
|
1064
|
-
padding-right: 2.
|
|
1083
|
+
padding-right: 2.2rem;
|
|
1065
1084
|
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='8' viewBox='0 0 14 8' fill='none'><path d='M1 1.5L7 6.5L13 1.5' stroke='%236b7280' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>");
|
|
1066
1085
|
background-repeat: no-repeat;
|
|
1067
|
-
background-position: right 0.
|
|
1086
|
+
background-position: right 0.7rem center;
|
|
1068
1087
|
background-size: 14px 8px;
|
|
1069
1088
|
appearance: none;
|
|
1070
1089
|
}
|
|
1071
1090
|
|
|
1091
|
+
:host ::ng-deep textarea {
|
|
1092
|
+
min-height: 5.5rem;
|
|
1093
|
+
resize: vertical;
|
|
1094
|
+
}
|
|
1095
|
+
|
|
1072
1096
|
:host ::ng-deep input[type='checkbox'] {
|
|
1073
1097
|
width: 20px;
|
|
1074
1098
|
height: 20px;
|
package/dist/runtime/config.js
CHANGED
|
@@ -12,9 +12,9 @@ function getCliVersion() {
|
|
|
12
12
|
}
|
|
13
13
|
function getApiBaseUrl() {
|
|
14
14
|
return (process.env.GENERATEUI_API_BASE_URL?.trim() ||
|
|
15
|
-
'
|
|
15
|
+
'https://generateuibackend-production.up.railway.app');
|
|
16
16
|
}
|
|
17
17
|
function getWebAuthUrl() {
|
|
18
18
|
return (process.env.GENERATEUI_WEB_AUTH_URL?.trim() ||
|
|
19
|
-
'
|
|
19
|
+
'https://generateuibackend-production.up.railway.app');
|
|
20
20
|
}
|
package/dist/telemetry.js
CHANGED
|
@@ -6,8 +6,9 @@ const crypto_1 = require("crypto");
|
|
|
6
6
|
const config_1 = require("./runtime/config");
|
|
7
7
|
const user_config_1 = require("./runtime/user-config");
|
|
8
8
|
const device_1 = require("./license/device");
|
|
9
|
+
const token_1 = require("./license/token");
|
|
9
10
|
const TELEMETRY_URL = process.env.GENERATEUI_TELEMETRY_URL?.trim() ||
|
|
10
|
-
'https://api.generateui.dev/
|
|
11
|
+
'https://api.generateui.dev/telemetry';
|
|
11
12
|
const TELEMETRY_TIMEOUT_MS = 1000;
|
|
12
13
|
function getOsName() {
|
|
13
14
|
return process.platform;
|
|
@@ -50,7 +51,8 @@ function loadOrCreateConfig() {
|
|
|
50
51
|
return {
|
|
51
52
|
config: {
|
|
52
53
|
installationId,
|
|
53
|
-
telemetry: config.telemetry
|
|
54
|
+
telemetry: config.telemetry,
|
|
55
|
+
lastLoginEmail: config.lastLoginEmail
|
|
54
56
|
},
|
|
55
57
|
isNew
|
|
56
58
|
};
|
|
@@ -61,13 +63,17 @@ function isTelemetryEnabled(cliEnabled, config) {
|
|
|
61
63
|
return config.telemetry !== false;
|
|
62
64
|
}
|
|
63
65
|
async function sendEvent(payload) {
|
|
66
|
+
const token = (0, token_1.loadToken)();
|
|
64
67
|
const controller = new AbortController();
|
|
65
68
|
const timeout = setTimeout(() => controller.abort(), TELEMETRY_TIMEOUT_MS);
|
|
66
69
|
try {
|
|
67
70
|
await fetch(TELEMETRY_URL, {
|
|
68
71
|
method: 'POST',
|
|
69
72
|
headers: {
|
|
70
|
-
'Content-Type': 'application/json'
|
|
73
|
+
'Content-Type': 'application/json',
|
|
74
|
+
...(token
|
|
75
|
+
? { Authorization: `Bearer ${token.accessToken}` }
|
|
76
|
+
: {})
|
|
71
77
|
},
|
|
72
78
|
body: JSON.stringify(payload),
|
|
73
79
|
signal: controller.signal
|
|
@@ -91,6 +97,7 @@ async function trackCommand(command, cliEnabled) {
|
|
|
91
97
|
event: 'first_run',
|
|
92
98
|
installationId: config.installationId,
|
|
93
99
|
deviceId: device.deviceId,
|
|
100
|
+
deviceCreatedAt: device.createdAt,
|
|
94
101
|
os: getOsName(),
|
|
95
102
|
arch: process.arch,
|
|
96
103
|
cliVersion: (0, config_1.getCliVersion)()
|
|
@@ -99,7 +106,9 @@ async function trackCommand(command, cliEnabled) {
|
|
|
99
106
|
await sendEvent({
|
|
100
107
|
event: 'command_run',
|
|
101
108
|
installationId: config.installationId,
|
|
109
|
+
deviceId: device.deviceId,
|
|
102
110
|
command,
|
|
111
|
+
email: config.lastLoginEmail ?? '',
|
|
103
112
|
cliVersion: (0, config_1.getCliVersion)()
|
|
104
113
|
});
|
|
105
114
|
}
|
|
@@ -108,9 +117,11 @@ async function trackLogin(email, cliEnabled) {
|
|
|
108
117
|
const enabled = isTelemetryEnabled(cliEnabled, config);
|
|
109
118
|
if (!enabled)
|
|
110
119
|
return;
|
|
120
|
+
const device = (0, device_1.loadDeviceIdentity)();
|
|
111
121
|
await sendEvent({
|
|
112
122
|
event: 'login',
|
|
113
123
|
installationId: config.installationId,
|
|
124
|
+
deviceId: device.deviceId,
|
|
114
125
|
email: email ?? '',
|
|
115
126
|
cliVersion: (0, config_1.getCliVersion)()
|
|
116
127
|
});
|