@hapico/cli 0.0.21 → 0.0.23

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/index.js CHANGED
@@ -123,6 +123,18 @@ const tryJSONParse = (str) => {
123
123
  }
124
124
  };
125
125
  exports.tryJSONParse = tryJSONParse;
126
+ // only support .ts, .tsx, .js, .jsx, .json, .css, .html, .env files
127
+ const supportedExtensions = [
128
+ ".ts",
129
+ ".tsx",
130
+ ".js",
131
+ ".jsx",
132
+ ".json",
133
+ ".css",
134
+ ".html",
135
+ ".env",
136
+ ];
137
+ const ignoreFolders = ["node_modules", ".git", ".hg", ".svn"];
126
138
  const compileES5 = (code, filePath) => {
127
139
  if (filePath && !filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
128
140
  return code;
@@ -143,7 +155,7 @@ const compileES5 = (code, filePath) => {
143
155
  return result.code;
144
156
  }
145
157
  catch (error) {
146
- console.log(chalk_1.default.red(`Error compiling code: ${error === null || error === void 0 ? void 0 : error.message}`));
158
+ console.log(chalk_1.default.red(`Error compiling code at ${filePath}`));
147
159
  return "";
148
160
  }
149
161
  };
@@ -172,12 +184,23 @@ class FileManager {
172
184
  traverseDirectory(fullPath);
173
185
  }
174
186
  else if (entry.isFile()) {
187
+ // skip các file trong thư mục bị ignore
188
+ if (ignoreFolders.some((folder) => fullPath.includes(folder))) {
189
+ return;
190
+ }
191
+ // chỉ hổ trợ các files nằm trong ./src
192
+ if (!fullPath.includes("/src/") && !fullPath.includes("\\src\\")) {
193
+ return;
194
+ }
175
195
  const content = fs.readFileSync(fullPath, { encoding: "utf8" });
176
- files.push({
177
- path: this.replaceSplashWithSeparator(fullPath.replace(this.basePath + path.sep, "./")),
178
- content,
179
- es5: (_a = (0, exports.compileES5)(content, fullPath)) !== null && _a !== void 0 ? _a : "",
180
- });
196
+ const extname = path.extname(fullPath);
197
+ if (supportedExtensions.includes(extname)) {
198
+ files.push({
199
+ path: this.replaceSplashWithSeparator(fullPath.replace(this.basePath + path.sep, "./")),
200
+ content,
201
+ es5: (_a = (0, exports.compileES5)(content, fullPath)) !== null && _a !== void 0 ? _a : "",
202
+ });
203
+ }
181
204
  }
182
205
  });
183
206
  };
@@ -371,12 +394,12 @@ class RoomState {
371
394
  return this.isConnected;
372
395
  }
373
396
  }
374
- commander_1.program.version("0.0.21").description("Hapico CLI for project management");
397
+ commander_1.program.version("0.0.23").description("Hapico CLI for project management");
375
398
  commander_1.program
376
399
  .command("clone <id>")
377
400
  .description("Clone a project by ID")
378
401
  .action(async (id) => {
379
- var _a, _b;
402
+ var _a, _b, _c, _d;
380
403
  const { accessToken } = getStoredToken();
381
404
  if (!accessToken) {
382
405
  console.error(chalk_1.default.red("✗ You need to login first. Use 'hapico login' command."));
@@ -390,11 +413,13 @@ commander_1.program
390
413
  let files = [];
391
414
  const apiSpinner = (0, ora_1.default)(chalk_1.default.blue("Fetching project data...")).start();
392
415
  try {
416
+ // ===== 1. Lấy version public/published (giữ nguyên như cũ) =====
393
417
  const response = await axios_1.default.get(`https://base.myworkbeast.com/api/views/${id}`);
394
418
  const code = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.code;
395
419
  const decompressedCode = pako_1.default.inflate(Uint8Array.from(atob(code), (c) => c.charCodeAt(0)), { to: "string" });
396
420
  files = ((_b = (0, exports.tryJSONParse)(decompressedCode)) === null || _b === void 0 ? void 0 : _b.files) || [];
397
421
  apiSpinner.succeed(chalk_1.default.green("Project data fetched successfully!"));
422
+ // ===== 2. Download + extract template =====
398
423
  const templateSpinner = (0, ora_1.default)(chalk_1.default.blue("Downloading template...")).start();
399
424
  const TEMPLATE_URL = "https://files.hcm04.vstorage.vngcloud.vn/assets/template_zalominiapp_devmode.zip";
400
425
  const templateResponse = await axios_1.default.get(TEMPLATE_URL, {
@@ -412,9 +437,10 @@ commander_1.program
412
437
  if (fs.existsSync(macosxDir)) {
413
438
  fs.rmSync(macosxDir, { recursive: true, force: true });
414
439
  }
415
- // Save project ID to hapico.config.json
440
+ // Save project ID
416
441
  saveProjectId(outputDir, id);
417
442
  console.log(chalk_1.default.green("Project cloned successfully!"));
443
+ // ===== 3. Save file từ version public =====
418
444
  const saveSpinner = (0, ora_1.default)(chalk_1.default.blue("Saving project files...")).start();
419
445
  files.forEach((file) => {
420
446
  const filePath = path.join(process.cwd(), id, "src", file.path);
@@ -425,6 +451,31 @@ commander_1.program
425
451
  fs.writeFileSync(filePath, file.content);
426
452
  });
427
453
  saveSpinner.succeed(chalk_1.default.green("Project files saved successfully!"));
454
+ // ===== 4. TỰ ĐỘNG PULL PHIÊN BẢN MỚI NHẤT (draft) – ĐÂY LÀ PHẦN MỚI =====
455
+ const pullSpinner = (0, ora_1.default)(chalk_1.default.blue("Pulling latest changes from server...")).start();
456
+ try {
457
+ const pullResponse = await axios_1.default.get(`https://base.myworkbeast.com/api/views/v3/${id}`, {
458
+ headers: {
459
+ Authorization: `Bearer ${accessToken}`,
460
+ "Content-Type": "application/json",
461
+ },
462
+ });
463
+ const pullCode = (_c = pullResponse === null || pullResponse === void 0 ? void 0 : pullResponse.data) === null || _c === void 0 ? void 0 : _c.code;
464
+ if (!pullCode) {
465
+ pullSpinner.info(chalk_1.default.cyan("No draft version found – using published version."));
466
+ }
467
+ else {
468
+ const pullDecompressed = pako_1.default.inflate(Uint8Array.from(atob(pullCode), (c) => c.charCodeAt(0)), { to: "string" });
469
+ const latestFiles = ((_d = (0, exports.tryJSONParse)(pullDecompressed)) === null || _d === void 0 ? void 0 : _d.files) || [];
470
+ const fileManager = new FileManager(path.join(outputDir, "src"));
471
+ fileManager.syncFiles(latestFiles);
472
+ pullSpinner.succeed(chalk_1.default.green("✓ Latest changes pulled successfully!"));
473
+ }
474
+ }
475
+ catch (pullErr) {
476
+ pullSpinner.warn(chalk_1.default.yellow(`⚠ Could not pull latest changes: ${pullErr.message}\n Run "hapico pull" manually later.`));
477
+ }
478
+ // ===== 5. Hướng dẫn chạy dev =====
428
479
  console.log(chalk_1.default.cyan(`💡 Run ${chalk_1.default.bold("cd ${id} && npm install && hapico dev")} to start the project.`));
429
480
  }
430
481
  catch (error) {
@@ -434,7 +485,7 @@ commander_1.program
434
485
  commander_1.program
435
486
  .command("dev")
436
487
  .description("Start the project in development mode")
437
- .option('--zversion <version>', 'Zalo version for QR code', '75')
488
+ .option("--zversion <version>", "Zalo version for QR code")
438
489
  .action((options) => {
439
490
  var _a;
440
491
  const { accessToken } = getStoredToken();
@@ -507,19 +558,10 @@ commander_1.program
507
558
  ".jsx",
508
559
  ".json",
509
560
  ".css",
510
- ".html",
511
561
  ".env",
512
562
  ".env.local",
513
563
  ".env.development",
514
564
  ".env.production",
515
- ".jsonc",
516
- ".yml",
517
- ".yaml",
518
- ".md",
519
- ".markdown",
520
- ".txt",
521
- ".xml",
522
- ".config",
523
565
  ];
524
566
  const filteredFiles = initialFiles.filter((file) => {
525
567
  return supportExtensions.some((ext) => file.path.endsWith(ext));
@@ -558,12 +600,21 @@ commander_1.program
558
600
  return;
559
601
  }
560
602
  const projectType = project.data.type || "view";
561
- const zversion = options.zversion || '75';
603
+ const zversion = options.zversion;
562
604
  if (projectType === "zalominiapp") {
563
- qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`, { small: true }, (qrcode) => {
564
- console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
565
- console.log(qrcode);
566
- });
605
+ console.log("zversion", zversion);
606
+ if (!zversion) {
607
+ qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}`, { small: true }, (qrcode) => {
608
+ console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
609
+ console.log(qrcode);
610
+ });
611
+ }
612
+ else {
613
+ qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`, { small: true }, (qrcode) => {
614
+ console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
615
+ console.log(qrcode);
616
+ });
617
+ }
567
618
  return;
568
619
  }
569
620
  else {
package/dist/index.js CHANGED
@@ -123,6 +123,18 @@ const tryJSONParse = (str) => {
123
123
  }
124
124
  };
125
125
  exports.tryJSONParse = tryJSONParse;
126
+ // only support .ts, .tsx, .js, .jsx, .json, .css, .html, .env files
127
+ const supportedExtensions = [
128
+ ".ts",
129
+ ".tsx",
130
+ ".js",
131
+ ".jsx",
132
+ ".json",
133
+ ".css",
134
+ ".html",
135
+ ".env",
136
+ ];
137
+ const ignoreFolders = ["node_modules", ".git", ".hg", ".svn"];
126
138
  const compileES5 = (code, filePath) => {
127
139
  if (filePath && !filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
128
140
  return code;
@@ -143,7 +155,7 @@ const compileES5 = (code, filePath) => {
143
155
  return result.code;
144
156
  }
145
157
  catch (error) {
146
- console.log(chalk_1.default.red(`Error compiling code: ${error === null || error === void 0 ? void 0 : error.message}`));
158
+ console.log(chalk_1.default.red(`Error compiling code at ${filePath}`));
147
159
  return "";
148
160
  }
149
161
  };
@@ -172,12 +184,23 @@ class FileManager {
172
184
  traverseDirectory(fullPath);
173
185
  }
174
186
  else if (entry.isFile()) {
187
+ // skip các file trong thư mục bị ignore
188
+ if (ignoreFolders.some((folder) => fullPath.includes(folder))) {
189
+ return;
190
+ }
191
+ // chỉ hổ trợ các files nằm trong ./src
192
+ if (!fullPath.includes("/src/") && !fullPath.includes("\\src\\")) {
193
+ return;
194
+ }
175
195
  const content = fs.readFileSync(fullPath, { encoding: "utf8" });
176
- files.push({
177
- path: this.replaceSplashWithSeparator(fullPath.replace(this.basePath + path.sep, "./")),
178
- content,
179
- es5: (_a = (0, exports.compileES5)(content, fullPath)) !== null && _a !== void 0 ? _a : "",
180
- });
196
+ const extname = path.extname(fullPath);
197
+ if (supportedExtensions.includes(extname)) {
198
+ files.push({
199
+ path: this.replaceSplashWithSeparator(fullPath.replace(this.basePath + path.sep, "./")),
200
+ content,
201
+ es5: (_a = (0, exports.compileES5)(content, fullPath)) !== null && _a !== void 0 ? _a : "",
202
+ });
203
+ }
181
204
  }
182
205
  });
183
206
  };
@@ -371,12 +394,12 @@ class RoomState {
371
394
  return this.isConnected;
372
395
  }
373
396
  }
374
- commander_1.program.version("0.0.21").description("Hapico CLI for project management");
397
+ commander_1.program.version("0.0.23").description("Hapico CLI for project management");
375
398
  commander_1.program
376
399
  .command("clone <id>")
377
400
  .description("Clone a project by ID")
378
401
  .action(async (id) => {
379
- var _a, _b;
402
+ var _a, _b, _c, _d;
380
403
  const { accessToken } = getStoredToken();
381
404
  if (!accessToken) {
382
405
  console.error(chalk_1.default.red("✗ You need to login first. Use 'hapico login' command."));
@@ -390,11 +413,13 @@ commander_1.program
390
413
  let files = [];
391
414
  const apiSpinner = (0, ora_1.default)(chalk_1.default.blue("Fetching project data...")).start();
392
415
  try {
416
+ // ===== 1. Lấy version public/published (giữ nguyên như cũ) =====
393
417
  const response = await axios_1.default.get(`https://base.myworkbeast.com/api/views/${id}`);
394
418
  const code = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.code;
395
419
  const decompressedCode = pako_1.default.inflate(Uint8Array.from(atob(code), (c) => c.charCodeAt(0)), { to: "string" });
396
420
  files = ((_b = (0, exports.tryJSONParse)(decompressedCode)) === null || _b === void 0 ? void 0 : _b.files) || [];
397
421
  apiSpinner.succeed(chalk_1.default.green("Project data fetched successfully!"));
422
+ // ===== 2. Download + extract template =====
398
423
  const templateSpinner = (0, ora_1.default)(chalk_1.default.blue("Downloading template...")).start();
399
424
  const TEMPLATE_URL = "https://files.hcm04.vstorage.vngcloud.vn/assets/template_zalominiapp_devmode.zip";
400
425
  const templateResponse = await axios_1.default.get(TEMPLATE_URL, {
@@ -412,9 +437,10 @@ commander_1.program
412
437
  if (fs.existsSync(macosxDir)) {
413
438
  fs.rmSync(macosxDir, { recursive: true, force: true });
414
439
  }
415
- // Save project ID to hapico.config.json
440
+ // Save project ID
416
441
  saveProjectId(outputDir, id);
417
442
  console.log(chalk_1.default.green("Project cloned successfully!"));
443
+ // ===== 3. Save file từ version public =====
418
444
  const saveSpinner = (0, ora_1.default)(chalk_1.default.blue("Saving project files...")).start();
419
445
  files.forEach((file) => {
420
446
  const filePath = path.join(process.cwd(), id, "src", file.path);
@@ -425,6 +451,31 @@ commander_1.program
425
451
  fs.writeFileSync(filePath, file.content);
426
452
  });
427
453
  saveSpinner.succeed(chalk_1.default.green("Project files saved successfully!"));
454
+ // ===== 4. TỰ ĐỘNG PULL PHIÊN BẢN MỚI NHẤT (draft) – ĐÂY LÀ PHẦN MỚI =====
455
+ const pullSpinner = (0, ora_1.default)(chalk_1.default.blue("Pulling latest changes from server...")).start();
456
+ try {
457
+ const pullResponse = await axios_1.default.get(`https://base.myworkbeast.com/api/views/v3/${id}`, {
458
+ headers: {
459
+ Authorization: `Bearer ${accessToken}`,
460
+ "Content-Type": "application/json",
461
+ },
462
+ });
463
+ const pullCode = (_c = pullResponse === null || pullResponse === void 0 ? void 0 : pullResponse.data) === null || _c === void 0 ? void 0 : _c.code;
464
+ if (!pullCode) {
465
+ pullSpinner.info(chalk_1.default.cyan("No draft version found – using published version."));
466
+ }
467
+ else {
468
+ const pullDecompressed = pako_1.default.inflate(Uint8Array.from(atob(pullCode), (c) => c.charCodeAt(0)), { to: "string" });
469
+ const latestFiles = ((_d = (0, exports.tryJSONParse)(pullDecompressed)) === null || _d === void 0 ? void 0 : _d.files) || [];
470
+ const fileManager = new FileManager(path.join(outputDir, "src"));
471
+ fileManager.syncFiles(latestFiles);
472
+ pullSpinner.succeed(chalk_1.default.green("✓ Latest changes pulled successfully!"));
473
+ }
474
+ }
475
+ catch (pullErr) {
476
+ pullSpinner.warn(chalk_1.default.yellow(`⚠ Could not pull latest changes: ${pullErr.message}\n Run "hapico pull" manually later.`));
477
+ }
478
+ // ===== 5. Hướng dẫn chạy dev =====
428
479
  console.log(chalk_1.default.cyan(`💡 Run ${chalk_1.default.bold("cd ${id} && npm install && hapico dev")} to start the project.`));
429
480
  }
430
481
  catch (error) {
@@ -434,7 +485,7 @@ commander_1.program
434
485
  commander_1.program
435
486
  .command("dev")
436
487
  .description("Start the project in development mode")
437
- .option('--zversion <version>', 'Zalo version for QR code', '75')
488
+ .option("--zversion <version>", "Zalo version for QR code")
438
489
  .action((options) => {
439
490
  var _a;
440
491
  const { accessToken } = getStoredToken();
@@ -507,19 +558,10 @@ commander_1.program
507
558
  ".jsx",
508
559
  ".json",
509
560
  ".css",
510
- ".html",
511
561
  ".env",
512
562
  ".env.local",
513
563
  ".env.development",
514
564
  ".env.production",
515
- ".jsonc",
516
- ".yml",
517
- ".yaml",
518
- ".md",
519
- ".markdown",
520
- ".txt",
521
- ".xml",
522
- ".config",
523
565
  ];
524
566
  const filteredFiles = initialFiles.filter((file) => {
525
567
  return supportExtensions.some((ext) => file.path.endsWith(ext));
@@ -558,12 +600,21 @@ commander_1.program
558
600
  return;
559
601
  }
560
602
  const projectType = project.data.type || "view";
561
- const zversion = options.zversion || '75';
603
+ const zversion = options.zversion;
562
604
  if (projectType === "zalominiapp") {
563
- qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`, { small: true }, (qrcode) => {
564
- console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
565
- console.log(qrcode);
566
- });
605
+ console.log("zversion", zversion);
606
+ if (!zversion) {
607
+ qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}`, { small: true }, (qrcode) => {
608
+ console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
609
+ console.log(qrcode);
610
+ });
611
+ }
612
+ else {
613
+ qrcode_terminal_1.default.generate(`https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`, { small: true }, (qrcode) => {
614
+ console.log(chalk_1.default.cyan("📱 Scan this QR code to connect to the project:"));
615
+ console.log(qrcode);
616
+ });
617
+ }
567
618
  return;
568
619
  }
569
620
  else {
package/index.ts CHANGED
@@ -130,6 +130,20 @@ export const tryJSONParse = (str: string): any => {
130
130
  }
131
131
  };
132
132
 
133
+ // only support .ts, .tsx, .js, .jsx, .json, .css, .html, .env files
134
+ const supportedExtensions = [
135
+ ".ts",
136
+ ".tsx",
137
+ ".js",
138
+ ".jsx",
139
+ ".json",
140
+ ".css",
141
+ ".html",
142
+ ".env",
143
+ ];
144
+
145
+ const ignoreFolders = ["node_modules", ".git", ".hg", ".svn"];
146
+
133
147
  export const compileES5 = (code: string, filePath?: string) => {
134
148
  if (filePath && !filePath.endsWith(".ts") && !filePath.endsWith(".tsx")) {
135
149
  return code;
@@ -151,7 +165,7 @@ export const compileES5 = (code: string, filePath?: string) => {
151
165
  compileCache.set(code, result.code || "");
152
166
  return result.code;
153
167
  } catch (error: any) {
154
- console.log(chalk.red(`Error compiling code: ${error?.message}`));
168
+ console.log(chalk.red(`Error compiling code at ${filePath}`));
155
169
  return "";
156
170
  }
157
171
  };
@@ -188,14 +202,27 @@ class FileManager {
188
202
  if (entry.isDirectory()) {
189
203
  traverseDirectory(fullPath);
190
204
  } else if (entry.isFile()) {
205
+ // skip các file trong thư mục bị ignore
206
+ if (ignoreFolders.some((folder) => fullPath.includes(folder))) {
207
+ return;
208
+ }
209
+
210
+ // chỉ hổ trợ các files nằm trong ./src
211
+ if (!fullPath.includes("/src/") && !fullPath.includes("\\src\\")) {
212
+ return;
213
+ }
214
+
191
215
  const content = fs.readFileSync(fullPath, { encoding: "utf8" });
192
- files.push({
193
- path: this.replaceSplashWithSeparator(
194
- fullPath.replace(this.basePath + path.sep, "./")
195
- ),
196
- content,
197
- es5: compileES5(content, fullPath) ?? "",
198
- });
216
+ const extname = path.extname(fullPath);
217
+ if (supportedExtensions.includes(extname)) {
218
+ files.push({
219
+ path: this.replaceSplashWithSeparator(
220
+ fullPath.replace(this.basePath + path.sep, "./")
221
+ ),
222
+ content,
223
+ es5: compileES5(content, fullPath) ?? "",
224
+ });
225
+ }
199
226
  }
200
227
  });
201
228
  };
@@ -447,7 +474,7 @@ class RoomState {
447
474
  }
448
475
  }
449
476
 
450
- program.version("0.0.21").description("Hapico CLI for project management");
477
+ program.version("0.0.23").description("Hapico CLI for project management");
451
478
 
452
479
  program
453
480
  .command("clone <id>")
@@ -470,17 +497,19 @@ program
470
497
  const apiSpinner: Ora = ora(chalk.blue("Fetching project data...")).start();
471
498
 
472
499
  try {
500
+ // ===== 1. Lấy version public/published (giữ nguyên như cũ) =====
473
501
  const response: ApiResponse = await axios.get(
474
502
  `https://base.myworkbeast.com/api/views/${id}`
475
503
  );
476
504
  const code = response?.data?.code;
477
505
  const decompressedCode = pako.inflate(
478
- Uint8Array.from(atob(code), (c) => c.charCodeAt(0)),
506
+ Uint8Array.from(atob(code), (c) => c.charCodeAt(0)),
479
507
  { to: "string" }
480
508
  );
481
509
  files = tryJSONParse(decompressedCode)?.files || [];
482
510
  apiSpinner.succeed(chalk.green("Project data fetched successfully!"));
483
511
 
512
+ // ===== 2. Download + extract template =====
484
513
  const templateSpinner: Ora = ora(
485
514
  chalk.blue("Downloading template...")
486
515
  ).start();
@@ -509,11 +538,11 @@ program
509
538
  fs.rmSync(macosxDir, { recursive: true, force: true });
510
539
  }
511
540
 
512
- // Save project ID to hapico.config.json
541
+ // Save project ID
513
542
  saveProjectId(outputDir, id);
514
-
515
543
  console.log(chalk.green("Project cloned successfully!"));
516
544
 
545
+ // ===== 3. Save file từ version public =====
517
546
  const saveSpinner: Ora = ora(
518
547
  chalk.blue("Saving project files...")
519
548
  ).start();
@@ -528,6 +557,52 @@ program
528
557
  fs.writeFileSync(filePath, file.content);
529
558
  });
530
559
  saveSpinner.succeed(chalk.green("Project files saved successfully!"));
560
+
561
+ // ===== 4. TỰ ĐỘNG PULL PHIÊN BẢN MỚI NHẤT (draft) – ĐÂY LÀ PHẦN MỚI =====
562
+ const pullSpinner: Ora = ora(
563
+ chalk.blue("Pulling latest changes from server...")
564
+ ).start();
565
+
566
+ try {
567
+ const pullResponse = await axios.get(
568
+ `https://base.myworkbeast.com/api/views/v3/${id}`,
569
+ {
570
+ headers: {
571
+ Authorization: `Bearer ${accessToken}`,
572
+ "Content-Type": "application/json",
573
+ },
574
+ }
575
+ );
576
+
577
+ const pullCode = pullResponse?.data?.code;
578
+ if (!pullCode) {
579
+ pullSpinner.info(
580
+ chalk.cyan("No draft version found – using published version.")
581
+ );
582
+ } else {
583
+ const pullDecompressed = pako.inflate(
584
+ Uint8Array.from(atob(pullCode), (c) => c.charCodeAt(0)),
585
+ { to: "string" }
586
+ );
587
+ const latestFiles: FileContent[] =
588
+ tryJSONParse(pullDecompressed)?.files || [];
589
+
590
+ const fileManager = new FileManager(path.join(outputDir, "src"));
591
+ fileManager.syncFiles(latestFiles);
592
+
593
+ pullSpinner.succeed(
594
+ chalk.green("✓ Latest changes pulled successfully!")
595
+ );
596
+ }
597
+ } catch (pullErr: any) {
598
+ pullSpinner.warn(
599
+ chalk.yellow(
600
+ `⚠ Could not pull latest changes: ${pullErr.message}\n Run "hapico pull" manually later.`
601
+ )
602
+ );
603
+ }
604
+
605
+ // ===== 5. Hướng dẫn chạy dev =====
531
606
  console.log(
532
607
  chalk.cyan(
533
608
  `💡 Run ${chalk.bold("cd ${id} && npm install && hapico dev")} to start the project.`
@@ -541,7 +616,7 @@ program
541
616
  program
542
617
  .command("dev")
543
618
  .description("Start the project in development mode")
544
- .option('--zversion <version>', 'Zalo version for QR code', '75')
619
+ .option("--zversion <version>", "Zalo version for QR code")
545
620
  .action((options) => {
546
621
  const { accessToken } = getStoredToken();
547
622
  if (!accessToken) {
@@ -637,19 +712,10 @@ program
637
712
  ".jsx",
638
713
  ".json",
639
714
  ".css",
640
- ".html",
641
715
  ".env",
642
716
  ".env.local",
643
717
  ".env.development",
644
718
  ".env.production",
645
- ".jsonc",
646
- ".yml",
647
- ".yaml",
648
- ".md",
649
- ".markdown",
650
- ".txt",
651
- ".xml",
652
- ".config",
653
719
  ];
654
720
  const filteredFiles = initialFiles.filter((file) => {
655
721
  return supportExtensions.some((ext) => file.path.endsWith(ext));
@@ -705,19 +771,33 @@ program
705
771
  }
706
772
 
707
773
  const projectType = project.data.type || "view";
708
- const zversion = options.zversion || '75';
774
+ const zversion = options.zversion;
709
775
 
710
776
  if (projectType === "zalominiapp") {
711
- QRCode.generate(
712
- `https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`,
713
- { small: true },
714
- (qrcode) => {
715
- console.log(
716
- chalk.cyan("📱 Scan this QR code to connect to the project:")
717
- );
718
- console.log(qrcode);
719
- }
720
- );
777
+ console.log("zversion", zversion);
778
+ if (!zversion) {
779
+ QRCode.generate(
780
+ `https://zalo.me/s/3218692650896662017/player/${projectId}`,
781
+ { small: true },
782
+ (qrcode) => {
783
+ console.log(
784
+ chalk.cyan("📱 Scan this QR code to connect to the project:")
785
+ );
786
+ console.log(qrcode);
787
+ }
788
+ );
789
+ } else {
790
+ QRCode.generate(
791
+ `https://zalo.me/s/3218692650896662017/player/${projectId}?env=TESTING&version=${zversion}`,
792
+ { small: true },
793
+ (qrcode) => {
794
+ console.log(
795
+ chalk.cyan("📱 Scan this QR code to connect to the project:")
796
+ );
797
+ console.log(qrcode);
798
+ }
799
+ );
800
+ }
721
801
  return;
722
802
  } else {
723
803
  const previewUrl = `https://com.ai.vn/dev_preview/${projectId}`;
@@ -1490,4 +1570,4 @@ ${file.content}
1490
1570
  console.log(chalk.green(`✓ File list saved to ${outputFile}`));
1491
1571
  });
1492
1572
 
1493
- program.parse(process.argv);
1573
+ program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hapico/cli",
3
- "version": "0.0.21",
3
+ "version": "0.0.23",
4
4
  "description": "A simple CLI tool for project management",
5
5
  "main": "index.js",
6
6
  "bin": {