@jvittechs/jai1-cli 0.1.78 → 0.1.80
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/dist/cli.js +563 -171
- package/dist/cli.js.map +1 -1
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command45 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/errors/index.ts
|
|
7
7
|
var Jai1Error = class extends Error {
|
|
@@ -33,7 +33,7 @@ var NetworkError = class extends Jai1Error {
|
|
|
33
33
|
// package.json
|
|
34
34
|
var package_default = {
|
|
35
35
|
name: "@jvittechs/jai1-cli",
|
|
36
|
-
version: "0.1.
|
|
36
|
+
version: "0.1.80",
|
|
37
37
|
description: "A unified CLI tool for JV-IT TECHS developers to manage Jai1 Framework. Please contact TeamAI for usage instructions.",
|
|
38
38
|
type: "module",
|
|
39
39
|
bin: {
|
|
@@ -85,6 +85,7 @@ var package_default = {
|
|
|
85
85
|
clipboardy: "^4.0.0",
|
|
86
86
|
commander: "^12.1.0",
|
|
87
87
|
cronstrue: "^2.50.0",
|
|
88
|
+
execa: "^9.6.1",
|
|
88
89
|
"gray-matter": "^4.0.3",
|
|
89
90
|
ink: "^5.0.1",
|
|
90
91
|
"ink-spinner": "^5.0.0",
|
|
@@ -894,9 +895,9 @@ var UnifiedApplyApp = ({
|
|
|
894
895
|
(c) => c.filepath.toLowerCase().includes(query) || c.name.toLowerCase().includes(query) || c.tags && c.tags.some((t) => t.toLowerCase().includes(query))
|
|
895
896
|
);
|
|
896
897
|
}, [components, searchQuery]);
|
|
897
|
-
useInput((
|
|
898
|
+
useInput((input2, key) => {
|
|
898
899
|
if (viewState === "summary") {
|
|
899
|
-
if (key.return ||
|
|
900
|
+
if (key.return || input2 === "q" || key.escape) {
|
|
900
901
|
onExit();
|
|
901
902
|
}
|
|
902
903
|
return;
|
|
@@ -910,7 +911,7 @@ var UnifiedApplyApp = ({
|
|
|
910
911
|
else setFocusArea("search");
|
|
911
912
|
return;
|
|
912
913
|
}
|
|
913
|
-
if (key.escape ||
|
|
914
|
+
if (key.escape || input2 === "q") {
|
|
914
915
|
onExit();
|
|
915
916
|
return;
|
|
916
917
|
}
|
|
@@ -925,7 +926,7 @@ var UnifiedApplyApp = ({
|
|
|
925
926
|
setCursorIndex((prev) => Math.max(0, prev - 1));
|
|
926
927
|
} else if (key.downArrow) {
|
|
927
928
|
setCursorIndex((prev) => Math.min(filteredComponents.length - 1, prev + 1));
|
|
928
|
-
} else if (
|
|
929
|
+
} else if (input2 === " ") {
|
|
929
930
|
const current = filteredComponents[cursorIndex];
|
|
930
931
|
if (current) {
|
|
931
932
|
setSelectedPaths((prev) => {
|
|
@@ -938,13 +939,13 @@ var UnifiedApplyApp = ({
|
|
|
938
939
|
return next;
|
|
939
940
|
});
|
|
940
941
|
}
|
|
941
|
-
} else if (
|
|
942
|
+
} else if (input2 === "a") {
|
|
942
943
|
setSelectedPaths((prev) => {
|
|
943
944
|
const next = new Set(prev);
|
|
944
945
|
filteredComponents.forEach((c) => next.add(c.filepath));
|
|
945
946
|
return next;
|
|
946
947
|
});
|
|
947
|
-
} else if (
|
|
948
|
+
} else if (input2 === "c") {
|
|
948
949
|
setSelectedPaths(/* @__PURE__ */ new Set());
|
|
949
950
|
}
|
|
950
951
|
}
|
|
@@ -953,7 +954,7 @@ var UnifiedApplyApp = ({
|
|
|
953
954
|
setSelectedPackageIndex((prev) => Math.max(0, prev - 1));
|
|
954
955
|
} else if (key.rightArrow) {
|
|
955
956
|
setSelectedPackageIndex((prev) => Math.min(tags.length - 1, prev + 1));
|
|
956
|
-
} else if (
|
|
957
|
+
} else if (input2 === " " || key.return) {
|
|
957
958
|
const tag = tags[selectedPackageIndex];
|
|
958
959
|
if (tag) {
|
|
959
960
|
const packageComponents = components.filter((c) => c.tags?.includes(tag.tag));
|
|
@@ -1331,7 +1332,7 @@ var MainMenuView = ({ ideContexts, onSelect }) => {
|
|
|
1331
1332
|
available: ideContexts.some((ctx) => ctx.ide === "jai1")
|
|
1332
1333
|
}
|
|
1333
1334
|
];
|
|
1334
|
-
useInput2((
|
|
1335
|
+
useInput2((input2, key) => {
|
|
1335
1336
|
if (key.upArrow) {
|
|
1336
1337
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
1337
1338
|
} else if (key.downArrow) {
|
|
@@ -1433,13 +1434,13 @@ var IDEOverviewView = ({
|
|
|
1433
1434
|
count: ideContext.stats.byType.context
|
|
1434
1435
|
});
|
|
1435
1436
|
}
|
|
1436
|
-
useInput3((
|
|
1437
|
+
useInput3((input2, key) => {
|
|
1437
1438
|
if (key.tab || key.rightArrow) {
|
|
1438
1439
|
setSelectedTabIndex((prev) => Math.min(tabs.length - 1, prev + 1));
|
|
1439
1440
|
} else if (key.leftArrow) {
|
|
1440
1441
|
setSelectedTabIndex((prev) => Math.max(0, prev - 1));
|
|
1441
1442
|
}
|
|
1442
|
-
const num = parseInt(
|
|
1443
|
+
const num = parseInt(input2, 10);
|
|
1443
1444
|
if (!isNaN(num) && num >= 1 && num <= tabs.length) {
|
|
1444
1445
|
setSelectedTabIndex(num - 1);
|
|
1445
1446
|
}
|
|
@@ -1501,7 +1502,7 @@ import React7, { useState as useState4 } from "react";
|
|
|
1501
1502
|
import { Box as Box5, Text as Text6, useInput as useInput4 } from "ink";
|
|
1502
1503
|
var ListView = ({ items, contentType, onSelect, onBack }) => {
|
|
1503
1504
|
const [selectedIndex, setSelectedIndex] = useState4(0);
|
|
1504
|
-
useInput4((
|
|
1505
|
+
useInput4((input2, key) => {
|
|
1505
1506
|
if (key.upArrow) {
|
|
1506
1507
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
1507
1508
|
} else if (key.downArrow) {
|
|
@@ -1552,18 +1553,18 @@ var DetailView = ({ item, scrollPosition: initialScroll, onBack }) => {
|
|
|
1552
1553
|
const [scrollPosition, setScrollPosition] = useState5(initialScroll);
|
|
1553
1554
|
const maxVisibleLines = 25;
|
|
1554
1555
|
const maxScroll = Math.max(0, item.previewLines.length - maxVisibleLines);
|
|
1555
|
-
useInput5((
|
|
1556
|
-
if (key.upArrow ||
|
|
1556
|
+
useInput5((input2, key) => {
|
|
1557
|
+
if (key.upArrow || input2 === "k") {
|
|
1557
1558
|
setScrollPosition((prev) => Math.max(0, prev - 1));
|
|
1558
|
-
} else if (key.downArrow ||
|
|
1559
|
+
} else if (key.downArrow || input2 === "j") {
|
|
1559
1560
|
setScrollPosition((prev) => Math.min(maxScroll, prev + 1));
|
|
1560
|
-
} else if (key.pageDown ||
|
|
1561
|
+
} else if (key.pageDown || input2 === "d") {
|
|
1561
1562
|
setScrollPosition((prev) => Math.min(maxScroll, prev + 5));
|
|
1562
|
-
} else if (key.pageUp ||
|
|
1563
|
+
} else if (key.pageUp || input2 === "u") {
|
|
1563
1564
|
setScrollPosition((prev) => Math.max(0, prev - 5));
|
|
1564
|
-
} else if (
|
|
1565
|
+
} else if (input2 === "g") {
|
|
1565
1566
|
setScrollPosition(0);
|
|
1566
|
-
} else if (
|
|
1567
|
+
} else if (input2 === "G") {
|
|
1567
1568
|
setScrollPosition(maxScroll);
|
|
1568
1569
|
} else if (key.escape || key.backspace) {
|
|
1569
1570
|
onBack();
|
|
@@ -1959,8 +1960,8 @@ var ContextApp = ({ initialIDE, initialType, onExit }) => {
|
|
|
1959
1960
|
setLoading(false);
|
|
1960
1961
|
});
|
|
1961
1962
|
}, [initialIDE]);
|
|
1962
|
-
useInput6((
|
|
1963
|
-
if (
|
|
1963
|
+
useInput6((input2, key) => {
|
|
1964
|
+
if (input2 === "q") {
|
|
1964
1965
|
onExit();
|
|
1965
1966
|
return;
|
|
1966
1967
|
}
|
|
@@ -2887,7 +2888,7 @@ var MENU_ITEMS = [
|
|
|
2887
2888
|
];
|
|
2888
2889
|
var MenuView = ({ onSelect }) => {
|
|
2889
2890
|
const [selectedIndex, setSelectedIndex] = useState7(0);
|
|
2890
|
-
useInput7((
|
|
2891
|
+
useInput7((input2, key) => {
|
|
2891
2892
|
if (key.upArrow) {
|
|
2892
2893
|
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
2893
2894
|
} else if (key.downArrow) {
|
|
@@ -3500,7 +3501,7 @@ var AgenticGuideView = ({ onBack }) => {
|
|
|
3500
3501
|
const [isTyping, setIsTyping] = useState8(false);
|
|
3501
3502
|
const [selectedSuggestion, setSelectedSuggestion] = useState8(0);
|
|
3502
3503
|
const [focusArea, setFocusArea] = useState8("input");
|
|
3503
|
-
useInput8((
|
|
3504
|
+
useInput8((input2, key) => {
|
|
3504
3505
|
if (key.escape) {
|
|
3505
3506
|
onBack();
|
|
3506
3507
|
return;
|
|
@@ -3632,7 +3633,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
3632
3633
|
setCurrentTopic(TOPIC_MAP[initialTopic]);
|
|
3633
3634
|
}
|
|
3634
3635
|
}, [initialTopic]);
|
|
3635
|
-
useInput9((
|
|
3636
|
+
useInput9((input2, key) => {
|
|
3636
3637
|
if (key.escape || currentTopic !== "menu" && key.backspace) {
|
|
3637
3638
|
if (currentTopic === "menu") {
|
|
3638
3639
|
onExit();
|
|
@@ -3642,7 +3643,7 @@ var GuideApp = ({ initialTopic, onExit }) => {
|
|
|
3642
3643
|
}
|
|
3643
3644
|
return;
|
|
3644
3645
|
}
|
|
3645
|
-
if (
|
|
3646
|
+
if (input2 === "q") {
|
|
3646
3647
|
onExit();
|
|
3647
3648
|
return;
|
|
3648
3649
|
}
|
|
@@ -4141,7 +4142,7 @@ var ModelSelector = ({
|
|
|
4141
4142
|
const allowedModels = models.filter((m) => m.allowed);
|
|
4142
4143
|
const currentIndex = allowedModels.findIndex((m) => m.id === currentModel);
|
|
4143
4144
|
const [selectedIndex, setSelectedIndex] = useState12(Math.max(0, currentIndex));
|
|
4144
|
-
useInput10((
|
|
4145
|
+
useInput10((input2, key) => {
|
|
4145
4146
|
if (key.escape) {
|
|
4146
4147
|
onCancel();
|
|
4147
4148
|
return;
|
|
@@ -4267,7 +4268,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
4267
4268
|
}
|
|
4268
4269
|
return false;
|
|
4269
4270
|
}, [refetch, exit]);
|
|
4270
|
-
useInput11((
|
|
4271
|
+
useInput11((input2, key) => {
|
|
4271
4272
|
if (showSlashMenu) {
|
|
4272
4273
|
if (key.upArrow) {
|
|
4273
4274
|
setSlashMenuIndex((i) => Math.max(0, i - 1));
|
|
@@ -4295,7 +4296,7 @@ var ChatApp = ({ service, initialModel }) => {
|
|
|
4295
4296
|
}
|
|
4296
4297
|
return;
|
|
4297
4298
|
}
|
|
4298
|
-
if (currentView === "error" && (key.return ||
|
|
4299
|
+
if (currentView === "error" && (key.return || input2 === "r")) {
|
|
4299
4300
|
setCurrentView("loading");
|
|
4300
4301
|
refetch();
|
|
4301
4302
|
return;
|
|
@@ -4550,9 +4551,9 @@ var TranslationService = class {
|
|
|
4550
4551
|
/**
|
|
4551
4552
|
* Detect input type
|
|
4552
4553
|
*/
|
|
4553
|
-
async detectInputType(
|
|
4554
|
+
async detectInputType(input2) {
|
|
4554
4555
|
try {
|
|
4555
|
-
const stat = await fs7.stat(
|
|
4556
|
+
const stat = await fs7.stat(input2);
|
|
4556
4557
|
if (stat.isDirectory()) return "folder";
|
|
4557
4558
|
if (stat.isFile()) return "file";
|
|
4558
4559
|
} catch {
|
|
@@ -4784,7 +4785,7 @@ Return ONLY the translated content, no explanations.`;
|
|
|
4784
4785
|
};
|
|
4785
4786
|
|
|
4786
4787
|
// src/commands/translate.ts
|
|
4787
|
-
async function handleTranslate(
|
|
4788
|
+
async function handleTranslate(input2, options) {
|
|
4788
4789
|
const configService = new ConfigService();
|
|
4789
4790
|
const config = await configService.load();
|
|
4790
4791
|
if (!config) {
|
|
@@ -4792,16 +4793,16 @@ async function handleTranslate(input, options) {
|
|
|
4792
4793
|
}
|
|
4793
4794
|
const llmService = new LlmProxyService(config);
|
|
4794
4795
|
const translationService = new TranslationService(llmService, options, options.model);
|
|
4795
|
-
const inputType = await translationService.detectInputType(
|
|
4796
|
+
const inputType = await translationService.detectInputType(input2);
|
|
4796
4797
|
switch (inputType) {
|
|
4797
4798
|
case "text":
|
|
4798
|
-
await handleTextTranslation(translationService,
|
|
4799
|
+
await handleTextTranslation(translationService, input2, options);
|
|
4799
4800
|
break;
|
|
4800
4801
|
case "file":
|
|
4801
|
-
await handleFileTranslation(translationService,
|
|
4802
|
+
await handleFileTranslation(translationService, input2, options);
|
|
4802
4803
|
break;
|
|
4803
4804
|
case "folder":
|
|
4804
|
-
await handleFolderTranslation(translationService,
|
|
4805
|
+
await handleFolderTranslation(translationService, input2, options);
|
|
4805
4806
|
break;
|
|
4806
4807
|
}
|
|
4807
4808
|
}
|
|
@@ -4878,8 +4879,8 @@ async function handleFolderTranslation(service, folderPath, options) {
|
|
|
4878
4879
|
}
|
|
4879
4880
|
}
|
|
4880
4881
|
function createTranslateCommand() {
|
|
4881
|
-
const cmd = new Command14("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (
|
|
4882
|
-
await handleTranslate(
|
|
4882
|
+
const cmd = new Command14("translate").description("D\u1ECBch v\u0103n b\u1EA3n, file ho\u1EB7c th\u01B0 m\u1EE5c b\u1EB1ng AI").argument("<input>", "Chu\u1ED7i v\u0103n b\u1EA3n, \u0111\u01B0\u1EDDng d\u1EABn file ho\u1EB7c th\u01B0 m\u1EE5c").option("--to <language>", "M\xE3 ng\xF4n ng\u1EEF \u0111\xEDch (m\u1EB7c \u0111\u1ECBnh: vi)", "vi").option("-o, --output <path>", "\u0110\u01B0\u1EDDng d\u1EABn output (file/th\u01B0 m\u1EE5c)").option("--dry-run", "Xem tr\u01B0\u1EDBc kh\xF4ng l\u01B0u file").option("--concurrency <number>", "S\u1ED1 file x\u1EED l\xFD song song (m\u1EB7c \u0111\u1ECBnh: 3)", "3").option("--model <model>", "Model LLM (m\u1EB7c \u0111\u1ECBnh: gpt-5.1-codex-mini)").option("--json", "Xu\u1EA5t k\u1EBFt qu\u1EA3 d\u1EA1ng JSON").action(async (input2, options) => {
|
|
4883
|
+
await handleTranslate(input2, options);
|
|
4883
4884
|
});
|
|
4884
4885
|
return cmd;
|
|
4885
4886
|
}
|
|
@@ -4939,12 +4940,12 @@ var UtilsService = class {
|
|
|
4939
4940
|
/**
|
|
4940
4941
|
* Hash text or file using specified algorithm
|
|
4941
4942
|
*/
|
|
4942
|
-
async hash(
|
|
4943
|
+
async hash(input2, algorithm) {
|
|
4943
4944
|
if (algorithm === "bcrypt") {
|
|
4944
4945
|
throw new Error("Use hashBcrypt for bcrypt algorithm");
|
|
4945
4946
|
}
|
|
4946
4947
|
const hash = crypto.createHash(algorithm);
|
|
4947
|
-
hash.update(
|
|
4948
|
+
hash.update(input2);
|
|
4948
4949
|
return hash.digest("hex");
|
|
4949
4950
|
}
|
|
4950
4951
|
/**
|
|
@@ -4957,14 +4958,14 @@ var UtilsService = class {
|
|
|
4957
4958
|
/**
|
|
4958
4959
|
* Hash using bcrypt
|
|
4959
4960
|
*/
|
|
4960
|
-
async hashBcrypt(
|
|
4961
|
-
return bcrypt.hash(
|
|
4961
|
+
async hashBcrypt(input2, rounds = 10) {
|
|
4962
|
+
return bcrypt.hash(input2, rounds);
|
|
4962
4963
|
}
|
|
4963
4964
|
/**
|
|
4964
4965
|
* Base64 encode
|
|
4965
4966
|
*/
|
|
4966
|
-
base64Encode(
|
|
4967
|
-
const buffer = typeof
|
|
4967
|
+
base64Encode(input2, urlSafe = false) {
|
|
4968
|
+
const buffer = typeof input2 === "string" ? Buffer.from(input2, "utf-8") : input2;
|
|
4968
4969
|
let encoded = buffer.toString("base64");
|
|
4969
4970
|
if (urlSafe) {
|
|
4970
4971
|
encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
@@ -4974,8 +4975,8 @@ var UtilsService = class {
|
|
|
4974
4975
|
/**
|
|
4975
4976
|
* Base64 decode
|
|
4976
4977
|
*/
|
|
4977
|
-
base64Decode(
|
|
4978
|
-
let normalized =
|
|
4978
|
+
base64Decode(input2) {
|
|
4979
|
+
let normalized = input2.replace(/-/g, "+").replace(/_/g, "/");
|
|
4979
4980
|
while (normalized.length % 4) {
|
|
4980
4981
|
normalized += "=";
|
|
4981
4982
|
}
|
|
@@ -5104,14 +5105,14 @@ var UtilsService = class {
|
|
|
5104
5105
|
/**
|
|
5105
5106
|
* URL encode
|
|
5106
5107
|
*/
|
|
5107
|
-
urlEncode(
|
|
5108
|
-
return full ? encodeURI(
|
|
5108
|
+
urlEncode(input2, full = false) {
|
|
5109
|
+
return full ? encodeURI(input2) : encodeURIComponent(input2);
|
|
5109
5110
|
}
|
|
5110
5111
|
/**
|
|
5111
5112
|
* URL decode
|
|
5112
5113
|
*/
|
|
5113
|
-
urlDecode(
|
|
5114
|
-
return full ? decodeURI(
|
|
5114
|
+
urlDecode(input2, full = false) {
|
|
5115
|
+
return full ? decodeURI(input2) : decodeURIComponent(input2);
|
|
5115
5116
|
}
|
|
5116
5117
|
/**
|
|
5117
5118
|
* Format bytes to human-readable size
|
|
@@ -5221,7 +5222,7 @@ Examples:
|
|
|
5221
5222
|
|
|
5222
5223
|
// src/commands/utils/hash.ts
|
|
5223
5224
|
import { Command as Command17 } from "commander";
|
|
5224
|
-
async function handleHashGeneration(
|
|
5225
|
+
async function handleHashGeneration(input2, options) {
|
|
5225
5226
|
const service = new UtilsService();
|
|
5226
5227
|
try {
|
|
5227
5228
|
let hash;
|
|
@@ -5232,14 +5233,14 @@ async function handleHashGeneration(input, options) {
|
|
|
5232
5233
|
}
|
|
5233
5234
|
hash = await service.hashFile(options.file, options.algorithm);
|
|
5234
5235
|
} else {
|
|
5235
|
-
if (!
|
|
5236
|
+
if (!input2) {
|
|
5236
5237
|
console.error("\u274C Please provide input text or use --file option");
|
|
5237
5238
|
process.exit(1);
|
|
5238
5239
|
}
|
|
5239
5240
|
if (options.algorithm === "bcrypt") {
|
|
5240
|
-
hash = await service.hashBcrypt(
|
|
5241
|
+
hash = await service.hashBcrypt(input2, options.rounds);
|
|
5241
5242
|
} else {
|
|
5242
|
-
hash = await service.hash(
|
|
5243
|
+
hash = await service.hash(input2, options.algorithm);
|
|
5243
5244
|
}
|
|
5244
5245
|
}
|
|
5245
5246
|
console.log("\u{1F512} Hash Result:");
|
|
@@ -5272,8 +5273,8 @@ Examples:
|
|
|
5272
5273
|
$ jai1 utils hash "password" --algorithm bcrypt --rounds 12
|
|
5273
5274
|
$ jai1 utils hash --file ./myfile.txt
|
|
5274
5275
|
$ jai1 utils hash --file ./image.png --algorithm sha512
|
|
5275
|
-
`).action(async (
|
|
5276
|
-
await handleHashGeneration(
|
|
5276
|
+
`).action(async (input2, options) => {
|
|
5277
|
+
await handleHashGeneration(input2, {
|
|
5277
5278
|
...options,
|
|
5278
5279
|
rounds: parseInt(options.rounds, 10)
|
|
5279
5280
|
});
|
|
@@ -5284,7 +5285,7 @@ Examples:
|
|
|
5284
5285
|
// src/commands/utils/base64-encode.ts
|
|
5285
5286
|
import { Command as Command18 } from "commander";
|
|
5286
5287
|
import { readFile as readFile2 } from "fs/promises";
|
|
5287
|
-
async function handleBase64Encode(
|
|
5288
|
+
async function handleBase64Encode(input2, options) {
|
|
5288
5289
|
const service = new UtilsService();
|
|
5289
5290
|
try {
|
|
5290
5291
|
let encoded;
|
|
@@ -5292,11 +5293,11 @@ async function handleBase64Encode(input, options) {
|
|
|
5292
5293
|
const content = await readFile2(options.file);
|
|
5293
5294
|
encoded = service.base64Encode(content, options.urlSafe);
|
|
5294
5295
|
} else {
|
|
5295
|
-
if (!
|
|
5296
|
+
if (!input2) {
|
|
5296
5297
|
console.error("\u274C Please provide input text or use --file option");
|
|
5297
5298
|
process.exit(1);
|
|
5298
5299
|
}
|
|
5299
|
-
encoded = service.base64Encode(
|
|
5300
|
+
encoded = service.base64Encode(input2, options.urlSafe);
|
|
5300
5301
|
}
|
|
5301
5302
|
console.log("\u{1F4DD} Base64 Encoded:");
|
|
5302
5303
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
@@ -5321,8 +5322,8 @@ Examples:
|
|
|
5321
5322
|
$ jai1 utils base64-encode "hello world" --url-safe
|
|
5322
5323
|
$ jai1 utils base64-encode --file ./document.txt
|
|
5323
5324
|
$ jai1 utils base64-encode --file ./image.png
|
|
5324
|
-
`).action(async (
|
|
5325
|
-
await handleBase64Encode(
|
|
5325
|
+
`).action(async (input2, options) => {
|
|
5326
|
+
await handleBase64Encode(input2, options);
|
|
5326
5327
|
});
|
|
5327
5328
|
return cmd;
|
|
5328
5329
|
}
|
|
@@ -5330,18 +5331,18 @@ Examples:
|
|
|
5330
5331
|
// src/commands/utils/base64-decode.ts
|
|
5331
5332
|
import { Command as Command19 } from "commander";
|
|
5332
5333
|
import { readFile as readFile3, writeFile } from "fs/promises";
|
|
5333
|
-
async function handleBase64Decode(
|
|
5334
|
+
async function handleBase64Decode(input2, options) {
|
|
5334
5335
|
const service = new UtilsService();
|
|
5335
5336
|
try {
|
|
5336
5337
|
let encodedInput;
|
|
5337
5338
|
if (options.file) {
|
|
5338
5339
|
encodedInput = await readFile3(options.file, "utf-8");
|
|
5339
5340
|
} else {
|
|
5340
|
-
if (!
|
|
5341
|
+
if (!input2) {
|
|
5341
5342
|
console.error("\u274C Please provide Base64 input or use --file option");
|
|
5342
5343
|
process.exit(1);
|
|
5343
5344
|
}
|
|
5344
|
-
encodedInput =
|
|
5345
|
+
encodedInput = input2;
|
|
5345
5346
|
}
|
|
5346
5347
|
const decoded = service.base64Decode(encodedInput.trim());
|
|
5347
5348
|
if (options.output) {
|
|
@@ -5366,8 +5367,8 @@ Examples:
|
|
|
5366
5367
|
$ jai1 utils base64-decode --file ./encoded.txt
|
|
5367
5368
|
$ jai1 utils base64-decode "aGVsbG8=" --output ./decoded.txt
|
|
5368
5369
|
$ jai1 utils base64-decode --file ./encoded.txt --output ./image.png
|
|
5369
|
-
`).action(async (
|
|
5370
|
-
await handleBase64Decode(
|
|
5370
|
+
`).action(async (input2, options) => {
|
|
5371
|
+
await handleBase64Decode(input2, options);
|
|
5371
5372
|
});
|
|
5372
5373
|
return cmd;
|
|
5373
5374
|
}
|
|
@@ -5518,10 +5519,10 @@ Examples:
|
|
|
5518
5519
|
|
|
5519
5520
|
// src/commands/utils/unix-time.ts
|
|
5520
5521
|
import { Command as Command22 } from "commander";
|
|
5521
|
-
async function handleUnixTime(
|
|
5522
|
+
async function handleUnixTime(input2, options) {
|
|
5522
5523
|
const service = new UtilsService();
|
|
5523
5524
|
try {
|
|
5524
|
-
if (!
|
|
5525
|
+
if (!input2) {
|
|
5525
5526
|
const now = /* @__PURE__ */ new Date();
|
|
5526
5527
|
const timestamp = service.dateToUnix(now, options.ms);
|
|
5527
5528
|
console.log("\u{1F552} Current Unix Timestamp:");
|
|
@@ -5531,8 +5532,8 @@ async function handleUnixTime(input, options) {
|
|
|
5531
5532
|
console.log(` ISO: ${now.toISOString()}`);
|
|
5532
5533
|
console.log(` Local: ${now.toLocaleString()}`);
|
|
5533
5534
|
console.log();
|
|
5534
|
-
} else if (/^\d+$/.test(
|
|
5535
|
-
const timestamp = parseInt(
|
|
5535
|
+
} else if (/^\d+$/.test(input2)) {
|
|
5536
|
+
const timestamp = parseInt(input2, 10);
|
|
5536
5537
|
const date = service.unixToDate(timestamp, options.ms);
|
|
5537
5538
|
console.log("\u{1F552} Unix Timestamp to Date:");
|
|
5538
5539
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
@@ -5545,7 +5546,7 @@ async function handleUnixTime(input, options) {
|
|
|
5545
5546
|
}
|
|
5546
5547
|
console.log();
|
|
5547
5548
|
} else {
|
|
5548
|
-
const date = new Date(
|
|
5549
|
+
const date = new Date(input2);
|
|
5549
5550
|
if (isNaN(date.getTime())) {
|
|
5550
5551
|
console.error("\u274C Invalid date format");
|
|
5551
5552
|
process.exit(1);
|
|
@@ -5553,7 +5554,7 @@ async function handleUnixTime(input, options) {
|
|
|
5553
5554
|
const timestamp = service.dateToUnix(date, options.ms);
|
|
5554
5555
|
console.log("\u{1F552} Date to Unix Timestamp:");
|
|
5555
5556
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5556
|
-
console.log(` Input: ${
|
|
5557
|
+
console.log(` Input: ${input2}`);
|
|
5557
5558
|
console.log(` Parsed: ${date.toISOString()}`);
|
|
5558
5559
|
console.log();
|
|
5559
5560
|
console.log(` ${timestamp}${options.ms ? " (ms)" : ""}`);
|
|
@@ -5573,8 +5574,8 @@ Examples:
|
|
|
5573
5574
|
$ jai1 utils unix-time "2024-01-15 10:30:00"
|
|
5574
5575
|
$ jai1 utils unix-time "2024-01-15" --format local
|
|
5575
5576
|
$ jai1 utils unix-time --ms
|
|
5576
|
-
`).action(async (
|
|
5577
|
-
await handleUnixTime(
|
|
5577
|
+
`).action(async (input2, options) => {
|
|
5578
|
+
await handleUnixTime(input2, options);
|
|
5578
5579
|
});
|
|
5579
5580
|
return cmd;
|
|
5580
5581
|
}
|
|
@@ -5631,10 +5632,10 @@ Examples:
|
|
|
5631
5632
|
|
|
5632
5633
|
// src/commands/utils/url-encode.ts
|
|
5633
5634
|
import { Command as Command24 } from "commander";
|
|
5634
|
-
async function handleUrlEncode(
|
|
5635
|
+
async function handleUrlEncode(input2, options) {
|
|
5635
5636
|
const service = new UtilsService();
|
|
5636
5637
|
try {
|
|
5637
|
-
const encoded = service.urlEncode(
|
|
5638
|
+
const encoded = service.urlEncode(input2, options.full);
|
|
5638
5639
|
console.log("\u{1F517} URL Encoded:");
|
|
5639
5640
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5640
5641
|
if (options.full) {
|
|
@@ -5657,18 +5658,18 @@ Examples:
|
|
|
5657
5658
|
$ jai1 utils url-encode "hello world & test"
|
|
5658
5659
|
$ jai1 utils url-encode "name=John Doe&age=30"
|
|
5659
5660
|
$ jai1 utils url-encode "https://example.com/path with spaces" --full
|
|
5660
|
-
`).showHelpAfterError("(add --help for additional examples)").action(async (
|
|
5661
|
-
await handleUrlEncode(
|
|
5661
|
+
`).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
|
|
5662
|
+
await handleUrlEncode(input2, options);
|
|
5662
5663
|
});
|
|
5663
5664
|
return cmd;
|
|
5664
5665
|
}
|
|
5665
5666
|
|
|
5666
5667
|
// src/commands/utils/url-decode.ts
|
|
5667
5668
|
import { Command as Command25 } from "commander";
|
|
5668
|
-
async function handleUrlDecode(
|
|
5669
|
+
async function handleUrlDecode(input2, options) {
|
|
5669
5670
|
const service = new UtilsService();
|
|
5670
5671
|
try {
|
|
5671
|
-
const decoded = service.urlDecode(
|
|
5672
|
+
const decoded = service.urlDecode(input2, options.full);
|
|
5672
5673
|
console.log("\u{1F517} URL Decoded:");
|
|
5673
5674
|
console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
5674
5675
|
if (options.full) {
|
|
@@ -5691,8 +5692,8 @@ Examples:
|
|
|
5691
5692
|
$ jai1 utils url-decode "hello%20world%20%26%20test"
|
|
5692
5693
|
$ jai1 utils url-decode "name%3DJohn%20Doe%26age%3D30"
|
|
5693
5694
|
$ jai1 utils url-decode "https://example.com/path%20with%20spaces" --full
|
|
5694
|
-
`).showHelpAfterError("(add --help for additional examples)").action(async (
|
|
5695
|
-
await handleUrlDecode(
|
|
5695
|
+
`).showHelpAfterError("(add --help for additional examples)").action(async (input2, options) => {
|
|
5696
|
+
await handleUrlDecode(input2, options);
|
|
5696
5697
|
});
|
|
5697
5698
|
return cmd;
|
|
5698
5699
|
}
|
|
@@ -5828,14 +5829,14 @@ var PasswordView = () => {
|
|
|
5828
5829
|
React27.useEffect(() => {
|
|
5829
5830
|
handleGenerate();
|
|
5830
5831
|
}, []);
|
|
5831
|
-
useInput12((
|
|
5832
|
+
useInput12((input2, key) => {
|
|
5832
5833
|
if (key.tab) {
|
|
5833
5834
|
if (focusedField === "length") setFocusedField("count");
|
|
5834
5835
|
else if (focusedField === "count") setFocusedField("generate");
|
|
5835
5836
|
else setFocusedField("length");
|
|
5836
5837
|
} else if (key.return) {
|
|
5837
5838
|
handleGenerate();
|
|
5838
|
-
} else if (
|
|
5839
|
+
} else if (input2 === "c" && passwords.length > 0) {
|
|
5839
5840
|
handleCopy(0);
|
|
5840
5841
|
}
|
|
5841
5842
|
});
|
|
@@ -5918,7 +5919,7 @@ var UuidView = () => {
|
|
|
5918
5919
|
React28.useEffect(() => {
|
|
5919
5920
|
handleGenerate();
|
|
5920
5921
|
}, []);
|
|
5921
|
-
useInput13((
|
|
5922
|
+
useInput13((input2, key) => {
|
|
5922
5923
|
if (key.tab) {
|
|
5923
5924
|
const fields = ["count", "uppercase", "hyphens", "generate"];
|
|
5924
5925
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -5931,7 +5932,7 @@ var UuidView = () => {
|
|
|
5931
5932
|
} else {
|
|
5932
5933
|
handleGenerate();
|
|
5933
5934
|
}
|
|
5934
|
-
} else if (
|
|
5935
|
+
} else if (input2 === "c" && uuids.length > 0) {
|
|
5935
5936
|
handleCopy(0);
|
|
5936
5937
|
}
|
|
5937
5938
|
});
|
|
@@ -6006,7 +6007,7 @@ var HashView = () => {
|
|
|
6006
6007
|
React29.useEffect(() => {
|
|
6007
6008
|
handleGenerate();
|
|
6008
6009
|
}, []);
|
|
6009
|
-
useInput14((
|
|
6010
|
+
useInput14((input2, key) => {
|
|
6010
6011
|
if (key.tab) {
|
|
6011
6012
|
const fields = ["text", "algorithm", "generate"];
|
|
6012
6013
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -6019,7 +6020,7 @@ var HashView = () => {
|
|
|
6019
6020
|
} else if (key.rightArrow && focusedField === "algorithm") {
|
|
6020
6021
|
const currentIndex = ALGORITHMS.indexOf(algorithm);
|
|
6021
6022
|
setAlgorithm(ALGORITHMS[(currentIndex + 1) % ALGORITHMS.length]);
|
|
6022
|
-
} else if (
|
|
6023
|
+
} else if (input2 === "c" && hash) {
|
|
6023
6024
|
handleCopy();
|
|
6024
6025
|
}
|
|
6025
6026
|
});
|
|
@@ -6085,7 +6086,7 @@ import React30, { useState as useState17 } from "react";
|
|
|
6085
6086
|
import { Box as Box20, Text as Text21, useInput as useInput15 } from "ink";
|
|
6086
6087
|
import TextInput7 from "ink-text-input";
|
|
6087
6088
|
var Base64View = () => {
|
|
6088
|
-
const [
|
|
6089
|
+
const [input2, setInput] = useState17("");
|
|
6089
6090
|
const [mode, setMode] = useState17("encode");
|
|
6090
6091
|
const [urlSafe, setUrlSafe] = useState17(false);
|
|
6091
6092
|
const [result, setResult] = useState17("");
|
|
@@ -6093,7 +6094,7 @@ var Base64View = () => {
|
|
|
6093
6094
|
const [focusedField, setFocusedField] = useState17("input");
|
|
6094
6095
|
const [copied, setCopied] = useState17(false);
|
|
6095
6096
|
const service = new UtilsService();
|
|
6096
|
-
useInput15((
|
|
6097
|
+
useInput15((input3, key) => {
|
|
6097
6098
|
if (key.tab) {
|
|
6098
6099
|
const fields = ["input", "mode", "urlsafe", "convert"];
|
|
6099
6100
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -6108,22 +6109,22 @@ var Base64View = () => {
|
|
|
6108
6109
|
} else {
|
|
6109
6110
|
handleConvert();
|
|
6110
6111
|
}
|
|
6111
|
-
} else if (
|
|
6112
|
+
} else if (input3 === "c" && result) {
|
|
6112
6113
|
handleCopy();
|
|
6113
6114
|
}
|
|
6114
6115
|
});
|
|
6115
6116
|
const handleConvert = () => {
|
|
6116
|
-
if (!
|
|
6117
|
+
if (!input2) {
|
|
6117
6118
|
setError("Input cannot be empty");
|
|
6118
6119
|
return;
|
|
6119
6120
|
}
|
|
6120
6121
|
try {
|
|
6121
6122
|
setError("");
|
|
6122
6123
|
if (mode === "encode") {
|
|
6123
|
-
const encoded = service.base64Encode(
|
|
6124
|
+
const encoded = service.base64Encode(input2, urlSafe);
|
|
6124
6125
|
setResult(encoded);
|
|
6125
6126
|
} else {
|
|
6126
|
-
const decoded = service.base64Decode(
|
|
6127
|
+
const decoded = service.base64Decode(input2);
|
|
6127
6128
|
setResult(decoded.toString("utf-8"));
|
|
6128
6129
|
}
|
|
6129
6130
|
setCopied(false);
|
|
@@ -6152,7 +6153,7 @@ var Base64View = () => {
|
|
|
6152
6153
|
marginBottom: 1
|
|
6153
6154
|
},
|
|
6154
6155
|
/* @__PURE__ */ React30.createElement(Text21, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
6155
|
-
/* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 0 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React30.createElement(TextInput7, { value:
|
|
6156
|
+
/* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 0 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React30.createElement(Box20, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React30.createElement(TextInput7, { value: input2, onChange: setInput, placeholder: "Enter text..." }) : /* @__PURE__ */ React30.createElement(Text21, { dimColor: !input2 }, input2 || "(empty)"))),
|
|
6156
6157
|
/* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Box20, { width: 20 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React30.createElement(Text21, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React30.createElement(Text21, { dimColor: true }, " (Enter to toggle)")),
|
|
6157
6158
|
mode === "encode" && /* @__PURE__ */ React30.createElement(Box20, { marginBottom: 1 }, /* @__PURE__ */ React30.createElement(Text21, { color: focusedField === "urlsafe" ? "green" : void 0 }, focusedField === "urlsafe" ? "\u25B6 " : " ", "[", urlSafe ? "\u2713" : " ", "] URL-Safe (+ \u2192 -, / \u2192 _)")),
|
|
6158
6159
|
/* @__PURE__ */ React30.createElement(Box20, { marginTop: 1 }, /* @__PURE__ */ React30.createElement(
|
|
@@ -6197,14 +6198,14 @@ import React31, { useState as useState18 } from "react";
|
|
|
6197
6198
|
import { Box as Box21, Text as Text22, useInput as useInput16 } from "ink";
|
|
6198
6199
|
import TextInput8 from "ink-text-input";
|
|
6199
6200
|
var UrlView = () => {
|
|
6200
|
-
const [
|
|
6201
|
+
const [input2, setInput] = useState18("");
|
|
6201
6202
|
const [mode, setMode] = useState18("encode");
|
|
6202
6203
|
const [fullUrl, setFullUrl] = useState18(false);
|
|
6203
6204
|
const [result, setResult] = useState18("");
|
|
6204
6205
|
const [focusedField, setFocusedField] = useState18("input");
|
|
6205
6206
|
const [copied, setCopied] = useState18(false);
|
|
6206
6207
|
const service = new UtilsService();
|
|
6207
|
-
useInput16((
|
|
6208
|
+
useInput16((input3, key) => {
|
|
6208
6209
|
if (key.tab) {
|
|
6209
6210
|
const fields = ["input", "mode", "full", "convert"];
|
|
6210
6211
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -6218,17 +6219,17 @@ var UrlView = () => {
|
|
|
6218
6219
|
} else {
|
|
6219
6220
|
handleConvert();
|
|
6220
6221
|
}
|
|
6221
|
-
} else if (
|
|
6222
|
+
} else if (input3 === "c" && result) {
|
|
6222
6223
|
handleCopy();
|
|
6223
6224
|
}
|
|
6224
6225
|
});
|
|
6225
6226
|
const handleConvert = () => {
|
|
6226
|
-
if (!
|
|
6227
|
+
if (!input2) return;
|
|
6227
6228
|
if (mode === "encode") {
|
|
6228
|
-
const encoded = fullUrl ? service.urlEncode(
|
|
6229
|
+
const encoded = fullUrl ? service.urlEncode(input2, true) : service.urlEncode(input2, false);
|
|
6229
6230
|
setResult(encoded);
|
|
6230
6231
|
} else {
|
|
6231
|
-
const decoded = fullUrl ? service.urlDecode(
|
|
6232
|
+
const decoded = fullUrl ? service.urlDecode(input2, true) : service.urlDecode(input2, false);
|
|
6232
6233
|
setResult(decoded);
|
|
6233
6234
|
}
|
|
6234
6235
|
setCopied(false);
|
|
@@ -6253,7 +6254,7 @@ var UrlView = () => {
|
|
|
6253
6254
|
marginBottom: 1
|
|
6254
6255
|
},
|
|
6255
6256
|
/* @__PURE__ */ React31.createElement(Text22, { bold: true, color: "yellow", marginBottom: 1 }, "Options:"),
|
|
6256
|
-
/* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 0 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React31.createElement(TextInput8, { value:
|
|
6257
|
+
/* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React31.createElement(Box21, { marginBottom: 0 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", "Input text:")), /* @__PURE__ */ React31.createElement(Box21, { marginLeft: 2, width: 60 }, focusedField === "input" ? /* @__PURE__ */ React31.createElement(TextInput8, { value: input2, onChange: setInput, placeholder: "Enter text or URL..." }) : /* @__PURE__ */ React31.createElement(Text22, { dimColor: !input2 }, input2 || "(empty)"))),
|
|
6257
6258
|
/* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Box21, { width: 20 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "mode" ? "green" : void 0 }, focusedField === "mode" ? "\u25B6 " : " ", "Mode:")), /* @__PURE__ */ React31.createElement(Text22, { bold: true, color: focusedField === "mode" ? "yellow" : void 0 }, mode === "encode" ? "ENCODE" : "DECODE"), focusedField === "mode" && /* @__PURE__ */ React31.createElement(Text22, { dimColor: true }, " (Enter to toggle)")),
|
|
6258
6259
|
/* @__PURE__ */ React31.createElement(Box21, { marginBottom: 1 }, /* @__PURE__ */ React31.createElement(Text22, { color: focusedField === "full" ? "green" : void 0 }, focusedField === "full" ? "\u25B6 " : " ", "[", fullUrl ? "\u2713" : " ", "] Full URL (encode/decode entire URL)")),
|
|
6259
6260
|
/* @__PURE__ */ React31.createElement(Box21, { marginTop: 1 }, /* @__PURE__ */ React31.createElement(
|
|
@@ -6287,7 +6288,7 @@ import React32, { useState as useState19 } from "react";
|
|
|
6287
6288
|
import { Box as Box22, Text as Text23, useInput as useInput17 } from "ink";
|
|
6288
6289
|
import TextInput9 from "ink-text-input";
|
|
6289
6290
|
var UnixTimeView = () => {
|
|
6290
|
-
const [
|
|
6291
|
+
const [input2, setInput] = useState19("");
|
|
6291
6292
|
const [mode, setMode] = useState19("now");
|
|
6292
6293
|
const [format, setFormat] = useState19("iso");
|
|
6293
6294
|
const [useMs, setUseMs] = useState19(false);
|
|
@@ -6296,7 +6297,7 @@ var UnixTimeView = () => {
|
|
|
6296
6297
|
const [focusedField, setFocusedField] = useState19("mode");
|
|
6297
6298
|
const [copied, setCopied] = useState19(false);
|
|
6298
6299
|
const service = new UtilsService();
|
|
6299
|
-
useInput17((
|
|
6300
|
+
useInput17((input3, key) => {
|
|
6300
6301
|
if (key.tab) {
|
|
6301
6302
|
const fields = mode === "now" ? ["mode", "ms", "convert"] : mode === "to-human" ? ["mode", "input", "format", "convert"] : ["mode", "input", "convert"];
|
|
6302
6303
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -6317,7 +6318,7 @@ var UnixTimeView = () => {
|
|
|
6317
6318
|
} else {
|
|
6318
6319
|
handleConvert();
|
|
6319
6320
|
}
|
|
6320
|
-
} else if (
|
|
6321
|
+
} else if (input3 === "c" && result) {
|
|
6321
6322
|
handleCopy();
|
|
6322
6323
|
}
|
|
6323
6324
|
});
|
|
@@ -6328,18 +6329,18 @@ var UnixTimeView = () => {
|
|
|
6328
6329
|
const timestamp = service.unixTimeCurrent(useMs);
|
|
6329
6330
|
setResult(timestamp.toString());
|
|
6330
6331
|
} else if (mode === "to-human") {
|
|
6331
|
-
if (!
|
|
6332
|
+
if (!input2) {
|
|
6332
6333
|
setError("Please enter a timestamp");
|
|
6333
6334
|
return;
|
|
6334
6335
|
}
|
|
6335
|
-
const human = service.unixTimeToHuman(parseInt(
|
|
6336
|
+
const human = service.unixTimeToHuman(parseInt(input2, 10), format);
|
|
6336
6337
|
setResult(human);
|
|
6337
6338
|
} else {
|
|
6338
|
-
if (!
|
|
6339
|
+
if (!input2) {
|
|
6339
6340
|
setError("Please enter a date string");
|
|
6340
6341
|
return;
|
|
6341
6342
|
}
|
|
6342
|
-
const timestamp = service.unixTimeFromString(
|
|
6343
|
+
const timestamp = service.unixTimeFromString(input2);
|
|
6343
6344
|
setResult(timestamp.toString());
|
|
6344
6345
|
}
|
|
6345
6346
|
setCopied(false);
|
|
@@ -6372,11 +6373,11 @@ var UnixTimeView = () => {
|
|
|
6372
6373
|
mode !== "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1, flexDirection: "column" }, /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 0 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "input" ? "green" : void 0 }, focusedField === "input" ? "\u25B6 " : " ", mode === "to-human" ? "Timestamp:" : "Date string:")), /* @__PURE__ */ React32.createElement(Box22, { marginLeft: 2, width: 50 }, focusedField === "input" ? /* @__PURE__ */ React32.createElement(
|
|
6373
6374
|
TextInput9,
|
|
6374
6375
|
{
|
|
6375
|
-
value:
|
|
6376
|
+
value: input2,
|
|
6376
6377
|
onChange: setInput,
|
|
6377
6378
|
placeholder: mode === "to-human" ? "1702550400" : "2024-01-15 10:30:00"
|
|
6378
6379
|
}
|
|
6379
|
-
) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !
|
|
6380
|
+
) : /* @__PURE__ */ React32.createElement(Text23, { dimColor: !input2 }, input2 || "(empty)"))),
|
|
6380
6381
|
mode === "to-human" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Box22, { width: 20 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "format" ? "green" : void 0 }, focusedField === "format" ? "\u25B6 " : " ", "Format:")), /* @__PURE__ */ React32.createElement(Text23, { bold: true, color: focusedField === "format" ? "yellow" : void 0 }, format.toUpperCase()), focusedField === "format" && /* @__PURE__ */ React32.createElement(Text23, { dimColor: true }, " (Enter to cycle)")),
|
|
6381
6382
|
mode === "now" && /* @__PURE__ */ React32.createElement(Box22, { marginBottom: 1 }, /* @__PURE__ */ React32.createElement(Text23, { color: focusedField === "ms" ? "green" : void 0 }, focusedField === "ms" ? "\u25B6 " : " ", "[", useMs ? "\u2713" : " ", "] Milliseconds")),
|
|
6382
6383
|
/* @__PURE__ */ React32.createElement(Box22, { marginTop: 1 }, /* @__PURE__ */ React32.createElement(
|
|
@@ -6430,7 +6431,7 @@ var JwtView = () => {
|
|
|
6430
6431
|
const [focusedField, setFocusedField] = useState20("mode");
|
|
6431
6432
|
const [copied, setCopied] = useState20(false);
|
|
6432
6433
|
const service = new UtilsService();
|
|
6433
|
-
useInput18((
|
|
6434
|
+
useInput18((input2, key) => {
|
|
6434
6435
|
if (key.tab) {
|
|
6435
6436
|
const fields = mode === "decode" ? ["mode", "token", "process"] : ["mode", "payload", "secret", "process"];
|
|
6436
6437
|
const currentIndex = fields.indexOf(focusedField);
|
|
@@ -6443,7 +6444,7 @@ var JwtView = () => {
|
|
|
6443
6444
|
} else {
|
|
6444
6445
|
handleProcess();
|
|
6445
6446
|
}
|
|
6446
|
-
} else if (
|
|
6447
|
+
} else if (input2 === "c" && result.token) {
|
|
6447
6448
|
handleCopy();
|
|
6448
6449
|
}
|
|
6449
6450
|
});
|
|
@@ -6568,12 +6569,12 @@ var CronView = () => {
|
|
|
6568
6569
|
const [focusedField, setFocusedField] = useState21("expression");
|
|
6569
6570
|
const [copied, setCopied] = useState21(false);
|
|
6570
6571
|
const service = new UtilsService();
|
|
6571
|
-
useInput19((
|
|
6572
|
+
useInput19((input2, key) => {
|
|
6572
6573
|
if (key.tab) {
|
|
6573
6574
|
setFocusedField(focusedField === "expression" ? "parse" : "expression");
|
|
6574
6575
|
} else if (key.return) {
|
|
6575
6576
|
handleParse();
|
|
6576
|
-
} else if (
|
|
6577
|
+
} else if (input2 === "c" && result) {
|
|
6577
6578
|
handleCopy();
|
|
6578
6579
|
}
|
|
6579
6580
|
});
|
|
@@ -6674,14 +6675,14 @@ var TimezoneView = () => {
|
|
|
6674
6675
|
const [focusedField, setFocusedField] = useState22("time");
|
|
6675
6676
|
const [copied, setCopied] = useState22(false);
|
|
6676
6677
|
const service = new UtilsService();
|
|
6677
|
-
useInput20((
|
|
6678
|
+
useInput20((input2, key) => {
|
|
6678
6679
|
if (key.tab) {
|
|
6679
6680
|
const fields = ["time", "from", "to", "convert"];
|
|
6680
6681
|
const currentIndex = fields.indexOf(focusedField);
|
|
6681
6682
|
setFocusedField(fields[(currentIndex + 1) % fields.length]);
|
|
6682
6683
|
} else if (key.return) {
|
|
6683
6684
|
handleConvert();
|
|
6684
|
-
} else if (
|
|
6685
|
+
} else if (input2 === "c" && result) {
|
|
6685
6686
|
handleCopy();
|
|
6686
6687
|
}
|
|
6687
6688
|
});
|
|
@@ -6800,7 +6801,7 @@ var HttpView = () => {
|
|
|
6800
6801
|
const [focusedField, setFocusedField] = useState23("url");
|
|
6801
6802
|
const [copied, setCopied] = useState23(false);
|
|
6802
6803
|
const service = new UtilsService();
|
|
6803
|
-
useInput21((
|
|
6804
|
+
useInput21((input2, key) => {
|
|
6804
6805
|
if (loading) return;
|
|
6805
6806
|
if (key.tab) {
|
|
6806
6807
|
const fields = ["url", "method", "headers", "body", "send"];
|
|
@@ -6814,7 +6815,7 @@ var HttpView = () => {
|
|
|
6814
6815
|
setMethod(METHODS[(currentIndex + 1) % METHODS.length]);
|
|
6815
6816
|
} else if (key.return && focusedField === "send") {
|
|
6816
6817
|
handleSend();
|
|
6817
|
-
} else if (
|
|
6818
|
+
} else if (input2 === "c" && response) {
|
|
6818
6819
|
handleCopy();
|
|
6819
6820
|
}
|
|
6820
6821
|
});
|
|
@@ -6945,7 +6946,7 @@ var MarkdownView = () => {
|
|
|
6945
6946
|
const [content, setContent] = useState24("");
|
|
6946
6947
|
const [error, setError] = useState24("");
|
|
6947
6948
|
const [focusedField, setFocusedField] = useState24("file");
|
|
6948
|
-
useInput22((
|
|
6949
|
+
useInput22((input2, key) => {
|
|
6949
6950
|
if (key.tab) {
|
|
6950
6951
|
setFocusedField(focusedField === "file" ? "preview" : "file");
|
|
6951
6952
|
} else if (key.return) {
|
|
@@ -7060,20 +7061,20 @@ var UtilsApp = ({ onExit }) => {
|
|
|
7060
7061
|
const [selectedIndex, setSelectedIndex] = useState25(0);
|
|
7061
7062
|
const [activeView, setActiveView] = useState25(null);
|
|
7062
7063
|
const { exit } = useApp5();
|
|
7063
|
-
useInput23((
|
|
7064
|
+
useInput23((input2, key) => {
|
|
7064
7065
|
if (activeView) {
|
|
7065
7066
|
if (key.escape) {
|
|
7066
7067
|
setActiveView(null);
|
|
7067
7068
|
}
|
|
7068
7069
|
return;
|
|
7069
7070
|
}
|
|
7070
|
-
if (key.upArrow ||
|
|
7071
|
+
if (key.upArrow || input2 === "k") {
|
|
7071
7072
|
setSelectedIndex((prev) => prev > 0 ? prev - 1 : MENU_ITEMS2.length - 1);
|
|
7072
|
-
} else if (key.downArrow ||
|
|
7073
|
+
} else if (key.downArrow || input2 === "j") {
|
|
7073
7074
|
setSelectedIndex((prev) => prev < MENU_ITEMS2.length - 1 ? prev + 1 : 0);
|
|
7074
7075
|
} else if (key.return) {
|
|
7075
7076
|
setActiveView(MENU_ITEMS2[selectedIndex].id);
|
|
7076
|
-
} else if (
|
|
7077
|
+
} else if (input2 === "q" || key.escape) {
|
|
7077
7078
|
onExit();
|
|
7078
7079
|
exit();
|
|
7079
7080
|
}
|
|
@@ -7237,8 +7238,398 @@ Quick Usage:
|
|
|
7237
7238
|
return utilsCommand;
|
|
7238
7239
|
}
|
|
7239
7240
|
|
|
7240
|
-
// src/commands/
|
|
7241
|
+
// src/commands/kit/index.ts
|
|
7242
|
+
import { Command as Command32 } from "commander";
|
|
7243
|
+
|
|
7244
|
+
// src/commands/kit/list.ts
|
|
7241
7245
|
import { Command as Command29 } from "commander";
|
|
7246
|
+
|
|
7247
|
+
// src/services/starter-kit.service.ts
|
|
7248
|
+
import { promises as fs9 } from "fs";
|
|
7249
|
+
import { join as join4 } from "path";
|
|
7250
|
+
import AdmZip from "adm-zip";
|
|
7251
|
+
var StarterKitService = class {
|
|
7252
|
+
/**
|
|
7253
|
+
* List available starter kits
|
|
7254
|
+
*/
|
|
7255
|
+
async list(config, options) {
|
|
7256
|
+
const params = new URLSearchParams();
|
|
7257
|
+
if (options?.category) params.set("category", options.category);
|
|
7258
|
+
if (options?.search) params.set("search", options.search);
|
|
7259
|
+
const url = `${config.apiUrl}/api/starter-kits${params.toString() ? "?" + params : ""}`;
|
|
7260
|
+
const response = await fetch(url, {
|
|
7261
|
+
headers: { "JAI1-Access-Key": config.accessKey }
|
|
7262
|
+
});
|
|
7263
|
+
if (!response.ok) {
|
|
7264
|
+
throw new NetworkError(`Failed to list starter kits: HTTP ${response.status}`);
|
|
7265
|
+
}
|
|
7266
|
+
const data = await response.json();
|
|
7267
|
+
return data.kits;
|
|
7268
|
+
}
|
|
7269
|
+
/**
|
|
7270
|
+
* Get single starter kit with full config
|
|
7271
|
+
*/
|
|
7272
|
+
async get(config, slug) {
|
|
7273
|
+
const response = await fetch(`${config.apiUrl}/api/starter-kits/${slug}`, {
|
|
7274
|
+
headers: { "JAI1-Access-Key": config.accessKey }
|
|
7275
|
+
});
|
|
7276
|
+
if (!response.ok) {
|
|
7277
|
+
if (response.status === 404) {
|
|
7278
|
+
throw new Error(`Starter kit not found: ${slug}`);
|
|
7279
|
+
}
|
|
7280
|
+
throw new NetworkError(`Failed to get starter kit: HTTP ${response.status}`);
|
|
7281
|
+
}
|
|
7282
|
+
return await response.json();
|
|
7283
|
+
}
|
|
7284
|
+
/**
|
|
7285
|
+
* Download and extract starter kit
|
|
7286
|
+
*/
|
|
7287
|
+
async downloadAndExtract(config, slug, targetDir, onProgress) {
|
|
7288
|
+
if (onProgress) onProgress(10);
|
|
7289
|
+
const response = await fetch(`${config.apiUrl}/api/starter-kits/${slug}/download`, {
|
|
7290
|
+
headers: { "JAI1-Access-Key": config.accessKey }
|
|
7291
|
+
});
|
|
7292
|
+
if (!response.ok) {
|
|
7293
|
+
throw new NetworkError(`Failed to get download URL: HTTP ${response.status}`);
|
|
7294
|
+
}
|
|
7295
|
+
const data = await response.json();
|
|
7296
|
+
if (onProgress) onProgress(30);
|
|
7297
|
+
const downloadResponse = await fetch(data.downloadUrl);
|
|
7298
|
+
if (!downloadResponse.ok) {
|
|
7299
|
+
throw new NetworkError(`Failed to download kit: HTTP ${downloadResponse.status}`);
|
|
7300
|
+
}
|
|
7301
|
+
if (onProgress) onProgress(60);
|
|
7302
|
+
const tmpDir = join4(process.env.TMPDIR || "/tmp", "jai1-kits");
|
|
7303
|
+
await fs9.mkdir(tmpDir, { recursive: true });
|
|
7304
|
+
const tmpFile = join4(tmpDir, `${slug}.zip`);
|
|
7305
|
+
const buffer = await downloadResponse.arrayBuffer();
|
|
7306
|
+
await fs9.writeFile(tmpFile, Buffer.from(buffer));
|
|
7307
|
+
if (onProgress) onProgress(80);
|
|
7308
|
+
const zip = new AdmZip(tmpFile);
|
|
7309
|
+
await fs9.mkdir(targetDir, { recursive: true });
|
|
7310
|
+
zip.extractAllTo(targetDir, true);
|
|
7311
|
+
if (onProgress) onProgress(100);
|
|
7312
|
+
await fs9.unlink(tmpFile);
|
|
7313
|
+
}
|
|
7314
|
+
};
|
|
7315
|
+
|
|
7316
|
+
// src/commands/kit/list.ts
|
|
7317
|
+
function createKitListCommand() {
|
|
7318
|
+
return new Command29("list").description("List available starter kits").option("-c, --category <category>", "Filter by category (backend, frontend, fullstack)").option("-s, --search <term>", "Search kits by name or description").action(async (options) => {
|
|
7319
|
+
const configService = new ConfigService();
|
|
7320
|
+
const config = await configService.load();
|
|
7321
|
+
if (!config) {
|
|
7322
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
7323
|
+
}
|
|
7324
|
+
const kitService = new StarterKitService();
|
|
7325
|
+
const kits = await kitService.list(config, {
|
|
7326
|
+
category: options.category,
|
|
7327
|
+
search: options.search
|
|
7328
|
+
});
|
|
7329
|
+
if (kits.length === 0) {
|
|
7330
|
+
console.log("No starter kits found.");
|
|
7331
|
+
return;
|
|
7332
|
+
}
|
|
7333
|
+
const byCategory = {};
|
|
7334
|
+
for (const kit of kits) {
|
|
7335
|
+
if (!byCategory[kit.category]) {
|
|
7336
|
+
byCategory[kit.category] = [];
|
|
7337
|
+
}
|
|
7338
|
+
byCategory[kit.category].push(kit);
|
|
7339
|
+
}
|
|
7340
|
+
console.log("\u{1F4E6} Available Starter Kits:\n");
|
|
7341
|
+
for (const [category, categoryKits] of Object.entries(byCategory)) {
|
|
7342
|
+
console.log(`${category.charAt(0).toUpperCase() + category.slice(1)}:`);
|
|
7343
|
+
for (const kit of categoryKits) {
|
|
7344
|
+
const tags = kit.tags.length > 0 ? ` [${kit.tags.join(", ")}]` : "";
|
|
7345
|
+
console.log(
|
|
7346
|
+
` ${kit.slug.padEnd(20)} ${kit.description.slice(0, 50).padEnd(52)} v${kit.version}${tags}`
|
|
7347
|
+
);
|
|
7348
|
+
}
|
|
7349
|
+
console.log();
|
|
7350
|
+
}
|
|
7351
|
+
});
|
|
7352
|
+
}
|
|
7353
|
+
|
|
7354
|
+
// src/commands/kit/info.ts
|
|
7355
|
+
import { Command as Command30 } from "commander";
|
|
7356
|
+
function createKitInfoCommand() {
|
|
7357
|
+
return new Command30("info").description("Show detailed information about a starter kit").argument("<slug>", "Starter kit slug").action(async (slug) => {
|
|
7358
|
+
const configService = new ConfigService();
|
|
7359
|
+
const config = await configService.load();
|
|
7360
|
+
if (!config) {
|
|
7361
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
7362
|
+
}
|
|
7363
|
+
const kitService = new StarterKitService();
|
|
7364
|
+
const kit = await kitService.get(config, slug);
|
|
7365
|
+
console.log(`\u{1F4E6} ${kit.name}
|
|
7366
|
+
`);
|
|
7367
|
+
console.log(`Description: ${kit.description}`);
|
|
7368
|
+
console.log(`Category: ${kit.category}`);
|
|
7369
|
+
console.log(`Version: ${kit.version}`);
|
|
7370
|
+
console.log(`Downloads: ${kit.downloads}`);
|
|
7371
|
+
if (kit.tags.length > 0) {
|
|
7372
|
+
console.log(`Tags: ${kit.tags.join(", ")}`);
|
|
7373
|
+
}
|
|
7374
|
+
if (kit.config.requiredTools && kit.config.requiredTools.length > 0) {
|
|
7375
|
+
console.log(`
|
|
7376
|
+
Required Tools:`);
|
|
7377
|
+
kit.config.requiredTools.forEach((tool) => {
|
|
7378
|
+
console.log(` - ${tool}`);
|
|
7379
|
+
});
|
|
7380
|
+
}
|
|
7381
|
+
if (kit.config.framework?.apply && kit.config.framework.components.length > 0) {
|
|
7382
|
+
console.log(`
|
|
7383
|
+
Included Framework Components:`);
|
|
7384
|
+
kit.config.framework.components.forEach((comp) => {
|
|
7385
|
+
console.log(` - ${comp}`);
|
|
7386
|
+
});
|
|
7387
|
+
}
|
|
7388
|
+
if (kit.config.variables && kit.config.variables.length > 0) {
|
|
7389
|
+
console.log(`
|
|
7390
|
+
Variables (prompted during creation):`);
|
|
7391
|
+
kit.config.variables.forEach((v) => {
|
|
7392
|
+
console.log(` - ${v.name}: ${v.prompt}${v.default ? ` (default: ${v.default})` : ""}`);
|
|
7393
|
+
});
|
|
7394
|
+
}
|
|
7395
|
+
if (kit.config.hooks?.postInit && kit.config.hooks.postInit.length > 0) {
|
|
7396
|
+
console.log(`
|
|
7397
|
+
Post-Init Commands:`);
|
|
7398
|
+
kit.config.hooks.postInit.forEach((cmd) => {
|
|
7399
|
+
console.log(` - ${cmd}`);
|
|
7400
|
+
});
|
|
7401
|
+
}
|
|
7402
|
+
});
|
|
7403
|
+
}
|
|
7404
|
+
|
|
7405
|
+
// src/commands/kit/create.ts
|
|
7406
|
+
import { Command as Command31 } from "commander";
|
|
7407
|
+
import { promises as fs10 } from "fs";
|
|
7408
|
+
import { join as join5 } from "path";
|
|
7409
|
+
import { select as select2, input, checkbox as checkbox3 } from "@inquirer/prompts";
|
|
7410
|
+
import { execa as execa2 } from "execa";
|
|
7411
|
+
|
|
7412
|
+
// src/services/hook-executor.service.ts
|
|
7413
|
+
import { execa } from "execa";
|
|
7414
|
+
var HookExecutor = class {
|
|
7415
|
+
constructor(cwd, variables) {
|
|
7416
|
+
this.cwd = cwd;
|
|
7417
|
+
this.variables = variables;
|
|
7418
|
+
}
|
|
7419
|
+
/**
|
|
7420
|
+
* Run hooks sequentially
|
|
7421
|
+
*/
|
|
7422
|
+
async run(hooks) {
|
|
7423
|
+
for (const hook of hooks) {
|
|
7424
|
+
const cmd = this.replaceVariables(hook);
|
|
7425
|
+
console.log(` $ ${cmd}`);
|
|
7426
|
+
try {
|
|
7427
|
+
await execa(cmd, {
|
|
7428
|
+
cwd: this.cwd,
|
|
7429
|
+
shell: true,
|
|
7430
|
+
stdio: "inherit"
|
|
7431
|
+
});
|
|
7432
|
+
} catch (error) {
|
|
7433
|
+
throw new Error(`Hook failed: ${cmd}`);
|
|
7434
|
+
}
|
|
7435
|
+
}
|
|
7436
|
+
}
|
|
7437
|
+
/**
|
|
7438
|
+
* Replace variables in command
|
|
7439
|
+
*/
|
|
7440
|
+
replaceVariables(cmd) {
|
|
7441
|
+
let result = cmd;
|
|
7442
|
+
for (const [key, value] of Object.entries(this.variables)) {
|
|
7443
|
+
result = result.replace(new RegExp(`\\{\\{${key}\\}\\}`, "g"), value);
|
|
7444
|
+
}
|
|
7445
|
+
return result;
|
|
7446
|
+
}
|
|
7447
|
+
};
|
|
7448
|
+
|
|
7449
|
+
// src/commands/kit/create.ts
|
|
7450
|
+
function createKitCreateCommand() {
|
|
7451
|
+
return new Command31("create").description("Create a new project from a starter kit").argument("<slug>", "Starter kit slug").argument("[directory]", "Project directory (default: ./<slug>)").option("-y, --yes", "Auto mode - use defaults, no prompts").option("--name <name>", "Project name").option("--skip-install", "Skip dependency installation").option("--skip-git", "Skip git initialization").option("--skip-framework", "Skip framework apply").option("--skip-ide", "Skip IDE sync").action(async (slug, directory, options) => {
|
|
7452
|
+
const configService = new ConfigService();
|
|
7453
|
+
const config = await configService.load();
|
|
7454
|
+
if (!config) {
|
|
7455
|
+
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
7456
|
+
}
|
|
7457
|
+
const isAutoMode = options.yes === true;
|
|
7458
|
+
const kitService = new StarterKitService();
|
|
7459
|
+
console.log(`\u{1F4E6} Fetching starter kit: ${slug}...`);
|
|
7460
|
+
const kit = await kitService.get(config, slug);
|
|
7461
|
+
if (kit.config.requiredTools && kit.config.requiredTools.length > 0) {
|
|
7462
|
+
console.log("\u{1F50D} Checking required tools...");
|
|
7463
|
+
for (const tool of kit.config.requiredTools) {
|
|
7464
|
+
try {
|
|
7465
|
+
await execa2("which", [tool]);
|
|
7466
|
+
} catch {
|
|
7467
|
+
console.warn(`\u26A0\uFE0F Warning: Required tool '${tool}' not found`);
|
|
7468
|
+
}
|
|
7469
|
+
}
|
|
7470
|
+
}
|
|
7471
|
+
const targetDir = directory || join5(process.cwd(), options.name || slug);
|
|
7472
|
+
try {
|
|
7473
|
+
await fs10.access(targetDir);
|
|
7474
|
+
throw new Error(`Directory already exists: ${targetDir}`);
|
|
7475
|
+
} catch (error) {
|
|
7476
|
+
if (error.code !== "ENOENT") {
|
|
7477
|
+
throw error;
|
|
7478
|
+
}
|
|
7479
|
+
}
|
|
7480
|
+
if (kit.config.hooks?.preInit && kit.config.hooks.preInit.length > 0) {
|
|
7481
|
+
console.log("\u{1F527} Running pre-init hooks...");
|
|
7482
|
+
const hookExecutor = new HookExecutor(process.cwd(), {});
|
|
7483
|
+
await hookExecutor.run(kit.config.hooks.preInit);
|
|
7484
|
+
}
|
|
7485
|
+
console.log("\u{1F4E5} Downloading template...");
|
|
7486
|
+
await kitService.downloadAndExtract(config, slug, targetDir, (percent) => {
|
|
7487
|
+
if (percent === 100) {
|
|
7488
|
+
console.log(" \u2713 Downloaded and extracted");
|
|
7489
|
+
}
|
|
7490
|
+
});
|
|
7491
|
+
if (kit.config.hooks?.postExtract && kit.config.hooks.postExtract.length > 0) {
|
|
7492
|
+
console.log("\u{1F4C4} Setting up environment...");
|
|
7493
|
+
const hookExecutor = new HookExecutor(targetDir, {});
|
|
7494
|
+
await hookExecutor.run(kit.config.hooks.postExtract);
|
|
7495
|
+
}
|
|
7496
|
+
const variables = {};
|
|
7497
|
+
if (kit.config.variables && kit.config.variables.length > 0) {
|
|
7498
|
+
if (isAutoMode) {
|
|
7499
|
+
console.log("\u{1F4DD} Using default values (auto mode)");
|
|
7500
|
+
for (const v of kit.config.variables) {
|
|
7501
|
+
variables[v.name] = options.name && v.name === "PROJECT_NAME" ? options.name : v.default || "";
|
|
7502
|
+
}
|
|
7503
|
+
} else {
|
|
7504
|
+
console.log("\u{1F4DD} Please provide project details:");
|
|
7505
|
+
for (const v of kit.config.variables) {
|
|
7506
|
+
if (v.type === "select" && v.options) {
|
|
7507
|
+
const answer = await select2({
|
|
7508
|
+
message: v.prompt,
|
|
7509
|
+
choices: v.options.map((opt) => ({ name: opt, value: opt })),
|
|
7510
|
+
default: v.default
|
|
7511
|
+
});
|
|
7512
|
+
variables[v.name] = answer;
|
|
7513
|
+
} else {
|
|
7514
|
+
const answer = await input({
|
|
7515
|
+
message: v.prompt,
|
|
7516
|
+
default: v.default
|
|
7517
|
+
});
|
|
7518
|
+
variables[v.name] = answer;
|
|
7519
|
+
}
|
|
7520
|
+
}
|
|
7521
|
+
}
|
|
7522
|
+
}
|
|
7523
|
+
if (Object.keys(variables).length > 0) {
|
|
7524
|
+
await applyVariableSubstitution(targetDir, variables);
|
|
7525
|
+
}
|
|
7526
|
+
if (!options.skipFramework && kit.config.framework?.apply) {
|
|
7527
|
+
console.log("\u{1F916} Applying jai1 framework...");
|
|
7528
|
+
const componentsService = new ComponentsService(targetDir);
|
|
7529
|
+
for (const filepath of kit.config.framework.components) {
|
|
7530
|
+
console.log(` \u{1F4E5} Installing ${filepath}...`);
|
|
7531
|
+
await componentsService.install(config, filepath);
|
|
7532
|
+
}
|
|
7533
|
+
console.log(" \u2713 Framework components applied");
|
|
7534
|
+
}
|
|
7535
|
+
if (!options.skipGit && kit.config.git?.init) {
|
|
7536
|
+
console.log("\u{1F527} Initializing git repository...");
|
|
7537
|
+
await execa2("git", ["init"], { cwd: targetDir });
|
|
7538
|
+
await execa2("git", ["add", "."], { cwd: targetDir });
|
|
7539
|
+
const commitMsg = kit.config.git.initialCommit || "Initial commit";
|
|
7540
|
+
await execa2("git", ["commit", "-m", commitMsg], { cwd: targetDir });
|
|
7541
|
+
console.log(" \u2713 Git initialized");
|
|
7542
|
+
}
|
|
7543
|
+
if (!options.skipInstall && kit.config.hooks?.postInit) {
|
|
7544
|
+
console.log("\u{1F527} Running setup...");
|
|
7545
|
+
const hookExecutor = new HookExecutor(targetDir, variables);
|
|
7546
|
+
await hookExecutor.run(kit.config.hooks.postInit);
|
|
7547
|
+
}
|
|
7548
|
+
if (!options.skipIde) {
|
|
7549
|
+
const ideChoices = [
|
|
7550
|
+
{ name: "Cursor", value: "cursor" },
|
|
7551
|
+
{ name: "Windsurf", value: "windsurf" },
|
|
7552
|
+
{ name: "VSCode", value: "vscode" },
|
|
7553
|
+
{ name: "Claude Code", value: "claude-code" },
|
|
7554
|
+
{ name: "Antigravity", value: "antigravity" }
|
|
7555
|
+
];
|
|
7556
|
+
let selectedIdes = [];
|
|
7557
|
+
if (isAutoMode) {
|
|
7558
|
+
selectedIdes = kit.config.ide?.defaultTargets || [];
|
|
7559
|
+
if (selectedIdes.length > 0) {
|
|
7560
|
+
console.log(`\u{1F5A5}\uFE0F Syncing to IDEs: ${selectedIdes.join(", ")}`);
|
|
7561
|
+
}
|
|
7562
|
+
} else {
|
|
7563
|
+
const defaultTargets = kit.config.ide?.defaultTargets || [];
|
|
7564
|
+
const answer = await checkbox3({
|
|
7565
|
+
message: "Ch\u1ECDn IDE \u0111\u1EC3 sync framework:",
|
|
7566
|
+
choices: ideChoices.map((c) => ({
|
|
7567
|
+
...c,
|
|
7568
|
+
checked: defaultTargets.includes(c.value)
|
|
7569
|
+
}))
|
|
7570
|
+
});
|
|
7571
|
+
selectedIdes = answer;
|
|
7572
|
+
}
|
|
7573
|
+
if (selectedIdes.length > 0) {
|
|
7574
|
+
await execa2("jai1", ["ide", "sync", ...selectedIdes], {
|
|
7575
|
+
cwd: targetDir,
|
|
7576
|
+
stdio: "inherit"
|
|
7577
|
+
});
|
|
7578
|
+
}
|
|
7579
|
+
}
|
|
7580
|
+
console.log("\n\u2705 Project created successfully!");
|
|
7581
|
+
console.log(`\u{1F4C1} Location: ${targetDir}`);
|
|
7582
|
+
console.log("\n\u{1F4A1} Next steps:");
|
|
7583
|
+
console.log(` cd ${targetDir}`);
|
|
7584
|
+
console.log(" jai1 apply # Add more framework components");
|
|
7585
|
+
});
|
|
7586
|
+
}
|
|
7587
|
+
async function applyVariableSubstitution(dir, variables) {
|
|
7588
|
+
const files = await getAllFiles(dir);
|
|
7589
|
+
for (const file of files) {
|
|
7590
|
+
let content = await fs10.readFile(file, "utf-8");
|
|
7591
|
+
let modified = false;
|
|
7592
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
7593
|
+
const regex = new RegExp(`\\{\\{${key}\\}\\}`, "g");
|
|
7594
|
+
if (regex.test(content)) {
|
|
7595
|
+
content = content.replace(regex, value);
|
|
7596
|
+
modified = true;
|
|
7597
|
+
}
|
|
7598
|
+
}
|
|
7599
|
+
if (modified) {
|
|
7600
|
+
await fs10.writeFile(file, content, "utf-8");
|
|
7601
|
+
}
|
|
7602
|
+
}
|
|
7603
|
+
}
|
|
7604
|
+
async function getAllFiles(dir) {
|
|
7605
|
+
const files = [];
|
|
7606
|
+
const entries = await fs10.readdir(dir, { withFileTypes: true });
|
|
7607
|
+
for (const entry of entries) {
|
|
7608
|
+
const fullPath = join5(dir, entry.name);
|
|
7609
|
+
if (entry.isDirectory()) {
|
|
7610
|
+
if (!entry.name.startsWith(".") && entry.name !== "node_modules") {
|
|
7611
|
+
files.push(...await getAllFiles(fullPath));
|
|
7612
|
+
}
|
|
7613
|
+
} else {
|
|
7614
|
+
files.push(fullPath);
|
|
7615
|
+
}
|
|
7616
|
+
}
|
|
7617
|
+
return files;
|
|
7618
|
+
}
|
|
7619
|
+
|
|
7620
|
+
// src/commands/kit/index.ts
|
|
7621
|
+
function createKitCommand() {
|
|
7622
|
+
const cmd = new Command32("kit").description("Manage starter kits for new projects").action(() => {
|
|
7623
|
+
cmd.help();
|
|
7624
|
+
});
|
|
7625
|
+
cmd.addCommand(createKitListCommand());
|
|
7626
|
+
cmd.addCommand(createKitInfoCommand());
|
|
7627
|
+
cmd.addCommand(createKitCreateCommand());
|
|
7628
|
+
return cmd;
|
|
7629
|
+
}
|
|
7630
|
+
|
|
7631
|
+
// src/commands/upgrade.ts
|
|
7632
|
+
import { Command as Command33 } from "commander";
|
|
7242
7633
|
import { confirm as confirm4 } from "@inquirer/prompts";
|
|
7243
7634
|
import { execSync } from "child_process";
|
|
7244
7635
|
var colors2 = {
|
|
@@ -7250,7 +7641,7 @@ var colors2 = {
|
|
|
7250
7641
|
bold: "\x1B[1m"
|
|
7251
7642
|
};
|
|
7252
7643
|
function createUpgradeCommand() {
|
|
7253
|
-
return new
|
|
7644
|
+
return new Command33("upgrade").description("Upgrade jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force upgrade without confirmation").action(async (options) => {
|
|
7254
7645
|
await handleUpgrade(options);
|
|
7255
7646
|
});
|
|
7256
7647
|
}
|
|
@@ -7398,11 +7789,11 @@ function getInstallCommand(packageManager2) {
|
|
|
7398
7789
|
}
|
|
7399
7790
|
|
|
7400
7791
|
// src/commands/clean.ts
|
|
7401
|
-
import { Command as
|
|
7402
|
-
import { confirm as confirm5, select as
|
|
7403
|
-
import { join as
|
|
7792
|
+
import { Command as Command34 } from "commander";
|
|
7793
|
+
import { confirm as confirm5, select as select3 } from "@inquirer/prompts";
|
|
7794
|
+
import { join as join6 } from "path";
|
|
7404
7795
|
function createCleanCommand() {
|
|
7405
|
-
return new
|
|
7796
|
+
return new Command34("clean").description("Clean up backups, cache, and temporary files").option("-y, --yes", "Skip confirmation").option("--backups", "Clean only backup files").option("--all", "Clean all (backups + cache)").action(async (options) => {
|
|
7406
7797
|
await handleClean(options);
|
|
7407
7798
|
});
|
|
7408
7799
|
}
|
|
@@ -7413,7 +7804,7 @@ async function handleClean(options) {
|
|
|
7413
7804
|
{
|
|
7414
7805
|
name: "Backups",
|
|
7415
7806
|
description: "Component backup files (.jai1_backup/)",
|
|
7416
|
-
path:
|
|
7807
|
+
path: join6(cwd, ".jai1_backup"),
|
|
7417
7808
|
check: async () => {
|
|
7418
7809
|
const backups = await service.listBackups(cwd);
|
|
7419
7810
|
return { exists: backups.length > 0, count: backups.length };
|
|
@@ -7463,7 +7854,7 @@ async function handleClean(options) {
|
|
|
7463
7854
|
console.log(` Path: ${target.path}
|
|
7464
7855
|
`);
|
|
7465
7856
|
}
|
|
7466
|
-
const action = await
|
|
7857
|
+
const action = await select3({
|
|
7467
7858
|
message: "What do you want to clean?",
|
|
7468
7859
|
choices: [
|
|
7469
7860
|
...availableTargets.map(({ target, info }) => ({
|
|
@@ -7515,7 +7906,7 @@ async function cleanTarget(target, skipConfirm) {
|
|
|
7515
7906
|
}
|
|
7516
7907
|
|
|
7517
7908
|
// src/commands/redmine/check.ts
|
|
7518
|
-
import { Command as
|
|
7909
|
+
import { Command as Command35 } from "commander";
|
|
7519
7910
|
|
|
7520
7911
|
// src/services/redmine-config.service.ts
|
|
7521
7912
|
import { readFile as readFile6 } from "fs/promises";
|
|
@@ -7822,7 +8213,7 @@ async function checkConnectivity(config) {
|
|
|
7822
8213
|
|
|
7823
8214
|
// src/commands/redmine/check.ts
|
|
7824
8215
|
function createRedmineCheckCommand() {
|
|
7825
|
-
const cmd = new
|
|
8216
|
+
const cmd = new Command35("check").description("Check Redmine connectivity").option("-c, --config <path>", "Config file path", "redmine.config.yaml").option("--json", "Output as JSON").action(async (options) => {
|
|
7826
8217
|
await handleRedmineCheck(options);
|
|
7827
8218
|
});
|
|
7828
8219
|
return cmd;
|
|
@@ -7850,7 +8241,7 @@ async function handleRedmineCheck(options) {
|
|
|
7850
8241
|
}
|
|
7851
8242
|
|
|
7852
8243
|
// src/commands/redmine/sync-issue.ts
|
|
7853
|
-
import { Command as
|
|
8244
|
+
import { Command as Command36 } from "commander";
|
|
7854
8245
|
|
|
7855
8246
|
// src/sync-issue.ts
|
|
7856
8247
|
import { resolve as resolve3, relative } from "path";
|
|
@@ -8226,7 +8617,7 @@ function extractIssueIdFromUrl(url) {
|
|
|
8226
8617
|
|
|
8227
8618
|
// src/commands/redmine/sync-issue.ts
|
|
8228
8619
|
function createSyncIssueCommand() {
|
|
8229
|
-
const cmd = new
|
|
8620
|
+
const cmd = new Command36("issue").description("Sync a single issue").option("-i, --id <number>", "Issue ID").option("-u, --url <url>", "Issue URL").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
8230
8621
|
await handleSyncIssue(options);
|
|
8231
8622
|
});
|
|
8232
8623
|
return cmd;
|
|
@@ -8270,7 +8661,7 @@ async function handleSyncIssue(options) {
|
|
|
8270
8661
|
}
|
|
8271
8662
|
|
|
8272
8663
|
// src/commands/redmine/sync-project.ts
|
|
8273
|
-
import { Command as
|
|
8664
|
+
import { Command as Command37 } from "commander";
|
|
8274
8665
|
|
|
8275
8666
|
// src/sync-project.ts
|
|
8276
8667
|
async function syncProject(config, options = {}) {
|
|
@@ -8340,7 +8731,7 @@ async function syncProject(config, options = {}) {
|
|
|
8340
8731
|
|
|
8341
8732
|
// src/commands/redmine/sync-project.ts
|
|
8342
8733
|
function createSyncProjectCommand() {
|
|
8343
|
-
const cmd = new
|
|
8734
|
+
const cmd = new Command37("project").description("Sync all issues in a project").option("-s, --status <status>", "Filter by status (default: *)", "*").option("--updated-since <date>", "Only sync issues updated since YYYY-MM-DD").option("--concurrency <number>", "Number of concurrent requests").option("--page-size <number>", "Page size for API requests").option("--dry-run", "Preview without making changes").option("-c, --config <path>", "Config file path").option("-o, --output-dir <path>", "Output directory").option("--json", "Output as JSON").action(async (options) => {
|
|
8344
8735
|
await handleSyncProject(options);
|
|
8345
8736
|
});
|
|
8346
8737
|
return cmd;
|
|
@@ -8395,12 +8786,12 @@ async function handleSyncProject(options) {
|
|
|
8395
8786
|
}
|
|
8396
8787
|
|
|
8397
8788
|
// src/commands/framework/info.ts
|
|
8398
|
-
import { Command as
|
|
8399
|
-
import { promises as
|
|
8400
|
-
import { join as
|
|
8789
|
+
import { Command as Command38 } from "commander";
|
|
8790
|
+
import { promises as fs11 } from "fs";
|
|
8791
|
+
import { join as join7 } from "path";
|
|
8401
8792
|
import { homedir as homedir5 } from "os";
|
|
8402
8793
|
function createInfoCommand() {
|
|
8403
|
-
const cmd = new
|
|
8794
|
+
const cmd = new Command38("info").description("Show jai1-client configuration and status").option("--json", "Output as JSON").option("--verbose", "Show detailed information").action(async (options) => {
|
|
8404
8795
|
await handleInfo(options);
|
|
8405
8796
|
});
|
|
8406
8797
|
return cmd;
|
|
@@ -8411,7 +8802,7 @@ async function handleInfo(options) {
|
|
|
8411
8802
|
if (!config) {
|
|
8412
8803
|
throw new ValidationError('Not initialized. Run "jai1 auth" first.');
|
|
8413
8804
|
}
|
|
8414
|
-
const frameworkPath =
|
|
8805
|
+
const frameworkPath = join7(homedir5(), ".jai1", "framework");
|
|
8415
8806
|
const projectStatus = await getProjectStatus2();
|
|
8416
8807
|
const info = {
|
|
8417
8808
|
configPath: configService.getConfigPath(),
|
|
@@ -8446,9 +8837,9 @@ function maskKey3(key) {
|
|
|
8446
8837
|
return "****" + key.slice(-4);
|
|
8447
8838
|
}
|
|
8448
8839
|
async function getProjectStatus2() {
|
|
8449
|
-
const projectJai1 =
|
|
8840
|
+
const projectJai1 = join7(process.cwd(), ".jai1");
|
|
8450
8841
|
try {
|
|
8451
|
-
await
|
|
8842
|
+
await fs11.access(projectJai1);
|
|
8452
8843
|
return { exists: true, version: "Synced" };
|
|
8453
8844
|
} catch {
|
|
8454
8845
|
return { exists: false };
|
|
@@ -8456,7 +8847,7 @@ async function getProjectStatus2() {
|
|
|
8456
8847
|
}
|
|
8457
8848
|
|
|
8458
8849
|
// src/commands/self-update.ts
|
|
8459
|
-
import { Command as
|
|
8850
|
+
import { Command as Command39 } from "commander";
|
|
8460
8851
|
import { confirm as confirm6 } from "@inquirer/prompts";
|
|
8461
8852
|
import { execSync as execSync2 } from "child_process";
|
|
8462
8853
|
var colors3 = {
|
|
@@ -8468,7 +8859,7 @@ var colors3 = {
|
|
|
8468
8859
|
bold: "\x1B[1m"
|
|
8469
8860
|
};
|
|
8470
8861
|
function createSelfUpdateCommand() {
|
|
8471
|
-
return new
|
|
8862
|
+
return new Command39("self-update").description("Update jai1-client to the latest version").option("--check", "Only check for updates without installing").option("--force", "Force update without confirmation").action(async (options) => {
|
|
8472
8863
|
await handleSelfUpdate(options);
|
|
8473
8864
|
});
|
|
8474
8865
|
}
|
|
@@ -8608,10 +8999,10 @@ function getInstallCommand2(packageManager2) {
|
|
|
8608
8999
|
}
|
|
8609
9000
|
|
|
8610
9001
|
// src/commands/clear-backups.ts
|
|
8611
|
-
import { Command as
|
|
9002
|
+
import { Command as Command40 } from "commander";
|
|
8612
9003
|
import { confirm as confirm7 } from "@inquirer/prompts";
|
|
8613
9004
|
function createClearBackupsCommand() {
|
|
8614
|
-
return new
|
|
9005
|
+
return new Command40("clear-backups").description("Clear backup files").option("-y, --yes", "Skip confirmation").action(async (options) => {
|
|
8615
9006
|
const service = new ComponentsService();
|
|
8616
9007
|
const backups = await service.listBackups(process.cwd());
|
|
8617
9008
|
if (backups.length === 0) {
|
|
@@ -8636,9 +9027,9 @@ function createClearBackupsCommand() {
|
|
|
8636
9027
|
}
|
|
8637
9028
|
|
|
8638
9029
|
// src/commands/vscode/index.ts
|
|
8639
|
-
import { Command as
|
|
8640
|
-
import { checkbox as
|
|
8641
|
-
import
|
|
9030
|
+
import { Command as Command41 } from "commander";
|
|
9031
|
+
import { checkbox as checkbox4, confirm as confirm8, select as select4 } from "@inquirer/prompts";
|
|
9032
|
+
import fs12 from "fs/promises";
|
|
8642
9033
|
import path6 from "path";
|
|
8643
9034
|
import { existsSync as existsSync3 } from "fs";
|
|
8644
9035
|
var PERFORMANCE_GROUPS2 = {
|
|
@@ -8776,7 +9167,7 @@ var PERFORMANCE_GROUPS2 = {
|
|
|
8776
9167
|
}
|
|
8777
9168
|
};
|
|
8778
9169
|
function createVSCodeCommand() {
|
|
8779
|
-
const vscodeCommand = new
|
|
9170
|
+
const vscodeCommand = new Command41("vscode").description("Qu\u1EA3n l\xFD c\xE0i \u0111\u1EB7t VSCode cho d\u1EF1 \xE1n hi\u1EC7n t\u1EA1i");
|
|
8780
9171
|
vscodeCommand.action(async () => {
|
|
8781
9172
|
await interactiveMode2();
|
|
8782
9173
|
});
|
|
@@ -8820,7 +9211,7 @@ async function interactiveMode2() {
|
|
|
8820
9211
|
console.log("\u2502 \u2022 Nh\u1EA5n ENTER \u0111\u1EC3 x\xE1c nh\u1EADn v\xE0 \xE1p d\u1EE5ng \u2502");
|
|
8821
9212
|
console.log("\u2502 \u2022 Nh\u1EA5n Ctrl+C \u0111\u1EC3 h\u1EE7y \u2502");
|
|
8822
9213
|
console.log("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F\n");
|
|
8823
|
-
const action = await
|
|
9214
|
+
const action = await select4({
|
|
8824
9215
|
message: "B\u1EA1n mu\u1ED1n l\xE0m g\xEC?",
|
|
8825
9216
|
choices: [
|
|
8826
9217
|
{ name: "\u2705 Enable c\xE1c nh\xF3m t\u1ED1i \u01B0u", value: "enable" },
|
|
@@ -8844,7 +9235,7 @@ async function selectGroupsToApply2(action) {
|
|
|
8844
9235
|
value: key
|
|
8845
9236
|
}));
|
|
8846
9237
|
try {
|
|
8847
|
-
const selectedGroups = await
|
|
9238
|
+
const selectedGroups = await checkbox4({
|
|
8848
9239
|
message: `Ch\u1ECDn c\xE1c nh\xF3m \u0111\u1EC3 ${action === "enable" ? "enable" : "disable"} (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):`,
|
|
8849
9240
|
choices
|
|
8850
9241
|
});
|
|
@@ -8869,13 +9260,13 @@ async function applyGroups2(groupKeys, action) {
|
|
|
8869
9260
|
return;
|
|
8870
9261
|
}
|
|
8871
9262
|
if (!existsSync3(vscodeDir)) {
|
|
8872
|
-
await
|
|
9263
|
+
await fs12.mkdir(vscodeDir, { recursive: true });
|
|
8873
9264
|
console.log("\u{1F4C1} \u0110\xE3 t\u1EA1o th\u01B0 m\u1EE5c .vscode/");
|
|
8874
9265
|
}
|
|
8875
9266
|
let currentSettings = {};
|
|
8876
9267
|
if (existsSync3(settingsPath)) {
|
|
8877
9268
|
try {
|
|
8878
|
-
const content = await
|
|
9269
|
+
const content = await fs12.readFile(settingsPath, "utf-8");
|
|
8879
9270
|
currentSettings = JSON.parse(content);
|
|
8880
9271
|
console.log("\u{1F4C4} \u0110\xE3 \u0111\u1ECDc c\xE0i \u0111\u1EB7t hi\u1EC7n t\u1EA1i t\u1EEB settings.json");
|
|
8881
9272
|
} catch {
|
|
@@ -8915,7 +9306,7 @@ async function applyGroups2(groupKeys, action) {
|
|
|
8915
9306
|
}
|
|
8916
9307
|
}
|
|
8917
9308
|
}
|
|
8918
|
-
await
|
|
9309
|
+
await fs12.writeFile(settingsPath, JSON.stringify(newSettings, null, 2));
|
|
8919
9310
|
console.log(`
|
|
8920
9311
|
\u2705 \u0110\xE3 c\u1EADp nh\u1EADt c\xE0i \u0111\u1EB7t VSCode t\u1EA1i: ${settingsPath}`);
|
|
8921
9312
|
console.log("\u{1F4A1} M\u1EB9o: Kh\u1EDFi \u0111\u1ED9ng l\u1EA1i VSCode \u0111\u1EC3 \xE1p d\u1EE5ng c\xE1c thay \u0111\u1ED5i.");
|
|
@@ -8936,7 +9327,7 @@ async function resetSettings2(groupKeys) {
|
|
|
8936
9327
|
return;
|
|
8937
9328
|
}
|
|
8938
9329
|
if (groupKeys.length === 0) {
|
|
8939
|
-
await
|
|
9330
|
+
await fs12.unlink(settingsPath);
|
|
8940
9331
|
console.log("\n\u2705 \u0110\xE3 x\xF3a file settings.json");
|
|
8941
9332
|
} else {
|
|
8942
9333
|
await applyGroups2(groupKeys, "disable");
|
|
@@ -8947,9 +9338,9 @@ async function resetSettings2(groupKeys) {
|
|
|
8947
9338
|
// src/commands/guide.ts
|
|
8948
9339
|
import React40 from "react";
|
|
8949
9340
|
import { render as render6 } from "ink";
|
|
8950
|
-
import { Command as
|
|
9341
|
+
import { Command as Command42 } from "commander";
|
|
8951
9342
|
function createGuideCommand() {
|
|
8952
|
-
const cmd = new
|
|
9343
|
+
const cmd = new Command42("guide").description("Interactive guide center for Agentic Coding").option("--topic <topic>", "Open specific topic (intro, rules, workflows, prompts, skills)").action(async (options) => {
|
|
8953
9344
|
const { waitUntilExit } = render6(
|
|
8954
9345
|
React40.createElement(GuideApp, {
|
|
8955
9346
|
initialTopic: options.topic,
|
|
@@ -8966,9 +9357,9 @@ function createGuideCommand() {
|
|
|
8966
9357
|
// src/commands/context.ts
|
|
8967
9358
|
import React41 from "react";
|
|
8968
9359
|
import { render as render7 } from "ink";
|
|
8969
|
-
import { Command as
|
|
9360
|
+
import { Command as Command43 } from "commander";
|
|
8970
9361
|
function createContextCommand() {
|
|
8971
|
-
const cmd = new
|
|
9362
|
+
const cmd = new Command43("context").description("Kh\xE1m ph\xE1 v\xE0 qu\u1EA3n l\xFD context d\u1EF1 \xE1n cho c\xE1c IDE").option("--ide <ide>", "M\u1EDF tr\u1EF1c ti\u1EBFp IDE c\u1EE5 th\u1EC3 (cursor, windsurf, antigravity, jai1)").option("--type <type>", "Hi\u1EC3n th\u1ECB lo\u1EA1i context c\u1EE5 th\u1EC3 (rules, workflows, skills, agents, prompts)").option("--stats", "Hi\u1EC3n th\u1ECB th\u1ED1ng k\xEA context (non-interactive)").action(async (options) => {
|
|
8972
9363
|
let initialIDE;
|
|
8973
9364
|
if (options.ide) {
|
|
8974
9365
|
const validIDEs = ["cursor", "windsurf", "antigravity", "jai1"];
|
|
@@ -9045,10 +9436,10 @@ async function printStats2() {
|
|
|
9045
9436
|
}
|
|
9046
9437
|
|
|
9047
9438
|
// src/commands/migrate-ide.ts
|
|
9048
|
-
import { Command as
|
|
9049
|
-
import { checkbox as
|
|
9439
|
+
import { Command as Command44 } from "commander";
|
|
9440
|
+
import { checkbox as checkbox5, confirm as confirm9 } from "@inquirer/prompts";
|
|
9050
9441
|
function createMigrateIdeCommand() {
|
|
9051
|
-
const cmd = new
|
|
9442
|
+
const cmd = new Command44("migrate-ide").description("Migrate .jai1 rules v\xE0 workflows sang IDEs (Cursor, Windsurf, Claude Code, etc.)").option("--ide <ides...>", "Target IDEs (cursor, windsurf, antigravity, claudecode, opencode)").option("--type <types...>", "Content types (rules, workflows, commands)").option("--dry-run", "Preview changes without writing files").action(async (options) => {
|
|
9052
9443
|
await runMigrateIde(options);
|
|
9053
9444
|
});
|
|
9054
9445
|
return cmd;
|
|
@@ -9076,7 +9467,7 @@ async function runMigrateIde(options) {
|
|
|
9076
9467
|
value: ide
|
|
9077
9468
|
};
|
|
9078
9469
|
});
|
|
9079
|
-
selectedIdes = await
|
|
9470
|
+
selectedIdes = await checkbox5({
|
|
9080
9471
|
message: "Ch\u1ECDn IDE(s) \u0111\u1EC3 migrate (SPACE \u0111\u1EC3 ch\u1ECDn, ENTER \u0111\u1EC3 x\xE1c nh\u1EADn):",
|
|
9081
9472
|
choices: ideChoices
|
|
9082
9473
|
});
|
|
@@ -9095,7 +9486,7 @@ async function runMigrateIde(options) {
|
|
|
9095
9486
|
{ name: `Workflows (${content.workflows.length} files)`, value: "workflows" },
|
|
9096
9487
|
{ name: `Commands (${content.commands.length} files)`, value: "commands" }
|
|
9097
9488
|
];
|
|
9098
|
-
selectedTypes = await
|
|
9489
|
+
selectedTypes = await checkbox5({
|
|
9099
9490
|
message: "Ch\u1ECDn content types \u0111\u1EC3 migrate:",
|
|
9100
9491
|
choices: typeChoices
|
|
9101
9492
|
});
|
|
@@ -9154,7 +9545,7 @@ async function runMigrateIde(options) {
|
|
|
9154
9545
|
}
|
|
9155
9546
|
|
|
9156
9547
|
// src/cli.ts
|
|
9157
|
-
var program = new
|
|
9548
|
+
var program = new Command45();
|
|
9158
9549
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
9159
9550
|
console.log(package_default.version);
|
|
9160
9551
|
if (!process.argv.includes("--skip-update-check")) {
|
|
@@ -9176,11 +9567,12 @@ program.addCommand(createOpenAiKeysCommand());
|
|
|
9176
9567
|
program.addCommand(createStatsCommand());
|
|
9177
9568
|
program.addCommand(createTranslateCommand());
|
|
9178
9569
|
program.addCommand(createUtilsCommand());
|
|
9570
|
+
program.addCommand(createKitCommand());
|
|
9179
9571
|
program.addCommand(createUpgradeCommand());
|
|
9180
9572
|
program.addCommand(createCleanCommand());
|
|
9181
|
-
var redmineCommand = new
|
|
9573
|
+
var redmineCommand = new Command45("redmine").description("Redmine context sync commands");
|
|
9182
9574
|
redmineCommand.addCommand(createRedmineCheckCommand());
|
|
9183
|
-
var syncCommand = new
|
|
9575
|
+
var syncCommand = new Command45("sync").description("Sync Redmine issues to markdown files");
|
|
9184
9576
|
syncCommand.addCommand(createSyncIssueCommand());
|
|
9185
9577
|
syncCommand.addCommand(createSyncProjectCommand());
|
|
9186
9578
|
redmineCommand.addCommand(syncCommand);
|