@webmate-studio/cli 0.3.7 → 0.3.8
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/bin/wm.mjs +2 -16
- package/package.json +2 -2
- package/src/commands/push.js +0 -275
package/bin/wm.mjs
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { Command } from 'commander';
|
|
4
4
|
import { buildCommand } from '../src/commands/build.js';
|
|
5
|
-
import { pushCommand } from '../src/commands/push.js';
|
|
6
5
|
import { devCommand } from '../src/commands/dev.js';
|
|
7
6
|
import { initCommand } from '../src/commands/init.js';
|
|
8
7
|
import { loginCommand } from '../src/commands/login.js';
|
|
@@ -58,28 +57,15 @@ program
|
|
|
58
57
|
.option('-o, --open', 'Open browser automatically')
|
|
59
58
|
.action(devCommand);
|
|
60
59
|
|
|
61
|
-
// wm build - Build components
|
|
60
|
+
// wm build - Build components (for local testing only - deployment via GitHub)
|
|
62
61
|
program
|
|
63
62
|
.command('build')
|
|
64
|
-
.description('Build components for production')
|
|
63
|
+
.description('Build components for production (local testing only)')
|
|
65
64
|
.option('-o, --output <dir>', 'Output directory', './dist')
|
|
66
65
|
.option('-m, --minify', 'Minify output')
|
|
67
66
|
.option('--watch', 'Watch for changes')
|
|
68
67
|
.action(buildCommand);
|
|
69
68
|
|
|
70
|
-
// wm push - Upload to CMS
|
|
71
|
-
program
|
|
72
|
-
.command('push')
|
|
73
|
-
.description('Upload components to CMS (auto-builds by default)')
|
|
74
|
-
.option('-t, --target <url>', 'CMS target URL')
|
|
75
|
-
.option('--token <token>', 'Authentication token')
|
|
76
|
-
.option('-f, --force', 'Overwrite existing version (development only)')
|
|
77
|
-
.option('--patch', 'Increment patch version (x.y.Z)')
|
|
78
|
-
.option('--minor', 'Increment minor version (x.Y.0)')
|
|
79
|
-
.option('--major', 'Increment major version (X.0.0)')
|
|
80
|
-
.option('--no-build', 'Skip auto-build, use existing dist/ (for CI/CD)')
|
|
81
|
-
.action(pushCommand);
|
|
82
|
-
|
|
83
69
|
// wm logout - Logout from CMS
|
|
84
70
|
program
|
|
85
71
|
.command('logout')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@webmate-studio/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Webmate Studio CLI - Build and manage your Webmate components",
|
|
6
6
|
"keywords": [
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@webmate-studio/builder": "^0.2.1",
|
|
35
35
|
"@webmate-studio/core": "^0.2.0",
|
|
36
36
|
"@webmate-studio/parser": "^0.2.1",
|
|
37
|
-
"@webmate-studio/preview": "^0.2.
|
|
37
|
+
"@webmate-studio/preview": "^0.2.6",
|
|
38
38
|
"alpinejs": "^3.15.0",
|
|
39
39
|
"commander": "^11.0.0",
|
|
40
40
|
"esbuild": "^0.19.0",
|
package/src/commands/push.js
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { uploadComponents, logger } from '@webmate-studio/core';
|
|
2
|
-
import { loadAuth, getTenantCmsUrl, getApiToken, isLoggedIn } from '../utils/auth.js';
|
|
3
|
-
import { loadConfig, updateConfigVersion } from '../utils/config.js';
|
|
4
|
-
import { incrementPatch, incrementMinor, incrementMajor } from '../utils/semver.js';
|
|
5
|
-
import { build as buildComponents } from '@webmate-studio/builder';
|
|
6
|
-
import { existsSync, readFileSync, statSync, readdirSync } from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import { select } from '@inquirer/prompts';
|
|
9
|
-
import ora from 'ora';
|
|
10
|
-
import pc from 'picocolors';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Load design tokens from CMS
|
|
14
|
-
*/
|
|
15
|
-
async function loadDesignTokens() {
|
|
16
|
-
try {
|
|
17
|
-
const auth = loadAuth();
|
|
18
|
-
if (!auth || !auth.apiToken) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const cmsUrl = getTenantCmsUrl();
|
|
23
|
-
if (!cmsUrl) {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Disable SSL verification for localhost
|
|
28
|
-
const isLocalhost = cmsUrl.includes('localhost') || cmsUrl.includes('127.0.0.1');
|
|
29
|
-
if (isLocalhost) {
|
|
30
|
-
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const response = await fetch(`${cmsUrl}/api/design-tokens`, {
|
|
34
|
-
headers: {
|
|
35
|
-
'x-api-token': auth.apiToken
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
if (!response.ok) {
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const data = await response.json();
|
|
44
|
-
|
|
45
|
-
// Restore SSL verification
|
|
46
|
-
if (isLocalhost) {
|
|
47
|
-
delete process.env.NODE_TLS_REJECT_UNAUTHORIZED;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return data.tokens || null;
|
|
51
|
-
} catch (error) {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Check if build is stale (source files newer than build)
|
|
58
|
-
*/
|
|
59
|
-
function isBuildStale(config) {
|
|
60
|
-
const distDir = config.output.dir;
|
|
61
|
-
const componentsDir = config.components.path;
|
|
62
|
-
|
|
63
|
-
const manifestPath = join(distDir, 'manifest.json');
|
|
64
|
-
if (!existsSync(manifestPath)) {
|
|
65
|
-
return true; // No build exists
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try {
|
|
69
|
-
const manifestStat = statSync(manifestPath);
|
|
70
|
-
const manifestTime = manifestStat.mtimeMs;
|
|
71
|
-
|
|
72
|
-
// Check if any component file is newer than manifest
|
|
73
|
-
const componentFiles = readdirSync(componentsDir, { recursive: true, withFileTypes: true });
|
|
74
|
-
for (const file of componentFiles) {
|
|
75
|
-
if (file.isFile() && (file.name.endsWith('.html') || file.name.endsWith('.js'))) {
|
|
76
|
-
const filePath = join(file.path, file.name);
|
|
77
|
-
const fileStat = statSync(filePath);
|
|
78
|
-
if (fileStat.mtimeMs > manifestTime) {
|
|
79
|
-
return true; // Source file is newer
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return false; // Build is up to date
|
|
85
|
-
} catch (error) {
|
|
86
|
-
return true; // On error, assume stale
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Push command - upload built components to CMS
|
|
92
|
-
* Auto-builds unless --no-build is specified
|
|
93
|
-
*/
|
|
94
|
-
export async function pushCommand(options) {
|
|
95
|
-
const config = await loadConfig();
|
|
96
|
-
const distDir = config.output.dir;
|
|
97
|
-
const manifestPath = join(distDir, 'manifest.json');
|
|
98
|
-
|
|
99
|
-
// Auto-build unless --no-build is specified
|
|
100
|
-
// Commander sets build: false when --no-build is used
|
|
101
|
-
if (options.build === false) {
|
|
102
|
-
// --no-build flag: Check if build exists
|
|
103
|
-
if (!existsSync(manifestPath)) {
|
|
104
|
-
logger.error('No build found and --no-build specified.');
|
|
105
|
-
logger.info('Run `wm build` first or remove --no-build flag.');
|
|
106
|
-
process.exit(1);
|
|
107
|
-
}
|
|
108
|
-
logger.info('Using existing build (--no-build).');
|
|
109
|
-
} else {
|
|
110
|
-
// Auto-build mode (default)
|
|
111
|
-
const buildExists = existsSync(manifestPath);
|
|
112
|
-
const buildStale = buildExists ? isBuildStale(config) : true;
|
|
113
|
-
|
|
114
|
-
if (!buildExists) {
|
|
115
|
-
logger.info('No build found. Building components...');
|
|
116
|
-
} else if (buildStale) {
|
|
117
|
-
logger.info('Source files changed. Rebuilding components...');
|
|
118
|
-
} else {
|
|
119
|
-
logger.info('Using existing build (up to date).');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
if (!buildExists || buildStale) {
|
|
123
|
-
const buildSpinner = ora('Building components...').start();
|
|
124
|
-
try {
|
|
125
|
-
await buildComponents({
|
|
126
|
-
outputDir: config.output.dir,
|
|
127
|
-
minify: config.output.minify || false,
|
|
128
|
-
designTokens: await loadDesignTokens()
|
|
129
|
-
});
|
|
130
|
-
buildSpinner.succeed('Build complete!');
|
|
131
|
-
} catch (error) {
|
|
132
|
-
buildSpinner.fail('Build failed');
|
|
133
|
-
logger.error(error.message);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
|
|
140
|
-
|
|
141
|
-
// Get target and token - prefer auth over config
|
|
142
|
-
let target;
|
|
143
|
-
let token;
|
|
144
|
-
|
|
145
|
-
// Use auth credentials if logged in (priority!)
|
|
146
|
-
if (isLoggedIn()) {
|
|
147
|
-
const auth = loadAuth();
|
|
148
|
-
target = options.target || getTenantCmsUrl();
|
|
149
|
-
token = options.token || getApiToken();
|
|
150
|
-
|
|
151
|
-
console.log('');
|
|
152
|
-
logger.info(`Using logged in project: ${pc.cyan(auth.tenant.name)}`);
|
|
153
|
-
logger.info(`Target: ${pc.cyan(target)}`);
|
|
154
|
-
} else {
|
|
155
|
-
// Not logged in - require explicit options
|
|
156
|
-
target = options.target;
|
|
157
|
-
token = options.token || process.env.CMS_TOKEN;
|
|
158
|
-
|
|
159
|
-
if (!target) {
|
|
160
|
-
logger.error('Not logged in and no target URL specified.');
|
|
161
|
-
logger.info('Either run `wm login` first or use --target option');
|
|
162
|
-
process.exit(1);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (!token) {
|
|
166
|
-
logger.error('Not authenticated.');
|
|
167
|
-
logger.info('Run `wm login` first or set CMS_TOKEN env variable');
|
|
168
|
-
process.exit(1);
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Determine new version
|
|
173
|
-
const currentVersion = config.version || '0.1.0';
|
|
174
|
-
let newVersion;
|
|
175
|
-
let shouldUpdateConfig = false;
|
|
176
|
-
|
|
177
|
-
if (options.force) {
|
|
178
|
-
// Force mode: Keep current version, overwrite
|
|
179
|
-
newVersion = currentVersion;
|
|
180
|
-
logger.info(`Version: ${pc.cyan(currentVersion)} ${pc.dim('(force overwrite)')}`);
|
|
181
|
-
} else if (options.patch) {
|
|
182
|
-
// Explicit patch increment
|
|
183
|
-
newVersion = incrementPatch(currentVersion);
|
|
184
|
-
shouldUpdateConfig = true;
|
|
185
|
-
logger.info(`Version: ${pc.cyan(currentVersion)} → ${pc.cyan(newVersion)} ${pc.dim('(patch)')}`);
|
|
186
|
-
} else if (options.minor) {
|
|
187
|
-
// Explicit minor increment
|
|
188
|
-
newVersion = incrementMinor(currentVersion);
|
|
189
|
-
shouldUpdateConfig = true;
|
|
190
|
-
logger.info(`Version: ${pc.cyan(currentVersion)} → ${pc.cyan(newVersion)} ${pc.dim('(minor)')}`);
|
|
191
|
-
} else if (options.major) {
|
|
192
|
-
// Explicit major increment
|
|
193
|
-
newVersion = incrementMajor(currentVersion);
|
|
194
|
-
shouldUpdateConfig = true;
|
|
195
|
-
logger.info(`Version: ${pc.cyan(currentVersion)} → ${pc.cyan(newVersion)} ${pc.dim('(major)')}`);
|
|
196
|
-
} else {
|
|
197
|
-
// Interactive prompt
|
|
198
|
-
console.log('');
|
|
199
|
-
const choice = await select({
|
|
200
|
-
message: `Current version: ${pc.cyan(currentVersion)}. How do you want to publish?`,
|
|
201
|
-
choices: [
|
|
202
|
-
{
|
|
203
|
-
name: `Patch (${pc.cyan(incrementPatch(currentVersion))}) - Bug fixes, small changes`,
|
|
204
|
-
value: 'patch',
|
|
205
|
-
description: 'Backwards compatible bug fixes'
|
|
206
|
-
},
|
|
207
|
-
{
|
|
208
|
-
name: `Minor (${pc.cyan(incrementMinor(currentVersion))}) - New features, backwards compatible`,
|
|
209
|
-
value: 'minor',
|
|
210
|
-
description: 'New functionality, backwards compatible'
|
|
211
|
-
},
|
|
212
|
-
{
|
|
213
|
-
name: `Major (${pc.cyan(incrementMajor(currentVersion))}) - Breaking changes`,
|
|
214
|
-
value: 'major',
|
|
215
|
-
description: 'Breaking changes, incompatible with previous versions'
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
name: `Force (${pc.cyan(currentVersion)}) - Overwrite current version ${pc.dim('(development only)')}`,
|
|
219
|
-
value: 'force',
|
|
220
|
-
description: 'Overwrite existing version without incrementing'
|
|
221
|
-
}
|
|
222
|
-
]
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
if (choice === 'patch') {
|
|
226
|
-
newVersion = incrementPatch(currentVersion);
|
|
227
|
-
shouldUpdateConfig = true;
|
|
228
|
-
} else if (choice === 'minor') {
|
|
229
|
-
newVersion = incrementMinor(currentVersion);
|
|
230
|
-
shouldUpdateConfig = true;
|
|
231
|
-
} else if (choice === 'major') {
|
|
232
|
-
newVersion = incrementMajor(currentVersion);
|
|
233
|
-
shouldUpdateConfig = true;
|
|
234
|
-
} else if (choice === 'force') {
|
|
235
|
-
newVersion = currentVersion;
|
|
236
|
-
shouldUpdateConfig = false;
|
|
237
|
-
options.force = true; // Enable force mode
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
console.log('');
|
|
241
|
-
logger.info(`Publishing version: ${pc.cyan(newVersion)}`);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// Update manifest with new version
|
|
245
|
-
manifest.version = newVersion;
|
|
246
|
-
|
|
247
|
-
const spinner = ora(`Uploading to ${target}...`).start();
|
|
248
|
-
|
|
249
|
-
try {
|
|
250
|
-
await uploadComponents(distDir, target, token, {
|
|
251
|
-
force: options.force || false,
|
|
252
|
-
version: newVersion
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
spinner.succeed('Upload complete!');
|
|
256
|
-
|
|
257
|
-
// Update config file with new version (only if not force mode)
|
|
258
|
-
if (shouldUpdateConfig) {
|
|
259
|
-
try {
|
|
260
|
-
updateConfigVersion(newVersion);
|
|
261
|
-
logger.success(`Updated wm.config.js with version ${pc.cyan(newVersion)}`);
|
|
262
|
-
} catch (err) {
|
|
263
|
-
logger.warn(`Could not update config file: ${err.message}`);
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
logger.success(`\n✅ Uploaded ${manifest.components.length} components to ${target}`);
|
|
268
|
-
logger.info(`Version: ${pc.cyan(newVersion)}`);
|
|
269
|
-
logger.info('Components are now available in your CMS.');
|
|
270
|
-
} catch (error) {
|
|
271
|
-
spinner.fail('Upload failed');
|
|
272
|
-
logger.error(error.message);
|
|
273
|
-
process.exit(1);
|
|
274
|
-
}
|
|
275
|
-
}
|