@yoamigo.com/cli 0.1.25 → 0.1.27
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/index.js +228 -122
- package/package.json +3 -1
- package/templates/starter/CHANGELOG.md +31 -0
- package/templates/starter/package-lock.json +472 -768
- package/templates/starter/package.json +1 -3
- package/templates/starter/public/{favicon.svg → assets/favicon.svg} +2 -2
- package/templates/starter/public/assets/welcome.jpg +0 -0
- package/templates/starter/showcase/01-desktop-hero.png +0 -0
- package/templates/starter/showcase/02-mobile-hero.png +0 -0
- package/templates/starter/showcase/06-desktop-about.png +0 -0
- package/templates/starter/showcase/07-desktop-contact.png +0 -0
- package/templates/starter/showcase/manifest.json +30 -0
- package/templates/starter/src/App.tsx +2 -1
- package/templates/starter/src/components/Footer.tsx +9 -3
- package/templates/starter/src/components/Header.tsx +96 -15
- package/templates/starter/src/content.ts +18 -16
- package/templates/starter/src/pages/about.tsx +21 -10
- package/templates/starter/src/pages/contact.tsx +58 -201
- package/templates/starter/src/pages/index.tsx +49 -57
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ my-template/
|
|
|
103
103
|
|
|
104
104
|
## Documentation
|
|
105
105
|
|
|
106
|
-
For full documentation, visit [yoamigo.com/
|
|
106
|
+
For full documentation, visit [https://www.yoamigo.com/dev/docs](https://www.yoamigo.com/dev/docs).
|
|
107
107
|
|
|
108
108
|
## License
|
|
109
109
|
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import "dotenv/config";
|
|
5
|
-
import { Command as
|
|
5
|
+
import { Command as Command6 } from "commander";
|
|
6
6
|
import { createRequire } from "module";
|
|
7
7
|
|
|
8
8
|
// src/commands/deploy.ts
|
|
@@ -11,6 +11,8 @@ import chalk2 from "chalk";
|
|
|
11
11
|
import ora2 from "ora";
|
|
12
12
|
import fs2 from "fs-extra";
|
|
13
13
|
import path2 from "path";
|
|
14
|
+
import os2 from "os";
|
|
15
|
+
import { execSync } from "child_process";
|
|
14
16
|
|
|
15
17
|
// src/commands/login.ts
|
|
16
18
|
import { Command } from "commander";
|
|
@@ -116,19 +118,10 @@ var loginCommand = new Command("login").description("Authenticate with your API
|
|
|
116
118
|
// src/commands/deploy.ts
|
|
117
119
|
var API_BASE_URL2 = getApiBaseUrl();
|
|
118
120
|
var APP_BASE_URL = getAppBaseUrl();
|
|
119
|
-
var EXCLUDE_PATTERNS = ["node_modules", "dist", ".git", "
|
|
120
|
-
var
|
|
121
|
-
"index.html",
|
|
122
|
-
"package.json",
|
|
123
|
-
"package-lock.json",
|
|
124
|
-
"pnpm-lock.yaml",
|
|
125
|
-
"vite.config.ts",
|
|
126
|
-
"tsconfig.json",
|
|
127
|
-
"postcss.config.cjs",
|
|
128
|
-
"tailwind.config.ts"
|
|
129
|
-
];
|
|
130
|
-
var deployCommand = new Command2("deploy").description("Upload template to YoAmigo").argument("<version>", "Template version (e.g., 1.0.0)").option("-v, --verbose", "Show detailed logging for debugging").action(async (version, options) => {
|
|
121
|
+
var EXCLUDE_PATTERNS = ["node_modules", "dist", ".git", ".vite", ".DS_Store"];
|
|
122
|
+
var deployCommand = new Command2("deploy").description("Upload template to YoAmigo").argument("[version]", "Template version (e.g., 1.0.0). Defaults to version from package.json").option("-v, --verbose", "Show detailed logging for debugging").action(async (versionArg, options) => {
|
|
131
123
|
const verbose = options.verbose;
|
|
124
|
+
let tempDir = null;
|
|
132
125
|
if (verbose) {
|
|
133
126
|
console.log(chalk2.dim(`API URL: ${API_BASE_URL2}`));
|
|
134
127
|
console.log(chalk2.dim(`App URL: ${APP_BASE_URL}`));
|
|
@@ -139,11 +132,6 @@ var deployCommand = new Command2("deploy").description("Upload template to YoAmi
|
|
|
139
132
|
console.error(chalk2.red("Error: Not logged in. Run `yoamigo login` first."));
|
|
140
133
|
process.exit(1);
|
|
141
134
|
}
|
|
142
|
-
const versionRegex = /^\d+\.\d+\.\d+$/;
|
|
143
|
-
if (!versionRegex.test(version)) {
|
|
144
|
-
console.error(chalk2.red("Error: Version must be in semver format (e.g., 1.0.0)"));
|
|
145
|
-
process.exit(1);
|
|
146
|
-
}
|
|
147
135
|
const packageJsonPath = path2.join(process.cwd(), "package.json");
|
|
148
136
|
if (!await fs2.pathExists(packageJsonPath)) {
|
|
149
137
|
console.error(chalk2.red("Error: No package.json found. Are you in a template project?"));
|
|
@@ -151,14 +139,22 @@ var deployCommand = new Command2("deploy").description("Upload template to YoAmi
|
|
|
151
139
|
}
|
|
152
140
|
const packageJson = await fs2.readJson(packageJsonPath);
|
|
153
141
|
const templateName = packageJson.name || "unnamed-template";
|
|
142
|
+
const version = versionArg || packageJson.version;
|
|
143
|
+
if (!version) {
|
|
144
|
+
console.error(chalk2.red("Error: No version specified and package.json has no version field"));
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
const versionRegex = /^\d+\.\d+\.\d+$/;
|
|
148
|
+
if (!versionRegex.test(version)) {
|
|
149
|
+
console.error(chalk2.red(`Error: Version "${version}" must be in semver format (e.g., 1.0.0)`));
|
|
150
|
+
process.exit(1);
|
|
151
|
+
}
|
|
152
|
+
if (!versionArg) {
|
|
153
|
+
console.log(chalk2.dim(`Using version from package.json: ${version}`));
|
|
154
|
+
}
|
|
154
155
|
const spinner = ora2("Deploying template...").start();
|
|
155
156
|
try {
|
|
156
|
-
spinner.text = "
|
|
157
|
-
const files = await collectFiles(process.cwd());
|
|
158
|
-
if (files.length === 0) {
|
|
159
|
-
throw new Error("No files found to upload");
|
|
160
|
-
}
|
|
161
|
-
spinner.text = `Uploading ${files.length} files...`;
|
|
157
|
+
spinner.text = "Creating template version...";
|
|
162
158
|
const templateUrl = `${API_BASE_URL2}/api/trpc/developer.createOrUpdateTemplate`;
|
|
163
159
|
const templateBody = {
|
|
164
160
|
name: templateName,
|
|
@@ -171,30 +167,14 @@ var deployCommand = new Command2("deploy").description("Upload template to YoAmi
|
|
|
171
167
|
console.log(chalk2.dim(`Body: ${JSON.stringify(templateBody)}`));
|
|
172
168
|
spinner.start();
|
|
173
169
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
body: JSON.stringify(templateBody)
|
|
183
|
-
});
|
|
184
|
-
} catch (fetchError) {
|
|
185
|
-
if (verbose) {
|
|
186
|
-
spinner.stop();
|
|
187
|
-
console.error(chalk2.red(`
|
|
188
|
-
Fetch error for ${templateUrl}:`));
|
|
189
|
-
console.error(chalk2.red(fetchError instanceof Error ? fetchError.stack || fetchError.message : String(fetchError)));
|
|
190
|
-
}
|
|
191
|
-
throw new Error(`Network error: ${fetchError instanceof Error ? fetchError.message : "fetch failed"}`);
|
|
192
|
-
}
|
|
193
|
-
if (verbose) {
|
|
194
|
-
spinner.stop();
|
|
195
|
-
console.log(chalk2.dim(`Response status: ${templateResponse.status}`));
|
|
196
|
-
spinner.start();
|
|
197
|
-
}
|
|
170
|
+
const templateResponse = await fetch(templateUrl, {
|
|
171
|
+
method: "POST",
|
|
172
|
+
headers: {
|
|
173
|
+
"Content-Type": "application/json",
|
|
174
|
+
"X-API-Key": credentials.apiKey
|
|
175
|
+
},
|
|
176
|
+
body: JSON.stringify(templateBody)
|
|
177
|
+
});
|
|
198
178
|
if (!templateResponse.ok) {
|
|
199
179
|
const errorText = await templateResponse.text();
|
|
200
180
|
if (verbose) {
|
|
@@ -214,65 +194,90 @@ Response body: ${errorText}`));
|
|
|
214
194
|
const templateData = await templateResponse.json();
|
|
215
195
|
const templateId = templateData.result?.data?.id;
|
|
216
196
|
const versionId = templateData.result?.data?.versionId;
|
|
217
|
-
if (!templateId) {
|
|
218
|
-
throw new Error("Failed to get template ID");
|
|
197
|
+
if (!templateId || !versionId) {
|
|
198
|
+
throw new Error("Failed to get template ID or version ID");
|
|
219
199
|
}
|
|
220
|
-
if (verbose
|
|
200
|
+
if (verbose) {
|
|
221
201
|
spinner.stop();
|
|
202
|
+
console.log(chalk2.dim(`Template ID: ${templateId}`));
|
|
222
203
|
console.log(chalk2.dim(`Version ID: ${versionId}`));
|
|
223
204
|
spinner.start();
|
|
224
205
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
}
|
|
206
|
+
spinner.text = "Copying template files...";
|
|
207
|
+
tempDir = await fs2.mkdtemp(path2.join(os2.tmpdir(), "yoamigo-deploy-"));
|
|
208
|
+
await copyTemplateFiles(process.cwd(), tempDir, verbose ? spinner : null);
|
|
209
|
+
spinner.text = "Installing dependencies (this may take a minute)...";
|
|
210
|
+
if (verbose) {
|
|
211
|
+
spinner.stop();
|
|
212
|
+
console.log(chalk2.dim("Running: pnpm install --ignore-scripts"));
|
|
213
|
+
spinner.start();
|
|
214
|
+
}
|
|
215
|
+
try {
|
|
216
|
+
execSync("pnpm install --ignore-scripts", {
|
|
217
|
+
cwd: tempDir,
|
|
218
|
+
stdio: "pipe",
|
|
219
|
+
maxBuffer: 10 * 1024 * 1024
|
|
220
|
+
});
|
|
221
|
+
} catch (installError) {
|
|
222
|
+
throw new Error(`Failed to install dependencies: ${installError instanceof Error ? installError.message : "unknown error"}`);
|
|
223
|
+
}
|
|
224
|
+
spinner.text = "Creating tarball...";
|
|
225
|
+
const tarballPath = path2.join(tempDir, "repo.tar.gz");
|
|
226
|
+
try {
|
|
227
|
+
execSync(
|
|
228
|
+
`tar -czf "${tarballPath}" --exclude='repo.tar.gz' -C "${tempDir}" .`,
|
|
229
|
+
{ maxBuffer: 50 * 1024 * 1024 }
|
|
230
|
+
);
|
|
231
|
+
} catch (tarError) {
|
|
232
|
+
throw new Error(`Failed to create tarball: ${tarError instanceof Error ? tarError.message : "unknown error"}`);
|
|
233
|
+
}
|
|
234
|
+
const tarballStats = await fs2.stat(tarballPath);
|
|
235
|
+
const tarballSizeKB = Math.round(tarballStats.size / 1024);
|
|
236
|
+
const tarballSizeMB = (tarballStats.size / (1024 * 1024)).toFixed(1);
|
|
237
|
+
if (verbose) {
|
|
238
|
+
spinner.stop();
|
|
239
|
+
console.log(chalk2.dim(`Tarball size: ${tarballSizeMB} MB (${tarballSizeKB} KB)`));
|
|
240
|
+
spinner.start();
|
|
241
|
+
}
|
|
242
|
+
spinner.text = "Getting upload URL...";
|
|
243
|
+
const uploadUrlEndpoint = `${API_BASE_URL2}/api/trpc/developer.getTarballUploadUrl`;
|
|
244
|
+
const uploadUrlResponse = await fetch(uploadUrlEndpoint, {
|
|
245
|
+
method: "POST",
|
|
246
|
+
headers: {
|
|
247
|
+
"Content-Type": "application/json",
|
|
248
|
+
"X-API-Key": credentials.apiKey
|
|
249
|
+
},
|
|
250
|
+
body: JSON.stringify({ templateId, versionId })
|
|
251
|
+
});
|
|
252
|
+
if (!uploadUrlResponse.ok) {
|
|
253
|
+
const errorText = await uploadUrlResponse.text();
|
|
254
|
+
throw new Error(`Failed to get upload URL: ${errorText}`);
|
|
255
|
+
}
|
|
256
|
+
const uploadUrlData = await uploadUrlResponse.json();
|
|
257
|
+
const uploadUrl = uploadUrlData.result?.data?.uploadUrl;
|
|
258
|
+
if (!uploadUrl) {
|
|
259
|
+
throw new Error("Failed to get upload URL from API");
|
|
260
|
+
}
|
|
261
|
+
spinner.text = `Uploading tarball (${tarballSizeMB} MB)...`;
|
|
262
|
+
const tarballBuffer = await fs2.readFile(tarballPath);
|
|
263
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
264
|
+
method: "PUT",
|
|
265
|
+
headers: {
|
|
266
|
+
"Content-Type": "application/gzip"
|
|
267
|
+
},
|
|
268
|
+
body: tarballBuffer
|
|
269
|
+
});
|
|
270
|
+
if (!uploadResponse.ok) {
|
|
271
|
+
const errorText = await uploadResponse.text();
|
|
272
|
+
throw new Error(`Failed to upload tarball: ${uploadResponse.status} ${errorText}`);
|
|
270
273
|
}
|
|
271
274
|
spinner.succeed(`Template v${version} deployed successfully!`);
|
|
272
275
|
console.log();
|
|
273
276
|
console.log(chalk2.green("Preview URL:"));
|
|
274
277
|
console.log(chalk2.cyan(` ${APP_BASE_URL}/preview/${templateId}`));
|
|
275
278
|
console.log();
|
|
279
|
+
console.log(chalk2.dim(`Tarball size: ${tarballSizeMB} MB`));
|
|
280
|
+
console.log();
|
|
276
281
|
console.log(chalk2.dim("To submit for review, visit your dashboard:"));
|
|
277
282
|
console.log(chalk2.dim(` ${APP_BASE_URL}/dashboard`));
|
|
278
283
|
} catch (error) {
|
|
@@ -283,44 +288,54 @@ Response body: ${errorText}`));
|
|
|
283
288
|
console.error(chalk2.red(error instanceof Error ? error.message : "Unknown error"));
|
|
284
289
|
}
|
|
285
290
|
process.exit(1);
|
|
291
|
+
} finally {
|
|
292
|
+
if (tempDir) {
|
|
293
|
+
try {
|
|
294
|
+
await fs2.remove(tempDir);
|
|
295
|
+
} catch {
|
|
296
|
+
}
|
|
297
|
+
}
|
|
286
298
|
}
|
|
287
299
|
});
|
|
288
|
-
async function
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
300
|
+
async function copyTemplateFiles(srcDir, destDir, spinner) {
|
|
301
|
+
const entries = await fs2.readdir(srcDir, { withFileTypes: true });
|
|
302
|
+
let fileCount = 0;
|
|
303
|
+
for (const entry of entries) {
|
|
304
|
+
if (EXCLUDE_PATTERNS.some((pattern) => entry.name === pattern || entry.name.startsWith("."))) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
const srcPath = path2.join(srcDir, entry.name);
|
|
308
|
+
const destPath = path2.join(destDir, entry.name);
|
|
309
|
+
if (entry.isDirectory()) {
|
|
310
|
+
await fs2.mkdirp(destPath);
|
|
311
|
+
await copyTemplateFilesRecursive(srcPath, destPath);
|
|
312
|
+
fileCount++;
|
|
313
|
+
} else {
|
|
314
|
+
await fs2.copy(srcPath, destPath);
|
|
315
|
+
fileCount++;
|
|
296
316
|
}
|
|
297
317
|
}
|
|
298
|
-
if (
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
if (await fs2.pathExists(publicDir)) {
|
|
303
|
-
const publicFiles = await collectFilesRecursive(publicDir);
|
|
304
|
-
files.push(...publicFiles);
|
|
318
|
+
if (spinner) {
|
|
319
|
+
spinner.stop();
|
|
320
|
+
console.log(chalk2.dim(`Copied ${fileCount} files/directories`));
|
|
321
|
+
spinner.start();
|
|
305
322
|
}
|
|
306
|
-
return files;
|
|
307
323
|
}
|
|
308
|
-
async function
|
|
309
|
-
const
|
|
310
|
-
const entries = await fs2.readdir(dir, { withFileTypes: true });
|
|
324
|
+
async function copyTemplateFilesRecursive(srcDir, destDir) {
|
|
325
|
+
const entries = await fs2.readdir(srcDir, { withFileTypes: true });
|
|
311
326
|
for (const entry of entries) {
|
|
312
|
-
|
|
313
|
-
if (EXCLUDE_PATTERNS.some((pattern) => entry.name.includes(pattern))) {
|
|
327
|
+
if (EXCLUDE_PATTERNS.some((pattern) => entry.name === pattern)) {
|
|
314
328
|
continue;
|
|
315
329
|
}
|
|
330
|
+
const srcPath = path2.join(srcDir, entry.name);
|
|
331
|
+
const destPath = path2.join(destDir, entry.name);
|
|
316
332
|
if (entry.isDirectory()) {
|
|
317
|
-
|
|
318
|
-
|
|
333
|
+
await fs2.mkdirp(destPath);
|
|
334
|
+
await copyTemplateFilesRecursive(srcPath, destPath);
|
|
319
335
|
} else {
|
|
320
|
-
|
|
336
|
+
await fs2.copy(srcPath, destPath);
|
|
321
337
|
}
|
|
322
338
|
}
|
|
323
|
-
return files;
|
|
324
339
|
}
|
|
325
340
|
|
|
326
341
|
// src/commands/dev.ts
|
|
@@ -457,13 +472,104 @@ var initCommand = new Command4("init").description("Create a new template projec
|
|
|
457
472
|
}
|
|
458
473
|
});
|
|
459
474
|
|
|
475
|
+
// src/commands/pull.ts
|
|
476
|
+
import { Buffer } from "buffer";
|
|
477
|
+
import { Command as Command5 } from "commander";
|
|
478
|
+
import chalk5 from "chalk";
|
|
479
|
+
import ora4 from "ora";
|
|
480
|
+
import fs5 from "fs-extra";
|
|
481
|
+
import path5 from "path";
|
|
482
|
+
var API_BASE_URL3 = getApiBaseUrl();
|
|
483
|
+
var pullCommand = new Command5("pull").description("Download a website from YoAmigo").argument("<siteId>", "The website ID to download").option("-o, --output <path>", "Output path for the ZIP file").option("-v, --verbose", "Show detailed logging for debugging").action(async (siteId, options) => {
|
|
484
|
+
const verbose = options.verbose;
|
|
485
|
+
if (verbose) {
|
|
486
|
+
console.log(chalk5.dim(`API URL: ${API_BASE_URL3}`));
|
|
487
|
+
console.log();
|
|
488
|
+
}
|
|
489
|
+
const credentials = await getCredentials();
|
|
490
|
+
if (!credentials) {
|
|
491
|
+
console.error(chalk5.red("Error: Not logged in. Run `yoamigo login` first."));
|
|
492
|
+
process.exit(1);
|
|
493
|
+
}
|
|
494
|
+
if (!siteId || siteId.trim().length === 0) {
|
|
495
|
+
console.error(chalk5.red("Error: Site ID is required."));
|
|
496
|
+
console.log(chalk5.dim("Usage: yoamigo pull <siteId>"));
|
|
497
|
+
process.exit(1);
|
|
498
|
+
}
|
|
499
|
+
const spinner = ora4("Downloading website...").start();
|
|
500
|
+
try {
|
|
501
|
+
const downloadUrl = `${API_BASE_URL3}/api/cli/download/${encodeURIComponent(siteId)}`;
|
|
502
|
+
if (verbose) {
|
|
503
|
+
spinner.stop();
|
|
504
|
+
console.log(chalk5.dim(`GET ${downloadUrl}`));
|
|
505
|
+
spinner.start();
|
|
506
|
+
}
|
|
507
|
+
const response = await fetch(downloadUrl, {
|
|
508
|
+
method: "GET",
|
|
509
|
+
headers: {
|
|
510
|
+
"X-API-Key": credentials.apiKey
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
if (!response.ok) {
|
|
514
|
+
const errorText = await response.text();
|
|
515
|
+
let errorMessage = "Failed to download website";
|
|
516
|
+
try {
|
|
517
|
+
const error = JSON.parse(errorText);
|
|
518
|
+
errorMessage = error.error || error.message || errorMessage;
|
|
519
|
+
} catch {
|
|
520
|
+
errorMessage = errorText || errorMessage;
|
|
521
|
+
}
|
|
522
|
+
if (response.status === 401) {
|
|
523
|
+
throw new Error("Invalid or expired API key. Run `yoamigo login` again.");
|
|
524
|
+
} else if (response.status === 403) {
|
|
525
|
+
throw new Error(errorMessage);
|
|
526
|
+
} else if (response.status === 404) {
|
|
527
|
+
throw new Error(`Website not found: ${siteId}`);
|
|
528
|
+
} else {
|
|
529
|
+
throw new Error(errorMessage);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
const contentDisposition = response.headers.get("content-disposition");
|
|
533
|
+
let filename = `${siteId}.zip`;
|
|
534
|
+
if (contentDisposition) {
|
|
535
|
+
const filenameMatch = contentDisposition.match(/filename="?([^";\n]+)"?/);
|
|
536
|
+
if (filenameMatch) {
|
|
537
|
+
filename = filenameMatch[1];
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
const outputPath = options.output ? path5.resolve(options.output) : path5.join(process.cwd(), filename);
|
|
541
|
+
spinner.text = "Saving file...";
|
|
542
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
543
|
+
const buffer = Buffer.from(arrayBuffer);
|
|
544
|
+
await fs5.ensureDir(path5.dirname(outputPath));
|
|
545
|
+
await fs5.writeFile(outputPath, buffer);
|
|
546
|
+
const fileSizeKB = Math.round(buffer.length / 1024);
|
|
547
|
+
const fileSizeMB = (buffer.length / (1024 * 1024)).toFixed(2);
|
|
548
|
+
spinner.succeed(`Website downloaded successfully!`);
|
|
549
|
+
console.log();
|
|
550
|
+
console.log(chalk5.green("Saved to:"));
|
|
551
|
+
console.log(chalk5.cyan(` ${outputPath}`));
|
|
552
|
+
console.log();
|
|
553
|
+
console.log(chalk5.dim(`File size: ${fileSizeMB} MB (${fileSizeKB} KB)`));
|
|
554
|
+
} catch (error) {
|
|
555
|
+
spinner.fail("Failed to download website");
|
|
556
|
+
if (verbose && error instanceof Error && error.stack) {
|
|
557
|
+
console.error(chalk5.red(error.stack));
|
|
558
|
+
} else {
|
|
559
|
+
console.error(chalk5.red(error instanceof Error ? error.message : "Unknown error"));
|
|
560
|
+
}
|
|
561
|
+
process.exit(1);
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
|
|
460
565
|
// src/index.ts
|
|
461
566
|
var require2 = createRequire(import.meta.url);
|
|
462
567
|
var pkg = require2("../package.json");
|
|
463
|
-
var program = new
|
|
568
|
+
var program = new Command6();
|
|
464
569
|
program.name("yoamigo").description("CLI for creating and managing YoAmigo templates").version(pkg.version, "-v, --version", "output the current version");
|
|
465
570
|
program.addCommand(loginCommand);
|
|
466
571
|
program.addCommand(initCommand);
|
|
467
572
|
program.addCommand(devCommand);
|
|
468
573
|
program.addCommand(deployCommand);
|
|
574
|
+
program.addCommand(pullCommand);
|
|
469
575
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yoamigo.com/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.27",
|
|
4
4
|
"description": "CLI for creating and managing YoAmigo templates",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE",
|
|
@@ -15,6 +15,8 @@
|
|
|
15
15
|
"!templates/*/node_modules",
|
|
16
16
|
"!templates/*/dist",
|
|
17
17
|
"!templates/*/.vite",
|
|
18
|
+
"!templates/*/.env",
|
|
19
|
+
"!templates/*/.claude",
|
|
18
20
|
"LICENSE",
|
|
19
21
|
"README.md"
|
|
20
22
|
],
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [1.0.14] - 2025-01-07
|
|
6
|
+
|
|
7
|
+
### Improvements
|
|
8
|
+
- Improved page navigation for smoother multi-page browsing
|
|
9
|
+
|
|
10
|
+
## [1.0.13] - 2025-01-05
|
|
11
|
+
|
|
12
|
+
### Improvements
|
|
13
|
+
- Updated header component styling
|
|
14
|
+
|
|
15
|
+
## [1.0.6] - 2025-12-16
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
- Added `preact` as direct dependency for production builds (required by pnpm strict resolution)
|
|
19
|
+
|
|
20
|
+
## [1.0.5] - 2025-12-16
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- Added tiptap dependencies for rich text editing support
|
|
24
|
+
- `@tiptap/core`, `@tiptap/react`, `@tiptap/starter-kit`, `@tiptap/extension-link`, `@tiptap/extension-text-style`, `@tiptap/pm`
|
|
25
|
+
- `dompurify` for HTML sanitization
|
|
26
|
+
- Updated `@yoamigo.com/core` to `^0.1.7`
|
|
27
|
+
|
|
28
|
+
## [1.0.4] - 2025-12-16
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
- Initial versioned release with self-contained template architecture
|