@iloom/cli 0.5.1 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BranchNamingService-GCCWB3LK.js → BranchNamingService-B5PVRR7F.js} +4 -4
- package/dist/ClaudeContextManager-PQ46VILL.js +14 -0
- package/dist/ClaudeService-6OMO552H.js +13 -0
- package/dist/GitHubService-S2OGUTDR.js +12 -0
- package/dist/{LoomLauncher-JNWBMHES.js → LoomLauncher-ZHDTPKED.js} +13 -16
- package/dist/{LoomLauncher-JNWBMHES.js.map → LoomLauncher-ZHDTPKED.js.map} +1 -1
- package/dist/MetadataManager-DFI73J3G.js +10 -0
- package/dist/PRManager-OCSB2HPT.js +14 -0
- package/dist/PromptTemplateManager-5GNF7FCP.js +9 -0
- package/dist/{SettingsManager-XPR4TEQL.js → SettingsManager-CNYBGXDT.js} +3 -3
- package/dist/SettingsMigrationManager-KZKDG66H.js +10 -0
- package/dist/{chunk-OEGECBFS.js → chunk-3PT7RKL5.js} +4 -4
- package/dist/{chunk-WUQQNE63.js → chunk-433MOLAU.js} +44 -7
- package/dist/chunk-433MOLAU.js.map +1 -0
- package/dist/{chunk-LN4H3A6A.js → chunk-53OMUNUN.js} +5 -5
- package/dist/{chunk-THF25ICZ.js → chunk-5F6IWWRS.js} +2 -2
- package/dist/{chunk-P2ZQ5LKB.js → chunk-5IWU3HXE.js} +5 -5
- package/dist/{chunk-QIUJPPJQ.js → chunk-5TXLVEXT.js} +3 -3
- package/dist/{chunk-TSLKDFAF.js → chunk-66BMJ25W.js} +7 -7
- package/dist/{chunk-6UIGZD2N.js → chunk-6MLEBAYZ.js} +2 -2
- package/dist/{chunk-BVIK2P6P.js → chunk-7HIRPCKU.js} +4 -4
- package/dist/{chunk-UNXRACJ7.js → chunk-7LSSNB7Y.js} +3 -3
- package/dist/{chunk-QHA67Q7A.js → chunk-7Q66W4OH.js} +2 -2
- package/dist/{chunk-RUC7OULH.js → chunk-AEIMYF4P.js} +6 -8
- package/dist/{chunk-RUC7OULH.js.map → chunk-AEIMYF4P.js.map} +1 -1
- package/dist/{chunk-MD6HA5IK.js → chunk-B2UO6EYE.js} +2 -2
- package/dist/{chunk-YZTDGPFB.js → chunk-CFUWQHCJ.js} +2 -2
- package/dist/{chunk-UYWAESOT.js → chunk-F2PWIRV4.js} +3 -3
- package/dist/{chunk-PSFVTBM7.js → chunk-FXDYIV3K.js} +2 -2
- package/dist/{chunk-CDQEK2WD.js → chunk-FXJKNVZW.js} +5 -5
- package/dist/{chunk-3CMGCRB5.js → chunk-HMMO2LDS.js} +3 -3
- package/dist/{chunk-OOU3DKNT.js → chunk-IDUICCZY.js} +2 -2
- package/dist/{chunk-HABINPX2.js → chunk-J7GHNTYK.js} +67 -11
- package/dist/chunk-J7GHNTYK.js.map +1 -0
- package/dist/{chunk-DKQ4SUII.js → chunk-K5G5SFWY.js} +2 -2
- package/dist/chunk-K5G5SFWY.js.map +1 -0
- package/dist/{chunk-KO2FOMHL.js → chunk-LT3SGBR7.js} +2 -2
- package/dist/{chunk-VBFDVGAE.js → chunk-LVLRMP7V.js} +2 -2
- package/dist/{chunk-RNZMHJK7.js → chunk-N4ZJVATC.js} +3 -3
- package/dist/chunk-NXMDEL3F.js +54 -0
- package/dist/chunk-NXMDEL3F.js.map +1 -0
- package/dist/{chunk-CDF7ZX2B.js → chunk-O7VL5N6S.js} +2 -2
- package/dist/{chunk-S65T4O6I.js → chunk-QPS6TZUW.js} +3 -3
- package/dist/{chunk-RJKMF6BC.js → chunk-SHVB3EFE.js} +3 -3
- package/dist/chunk-VT4PDUYT.js +578 -0
- package/dist/chunk-VT4PDUYT.js.map +1 -0
- package/dist/{chunk-4YTILIIH.js → chunk-VV66DH6T.js} +8 -8
- package/dist/{chunk-GVRO4PWE.js → chunk-XNNXAAZT.js} +6 -6
- package/dist/{chunk-AS2IRKLU.js → chunk-YU5HVI6B.js} +2 -2
- package/dist/{chunk-6KB7R22U.js → chunk-Z5BM4JWB.js} +25 -24
- package/dist/chunk-Z5BM4JWB.js.map +1 -0
- package/dist/{chunk-SJ2GZ6RF.js → chunk-ZX3GTM7O.js} +2 -2
- package/dist/{claude-ACVXNB6N.js → claude-H33OQMXO.js} +4 -6
- package/dist/{cleanup-LU6NU2NZ.js → cleanup-Y5W3CNUV.js} +20 -22
- package/dist/{cleanup-LU6NU2NZ.js.map → cleanup-Y5W3CNUV.js.map} +1 -1
- package/dist/cli.js +71 -73
- package/dist/cli.js.map +1 -1
- package/dist/{color-ZPIIUADB.js → color-4TJ4P5EY.js} +5 -3
- package/dist/{contribute-RS3DO3WP.js → contribute-K7UXBOML.js} +8 -8
- package/dist/{dev-server-ASH7HJVI.js → dev-server-HNBRWGCD.js} +11 -13
- package/dist/{dev-server-ASH7HJVI.js.map → dev-server-HNBRWGCD.js.map} +1 -1
- package/dist/{feedback-OFVW22UW.js → feedback-567ZH2O7.js} +11 -13
- package/dist/{feedback-OFVW22UW.js.map → feedback-567ZH2O7.js.map} +1 -1
- package/dist/{git-OQAPUPLP.js → git-OV6ADVO7.js} +6 -6
- package/dist/{ignite-NREQ3JRM.js → ignite-3HB3ZBEW.js} +15 -17
- package/dist/{ignite-NREQ3JRM.js.map → ignite-3HB3ZBEW.js.map} +1 -1
- package/dist/index.d.ts +54 -35
- package/dist/index.js +371 -276
- package/dist/index.js.map +1 -1
- package/dist/init-CMIRHFSR.js +19 -0
- package/dist/{installation-detector-6R6YOFVZ.js → installation-detector-VXZOCL6P.js} +3 -3
- package/dist/mcp/issue-management-server.js +62 -7
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-3KBC4A3Y.js +11 -0
- package/dist/{open-KW4NTLXH.js → open-AXE225Z5.js} +11 -13
- package/dist/{open-KW4NTLXH.js.map → open-AXE225Z5.js.map} +1 -1
- package/dist/{projects-QEAEBAT2.js → projects-GVEMCN5R.js} +4 -4
- package/dist/{prompt-A7GGRHSY.js → prompt-3SAZYRUN.js} +3 -3
- package/dist/prompts/session-summary-prompt.txt +58 -4
- package/dist/{rebase-WZHHE5LU.js → rebase-6UIHMUWS.js} +9 -11
- package/dist/{rebase-WZHHE5LU.js.map → rebase-6UIHMUWS.js.map} +1 -1
- package/dist/{recap-33NPZ3ZO.js → recap-XTBNMEMO.js} +12 -19
- package/dist/recap-XTBNMEMO.js.map +1 -0
- package/dist/{remote-73TZ2ADI.js → remote-IJAMOEAP.js} +3 -3
- package/dist/{run-HRYQ7TR7.js → run-H375EYRB.js} +11 -13
- package/dist/{run-HRYQ7TR7.js.map → run-H375EYRB.js.map} +1 -1
- package/dist/{shell-JMU5XTHW.js → shell-33FJCWJQ.js} +9 -11
- package/dist/{shell-JMU5XTHW.js.map → shell-33FJCWJQ.js.map} +1 -1
- package/dist/{summary-4SSGGH7N.js → summary-JUMOCNLR.js} +14 -15
- package/dist/{summary-4SSGGH7N.js.map → summary-JUMOCNLR.js.map} +1 -1
- package/dist/{test-git-6SAIRBUD.js → test-git-CO3BA4BV.js} +6 -6
- package/dist/{test-prefix-RLVRK5ZD.js → test-prefix-HZYSDQYT.js} +6 -6
- package/dist/{test-tabs-3SCJWRKT.js → test-tabs-D3POYOJ5.js} +3 -6
- package/dist/{test-tabs-3SCJWRKT.js.map → test-tabs-D3POYOJ5.js.map} +1 -1
- package/dist/{test-webserver-VPNLAFZ3.js → test-webserver-YVQD42W6.js} +2 -2
- package/dist/{update-LETF5ASC.js → update-5NOHT4SG.js} +4 -4
- package/dist/{update-notifier-H55ZK7NU.js → update-notifier-ARA5SPUW.js} +3 -3
- package/package.json +1 -1
- package/dist/ClaudeContextManager-DQFKIMEP.js +0 -16
- package/dist/ClaudeService-CJS32WG2.js +0 -15
- package/dist/GitHubService-RPM27GWD.js +0 -12
- package/dist/MetadataManager-WXUVXKUS.js +0 -10
- package/dist/PRManager-7DSIMCAD.js +0 -16
- package/dist/PromptTemplateManager-72FEOGT6.js +0 -9
- package/dist/SettingsMigrationManager-EH3J2TCN.js +0 -10
- package/dist/chunk-6KB7R22U.js.map +0 -1
- package/dist/chunk-DKQ4SUII.js.map +0 -1
- package/dist/chunk-HABINPX2.js.map +0 -1
- package/dist/chunk-UYVWLISQ.js +0 -113
- package/dist/chunk-UYVWLISQ.js.map +0 -1
- package/dist/chunk-VAYGNQTE.js +0 -234
- package/dist/chunk-VAYGNQTE.js.map +0 -1
- package/dist/chunk-WUQQNE63.js.map +0 -1
- package/dist/chunk-Z5NXYJIG.js +0 -207
- package/dist/chunk-Z5NXYJIG.js.map +0 -1
- package/dist/init-F6PFMSU5.js +0 -21
- package/dist/neon-helpers-L5CXQ5CT.js +0 -11
- package/dist/recap-33NPZ3ZO.js.map +0 -1
- /package/dist/{BranchNamingService-GCCWB3LK.js.map → BranchNamingService-B5PVRR7F.js.map} +0 -0
- /package/dist/{ClaudeContextManager-DQFKIMEP.js.map → ClaudeContextManager-PQ46VILL.js.map} +0 -0
- /package/dist/{ClaudeService-CJS32WG2.js.map → ClaudeService-6OMO552H.js.map} +0 -0
- /package/dist/{GitHubService-RPM27GWD.js.map → GitHubService-S2OGUTDR.js.map} +0 -0
- /package/dist/{MetadataManager-WXUVXKUS.js.map → MetadataManager-DFI73J3G.js.map} +0 -0
- /package/dist/{PRManager-7DSIMCAD.js.map → PRManager-OCSB2HPT.js.map} +0 -0
- /package/dist/{PromptTemplateManager-72FEOGT6.js.map → PromptTemplateManager-5GNF7FCP.js.map} +0 -0
- /package/dist/{SettingsManager-XPR4TEQL.js.map → SettingsManager-CNYBGXDT.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-EH3J2TCN.js.map → SettingsMigrationManager-KZKDG66H.js.map} +0 -0
- /package/dist/{chunk-OEGECBFS.js.map → chunk-3PT7RKL5.js.map} +0 -0
- /package/dist/{chunk-LN4H3A6A.js.map → chunk-53OMUNUN.js.map} +0 -0
- /package/dist/{chunk-THF25ICZ.js.map → chunk-5F6IWWRS.js.map} +0 -0
- /package/dist/{chunk-P2ZQ5LKB.js.map → chunk-5IWU3HXE.js.map} +0 -0
- /package/dist/{chunk-QIUJPPJQ.js.map → chunk-5TXLVEXT.js.map} +0 -0
- /package/dist/{chunk-TSLKDFAF.js.map → chunk-66BMJ25W.js.map} +0 -0
- /package/dist/{chunk-6UIGZD2N.js.map → chunk-6MLEBAYZ.js.map} +0 -0
- /package/dist/{chunk-BVIK2P6P.js.map → chunk-7HIRPCKU.js.map} +0 -0
- /package/dist/{chunk-UNXRACJ7.js.map → chunk-7LSSNB7Y.js.map} +0 -0
- /package/dist/{chunk-QHA67Q7A.js.map → chunk-7Q66W4OH.js.map} +0 -0
- /package/dist/{chunk-MD6HA5IK.js.map → chunk-B2UO6EYE.js.map} +0 -0
- /package/dist/{chunk-YZTDGPFB.js.map → chunk-CFUWQHCJ.js.map} +0 -0
- /package/dist/{chunk-UYWAESOT.js.map → chunk-F2PWIRV4.js.map} +0 -0
- /package/dist/{chunk-PSFVTBM7.js.map → chunk-FXDYIV3K.js.map} +0 -0
- /package/dist/{chunk-CDQEK2WD.js.map → chunk-FXJKNVZW.js.map} +0 -0
- /package/dist/{chunk-3CMGCRB5.js.map → chunk-HMMO2LDS.js.map} +0 -0
- /package/dist/{chunk-OOU3DKNT.js.map → chunk-IDUICCZY.js.map} +0 -0
- /package/dist/{chunk-KO2FOMHL.js.map → chunk-LT3SGBR7.js.map} +0 -0
- /package/dist/{chunk-VBFDVGAE.js.map → chunk-LVLRMP7V.js.map} +0 -0
- /package/dist/{chunk-RNZMHJK7.js.map → chunk-N4ZJVATC.js.map} +0 -0
- /package/dist/{chunk-CDF7ZX2B.js.map → chunk-O7VL5N6S.js.map} +0 -0
- /package/dist/{chunk-S65T4O6I.js.map → chunk-QPS6TZUW.js.map} +0 -0
- /package/dist/{chunk-RJKMF6BC.js.map → chunk-SHVB3EFE.js.map} +0 -0
- /package/dist/{chunk-4YTILIIH.js.map → chunk-VV66DH6T.js.map} +0 -0
- /package/dist/{chunk-GVRO4PWE.js.map → chunk-XNNXAAZT.js.map} +0 -0
- /package/dist/{chunk-AS2IRKLU.js.map → chunk-YU5HVI6B.js.map} +0 -0
- /package/dist/{chunk-SJ2GZ6RF.js.map → chunk-ZX3GTM7O.js.map} +0 -0
- /package/dist/{claude-ACVXNB6N.js.map → claude-H33OQMXO.js.map} +0 -0
- /package/dist/{color-ZPIIUADB.js.map → color-4TJ4P5EY.js.map} +0 -0
- /package/dist/{contribute-RS3DO3WP.js.map → contribute-K7UXBOML.js.map} +0 -0
- /package/dist/{git-OQAPUPLP.js.map → git-OV6ADVO7.js.map} +0 -0
- /package/dist/{init-F6PFMSU5.js.map → init-CMIRHFSR.js.map} +0 -0
- /package/dist/{installation-detector-6R6YOFVZ.js.map → installation-detector-VXZOCL6P.js.map} +0 -0
- /package/dist/{neon-helpers-L5CXQ5CT.js.map → neon-helpers-3KBC4A3Y.js.map} +0 -0
- /package/dist/{projects-QEAEBAT2.js.map → projects-GVEMCN5R.js.map} +0 -0
- /package/dist/{prompt-A7GGRHSY.js.map → prompt-3SAZYRUN.js.map} +0 -0
- /package/dist/{remote-73TZ2ADI.js.map → remote-IJAMOEAP.js.map} +0 -0
- /package/dist/{test-git-6SAIRBUD.js.map → test-git-CO3BA4BV.js.map} +0 -0
- /package/dist/{test-prefix-RLVRK5ZD.js.map → test-prefix-HZYSDQYT.js.map} +0 -0
- /package/dist/{test-webserver-VPNLAFZ3.js.map → test-webserver-YVQD42W6.js.map} +0 -0
- /package/dist/{update-LETF5ASC.js.map → update-5NOHT4SG.js.map} +0 -0
- /package/dist/{update-notifier-H55ZK7NU.js.map → update-notifier-ARA5SPUW.js.map} +0 -0
package/dist/chunk-UYVWLISQ.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
// src/utils/logger.ts
|
|
4
|
-
import chalk, { Chalk } from "chalk";
|
|
5
|
-
var stdoutChalk = new Chalk({ level: chalk.level });
|
|
6
|
-
var stderrChalk = new Chalk({ level: chalk.level });
|
|
7
|
-
function formatMessage(message, ...args) {
|
|
8
|
-
const formattedArgs = args.map(
|
|
9
|
-
(arg) => typeof arg === "object" ? JSON.stringify(arg, null, 2) : String(arg)
|
|
10
|
-
);
|
|
11
|
-
return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(" ")}` : message;
|
|
12
|
-
}
|
|
13
|
-
function formatWithEmoji(message, emoji, colorFn) {
|
|
14
|
-
if (message.trim()) {
|
|
15
|
-
return colorFn(`${emoji} ${message}`);
|
|
16
|
-
} else {
|
|
17
|
-
return "";
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
var globalDebugEnabled = false;
|
|
21
|
-
var logger = {
|
|
22
|
-
info: (message, ...args) => {
|
|
23
|
-
const formatted = formatMessage(message, ...args);
|
|
24
|
-
const output = formatWithEmoji(formatted, "\u{1F5C2}\uFE0F ", stdoutChalk.blue);
|
|
25
|
-
console.log(output);
|
|
26
|
-
},
|
|
27
|
-
success: (message, ...args) => {
|
|
28
|
-
const formatted = formatMessage(message, ...args);
|
|
29
|
-
const output = formatWithEmoji(formatted, "\u2705", stdoutChalk.green);
|
|
30
|
-
console.log(output);
|
|
31
|
-
},
|
|
32
|
-
warn: (message, ...args) => {
|
|
33
|
-
const formatted = formatMessage(message, ...args);
|
|
34
|
-
const output = formatWithEmoji(formatted, "\u26A0\uFE0F ", stderrChalk.yellow);
|
|
35
|
-
console.error(output);
|
|
36
|
-
},
|
|
37
|
-
error: (message, ...args) => {
|
|
38
|
-
const formatted = formatMessage(message, ...args);
|
|
39
|
-
const output = formatWithEmoji(formatted, "\u274C", stderrChalk.red);
|
|
40
|
-
console.error(output);
|
|
41
|
-
},
|
|
42
|
-
debug: (message, ...args) => {
|
|
43
|
-
if (globalDebugEnabled) {
|
|
44
|
-
const formatted = formatMessage(message, ...args);
|
|
45
|
-
const output = formatWithEmoji(formatted, "\u{1F50D}", stdoutChalk.gray);
|
|
46
|
-
console.log(output);
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
setDebug: (enabled) => {
|
|
50
|
-
globalDebugEnabled = enabled;
|
|
51
|
-
},
|
|
52
|
-
isDebugEnabled: () => {
|
|
53
|
-
return globalDebugEnabled;
|
|
54
|
-
},
|
|
55
|
-
stdout: process.stdout
|
|
56
|
-
};
|
|
57
|
-
function createStderrLogger(options = {}) {
|
|
58
|
-
const { prefix = "", timestamp = false, forceColor, debug = globalDebugEnabled } = options;
|
|
59
|
-
let localDebugEnabled = debug;
|
|
60
|
-
const customChalk = forceColor !== void 0 ? new Chalk({ level: forceColor ? 3 : 0 }) : stderrChalk;
|
|
61
|
-
const prefixStr = prefix ? `[${prefix}] ` : "";
|
|
62
|
-
const getTimestamp = () => timestamp ? `[${(/* @__PURE__ */ new Date()).toISOString()}] ` : "";
|
|
63
|
-
return {
|
|
64
|
-
info: (message, ...args) => {
|
|
65
|
-
const formatted = formatMessage(message, ...args);
|
|
66
|
-
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
67
|
-
const output = formatWithEmoji(fullMessage, "\u{1F5C2}\uFE0F ", customChalk.blue);
|
|
68
|
-
console.error(output);
|
|
69
|
-
},
|
|
70
|
-
success: (message, ...args) => {
|
|
71
|
-
const formatted = formatMessage(message, ...args);
|
|
72
|
-
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
73
|
-
const output = formatWithEmoji(fullMessage, "\u2705", customChalk.green);
|
|
74
|
-
console.error(output);
|
|
75
|
-
},
|
|
76
|
-
warn: (message, ...args) => {
|
|
77
|
-
const formatted = formatMessage(message, ...args);
|
|
78
|
-
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
79
|
-
const output = formatWithEmoji(fullMessage, "\u26A0\uFE0F ", customChalk.yellow);
|
|
80
|
-
console.error(output);
|
|
81
|
-
},
|
|
82
|
-
error: (message, ...args) => {
|
|
83
|
-
const formatted = formatMessage(message, ...args);
|
|
84
|
-
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
85
|
-
const output = formatWithEmoji(fullMessage, "\u274C", customChalk.red);
|
|
86
|
-
console.error(output);
|
|
87
|
-
},
|
|
88
|
-
debug: (message, ...args) => {
|
|
89
|
-
if (localDebugEnabled) {
|
|
90
|
-
const formatted = formatMessage(message, ...args);
|
|
91
|
-
const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`;
|
|
92
|
-
const output = formatWithEmoji(fullMessage, "\u{1F50D}", customChalk.gray);
|
|
93
|
-
console.error(output);
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
setDebug: (enabled) => {
|
|
97
|
-
localDebugEnabled = enabled;
|
|
98
|
-
},
|
|
99
|
-
isDebugEnabled: () => {
|
|
100
|
-
return globalDebugEnabled;
|
|
101
|
-
},
|
|
102
|
-
stdout: process.stderr
|
|
103
|
-
// Use stderr for progress output in JSON mode
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
var logger_default = logger;
|
|
107
|
-
|
|
108
|
-
export {
|
|
109
|
-
logger,
|
|
110
|
-
createStderrLogger,
|
|
111
|
-
logger_default
|
|
112
|
-
};
|
|
113
|
-
//# sourceMappingURL=chunk-UYVWLISQ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/logger.ts"],"sourcesContent":["// Lines 1-5: Imports\nimport chalk, { Chalk } from 'chalk'\n\n// Lines 7-17: Type definitions\nexport interface LoggerOptions {\n prefix?: string\n timestamp?: boolean\n silent?: boolean\n forceColor?: boolean | undefined | null\n debug?: boolean\n}\n\nexport interface Logger {\n info: (message: string, ...args: unknown[]) => void\n success: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n setDebug: (enabled: boolean) => void\n isDebugEnabled: () => boolean\n stdout: NodeJS.WriteStream // Stream for progress output (stdout normally, stderr in JSON mode)\n}\n\n// Lines 19-29: Stream-specific chalk instances\nconst stdoutChalk = new Chalk({ level: chalk.level })\nconst stderrChalk = new Chalk({ level: chalk.level })\n\n// Lines 31-45: Helper functions\nfunction formatMessage(message: string, ...args: unknown[]): string {\n // Convert args to strings and append to message\n const formattedArgs = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)\n )\n return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(' ')}` : message\n}\n\nfunction formatWithEmoji(message: string, emoji: string, colorFn: (str: string) => string): string {\n if (message.trim()) {\n return colorFn(`${emoji} ${message}`)\n } else {\n return ''\n }\n}\n\nlet globalDebugEnabled = false\n\n// Lines 47-96: Main logger implementation\n/* eslint-disable no-console */\nexport const logger: Logger = {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🗂️ ', stdoutChalk.blue)\n console.log(output)\n },\n\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '✅', stdoutChalk.green)\n console.log(output)\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '⚠️ ', stderrChalk.yellow)\n console.error(output)\n },\n\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '❌', stderrChalk.red)\n console.error(output)\n },\n\n debug: (message: string, ...args: unknown[]): void => {\n if (globalDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🔍', stdoutChalk.gray)\n console.log(output)\n }\n },\n\n setDebug: (enabled: boolean): void => {\n globalDebugEnabled = enabled\n },\n\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n\n stdout: process.stdout\n}\n/* eslint-enable no-console */\n\n// Lines 98-145: Factory function for custom logger instances\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customStdoutChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stdoutChalk\n const customStderrChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n if (silent) {\n // Return no-op logger when silent\n return {\n info: (): void => {},\n success: (): void => {},\n warn: (): void => {},\n error: (): void => {},\n debug: (): void => {},\n setDebug: (): void => {},\n isDebugEnabled: (): boolean => {\n return false\n },\n stdout: process.stdout\n }\n }\n\n /* eslint-disable no-console */\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', customStdoutChalk.blue)\n console.log(output)\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', customStdoutChalk.green)\n console.log(output)\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', customStderrChalk.yellow)\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', customStderrChalk.red)\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', customStdoutChalk.gray)\n console.log(output)\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stdout\n }\n /* eslint-enable no-console */\n}\n\n// Lines 147-200: Factory function for stderr-only logger (for JSON mode)\n/**\n * Creates a logger that redirects all output to stderr.\n * Use this in JSON mode so progress messages don't pollute stdout.\n * The JSON output can then be cleanly piped.\n */\nexport function createStderrLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', customChalk.blue)\n console.error(output) // Redirect to stderr\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', customChalk.green)\n console.error(output) // Redirect to stderr\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', customChalk.yellow)\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', customChalk.red)\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', customChalk.gray)\n console.error(output) // Redirect to stderr\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stderr // Use stderr for progress output in JSON mode\n }\n}\n\n// Default export\nexport default logger\n"],"mappings":"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","names":[]}
|
package/dist/chunk-VAYGNQTE.js
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
buildEnvSourceCommands
|
|
4
|
-
} from "./chunk-Z5NXYJIG.js";
|
|
5
|
-
|
|
6
|
-
// src/utils/terminal.ts
|
|
7
|
-
import { execa } from "execa";
|
|
8
|
-
import { existsSync } from "fs";
|
|
9
|
-
function detectPlatform() {
|
|
10
|
-
const platform = process.platform;
|
|
11
|
-
if (platform === "darwin") return "darwin";
|
|
12
|
-
if (platform === "linux") return "linux";
|
|
13
|
-
if (platform === "win32") return "win32";
|
|
14
|
-
return "unsupported";
|
|
15
|
-
}
|
|
16
|
-
async function detectITerm2() {
|
|
17
|
-
const platform = detectPlatform();
|
|
18
|
-
if (platform !== "darwin") return false;
|
|
19
|
-
return existsSync("/Applications/iTerm.app");
|
|
20
|
-
}
|
|
21
|
-
async function openTerminalWindow(options) {
|
|
22
|
-
const platform = detectPlatform();
|
|
23
|
-
if (platform !== "darwin") {
|
|
24
|
-
throw new Error(
|
|
25
|
-
`Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
const hasITerm2 = await detectITerm2();
|
|
29
|
-
const applescript = hasITerm2 ? await buildITerm2SingleTabScript(options) : await buildAppleScript(options);
|
|
30
|
-
try {
|
|
31
|
-
await execa("osascript", ["-e", applescript]);
|
|
32
|
-
if (!hasITerm2) {
|
|
33
|
-
await execa("osascript", ["-e", 'tell application "Terminal" to activate']);
|
|
34
|
-
}
|
|
35
|
-
} catch (error) {
|
|
36
|
-
throw new Error(
|
|
37
|
-
`Failed to open terminal window: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
async function buildAppleScript(options) {
|
|
42
|
-
const {
|
|
43
|
-
workspacePath,
|
|
44
|
-
command,
|
|
45
|
-
backgroundColor,
|
|
46
|
-
port,
|
|
47
|
-
includeEnvSetup,
|
|
48
|
-
includePortExport
|
|
49
|
-
} = options;
|
|
50
|
-
const commands = [];
|
|
51
|
-
if (workspacePath) {
|
|
52
|
-
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
53
|
-
}
|
|
54
|
-
if (includeEnvSetup && workspacePath) {
|
|
55
|
-
const sourceCommands = await buildEnvSourceCommands(
|
|
56
|
-
workspacePath,
|
|
57
|
-
async (p) => existsSync(p)
|
|
58
|
-
);
|
|
59
|
-
commands.push(...sourceCommands);
|
|
60
|
-
}
|
|
61
|
-
if (includePortExport && port !== void 0) {
|
|
62
|
-
commands.push(`export PORT=${port}`);
|
|
63
|
-
}
|
|
64
|
-
if (command) {
|
|
65
|
-
commands.push(command);
|
|
66
|
-
}
|
|
67
|
-
const fullCommand = commands.join(" && ");
|
|
68
|
-
const historyFreeCommand = ` ${fullCommand}`;
|
|
69
|
-
let script = `tell application "Terminal"
|
|
70
|
-
`;
|
|
71
|
-
script += ` set newTab to do script "${escapeForAppleScript(historyFreeCommand)}"
|
|
72
|
-
`;
|
|
73
|
-
if (backgroundColor) {
|
|
74
|
-
const { r, g, b } = backgroundColor;
|
|
75
|
-
script += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
76
|
-
`;
|
|
77
|
-
}
|
|
78
|
-
script += `end tell`;
|
|
79
|
-
return script;
|
|
80
|
-
}
|
|
81
|
-
function escapePathForAppleScript(path) {
|
|
82
|
-
return path.replace(/'/g, "'\\''");
|
|
83
|
-
}
|
|
84
|
-
function escapeForAppleScript(command) {
|
|
85
|
-
return command.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
86
|
-
}
|
|
87
|
-
async function buildITerm2SingleTabScript(options) {
|
|
88
|
-
const command = await buildCommandSequence(options);
|
|
89
|
-
let script = 'tell application id "com.googlecode.iterm2"\n';
|
|
90
|
-
script += " create window with default profile\n";
|
|
91
|
-
script += " set s1 to current session of current window\n\n";
|
|
92
|
-
if (options.backgroundColor) {
|
|
93
|
-
const { r, g, b } = options.backgroundColor;
|
|
94
|
-
script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
95
|
-
`;
|
|
96
|
-
}
|
|
97
|
-
script += ` tell s1 to write text "${escapeForAppleScript(command)}"
|
|
98
|
-
|
|
99
|
-
`;
|
|
100
|
-
if (options.title) {
|
|
101
|
-
script += ` set name of s1 to "${escapeForAppleScript(options.title)}"
|
|
102
|
-
|
|
103
|
-
`;
|
|
104
|
-
}
|
|
105
|
-
script += " activate\n";
|
|
106
|
-
script += "end tell";
|
|
107
|
-
return script;
|
|
108
|
-
}
|
|
109
|
-
async function buildCommandSequence(options) {
|
|
110
|
-
const {
|
|
111
|
-
workspacePath,
|
|
112
|
-
command,
|
|
113
|
-
port,
|
|
114
|
-
includeEnvSetup,
|
|
115
|
-
includePortExport
|
|
116
|
-
} = options;
|
|
117
|
-
const commands = [];
|
|
118
|
-
if (workspacePath) {
|
|
119
|
-
commands.push(`cd '${escapePathForAppleScript(workspacePath)}'`);
|
|
120
|
-
}
|
|
121
|
-
if (includeEnvSetup && workspacePath) {
|
|
122
|
-
const sourceCommands = await buildEnvSourceCommands(
|
|
123
|
-
workspacePath,
|
|
124
|
-
async (p) => existsSync(p)
|
|
125
|
-
);
|
|
126
|
-
commands.push(...sourceCommands);
|
|
127
|
-
}
|
|
128
|
-
if (includePortExport && port !== void 0) {
|
|
129
|
-
commands.push(`export PORT=${port}`);
|
|
130
|
-
}
|
|
131
|
-
if (command) {
|
|
132
|
-
commands.push(command);
|
|
133
|
-
}
|
|
134
|
-
const fullCommand = commands.join(" && ");
|
|
135
|
-
return ` ${fullCommand}`;
|
|
136
|
-
}
|
|
137
|
-
async function buildITerm2MultiTabScript(optionsArray) {
|
|
138
|
-
if (optionsArray.length < 2) {
|
|
139
|
-
throw new Error("buildITerm2MultiTabScript requires at least 2 terminal options");
|
|
140
|
-
}
|
|
141
|
-
let script = 'tell application id "com.googlecode.iterm2"\n';
|
|
142
|
-
script += " create window with default profile\n";
|
|
143
|
-
script += " set newWindow to current window\n";
|
|
144
|
-
const options1 = optionsArray[0];
|
|
145
|
-
if (!options1) {
|
|
146
|
-
throw new Error("First terminal option is undefined");
|
|
147
|
-
}
|
|
148
|
-
const command1 = await buildCommandSequence(options1);
|
|
149
|
-
script += " set s1 to current session of newWindow\n\n";
|
|
150
|
-
if (options1.backgroundColor) {
|
|
151
|
-
const { r, g, b } = options1.backgroundColor;
|
|
152
|
-
script += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
153
|
-
`;
|
|
154
|
-
}
|
|
155
|
-
script += ` tell s1 to write text "${escapeForAppleScript(command1)}"
|
|
156
|
-
|
|
157
|
-
`;
|
|
158
|
-
if (options1.title) {
|
|
159
|
-
script += ` set name of s1 to "${escapeForAppleScript(options1.title)}"
|
|
160
|
-
|
|
161
|
-
`;
|
|
162
|
-
}
|
|
163
|
-
for (let i = 1; i < optionsArray.length; i++) {
|
|
164
|
-
const options = optionsArray[i];
|
|
165
|
-
if (!options) {
|
|
166
|
-
throw new Error(`Terminal option at index ${i} is undefined`);
|
|
167
|
-
}
|
|
168
|
-
const command = await buildCommandSequence(options);
|
|
169
|
-
const sessionVar = `s${i + 1}`;
|
|
170
|
-
script += " tell newWindow\n";
|
|
171
|
-
script += ` set newTab${i} to (create tab with default profile)
|
|
172
|
-
`;
|
|
173
|
-
script += " end tell\n";
|
|
174
|
-
script += ` set ${sessionVar} to current session of newTab${i}
|
|
175
|
-
|
|
176
|
-
`;
|
|
177
|
-
if (options.backgroundColor) {
|
|
178
|
-
const { r, g, b } = options.backgroundColor;
|
|
179
|
-
script += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}
|
|
180
|
-
`;
|
|
181
|
-
}
|
|
182
|
-
script += ` tell ${sessionVar} to write text "${escapeForAppleScript(command)}"
|
|
183
|
-
|
|
184
|
-
`;
|
|
185
|
-
if (options.title) {
|
|
186
|
-
script += ` set name of ${sessionVar} to "${escapeForAppleScript(options.title)}"
|
|
187
|
-
|
|
188
|
-
`;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
script += " activate\n";
|
|
192
|
-
script += "end tell";
|
|
193
|
-
return script;
|
|
194
|
-
}
|
|
195
|
-
async function openMultipleTerminalWindows(optionsArray) {
|
|
196
|
-
if (optionsArray.length < 2) {
|
|
197
|
-
throw new Error("openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.");
|
|
198
|
-
}
|
|
199
|
-
const platform = detectPlatform();
|
|
200
|
-
if (platform !== "darwin") {
|
|
201
|
-
throw new Error(
|
|
202
|
-
`Terminal window launching not yet supported on ${platform}. Currently only macOS is supported.`
|
|
203
|
-
);
|
|
204
|
-
}
|
|
205
|
-
const hasITerm2 = await detectITerm2();
|
|
206
|
-
if (hasITerm2) {
|
|
207
|
-
const applescript = await buildITerm2MultiTabScript(optionsArray);
|
|
208
|
-
try {
|
|
209
|
-
await execa("osascript", ["-e", applescript]);
|
|
210
|
-
} catch (error) {
|
|
211
|
-
throw new Error(
|
|
212
|
-
`Failed to open iTerm2 window: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
} else {
|
|
216
|
-
for (let i = 0; i < optionsArray.length; i++) {
|
|
217
|
-
const options = optionsArray[i];
|
|
218
|
-
if (!options) {
|
|
219
|
-
throw new Error(`Terminal option at index ${i} is undefined`);
|
|
220
|
-
}
|
|
221
|
-
await openTerminalWindow(options);
|
|
222
|
-
if (i < optionsArray.length - 1) {
|
|
223
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
export {
|
|
230
|
-
detectITerm2,
|
|
231
|
-
openTerminalWindow,
|
|
232
|
-
openMultipleTerminalWindows
|
|
233
|
-
};
|
|
234
|
-
//# sourceMappingURL=chunk-VAYGNQTE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/terminal.ts"],"sourcesContent":["import { execa } from 'execa'\nimport { existsSync } from 'node:fs'\nimport type { Platform } from '../types/index.js'\nimport { buildEnvSourceCommands } from './env.js'\n\nexport interface TerminalWindowOptions {\n\tworkspacePath?: string\n\tcommand?: string\n\tbackgroundColor?: { r: number; g: number; b: number }\n\tport?: number\n\tincludeEnvSetup?: boolean // source .env\n\tincludePortExport?: boolean // export PORT=<port>\n\ttitle?: string // Terminal tab title\n}\n\n/**\n * Detect current platform\n */\nexport function detectPlatform(): Platform {\n\tconst platform = process.platform\n\tif (platform === 'darwin') return 'darwin'\n\tif (platform === 'linux') return 'linux'\n\tif (platform === 'win32') return 'win32'\n\treturn 'unsupported'\n}\n\n/**\n * Detect if iTerm2 is installed on macOS\n * Returns false on non-macOS platforms\n */\nexport async function detectITerm2(): Promise<boolean> {\n\tconst platform = detectPlatform()\n\tif (platform !== 'darwin') return false\n\n\t// Check if iTerm.app exists at standard location\n\treturn existsSync('/Applications/iTerm.app')\n}\n\n/**\n * Open new terminal window with specified options\n * Currently supports macOS only\n */\nexport async function openTerminalWindow(\n\toptions: TerminalWindowOptions\n): Promise<void> {\n\tconst platform = detectPlatform()\n\n\tif (platform !== 'darwin') {\n\t\tthrow new Error(\n\t\t\t`Terminal window launching not yet supported on ${platform}. ` +\n\t\t\t\t`Currently only macOS is supported.`\n\t\t)\n\t}\n\n\t// Detect if iTerm2 is available\n\tconst hasITerm2 = await detectITerm2()\n\n\t// Build appropriate AppleScript based on terminal availability\n\tconst applescript = hasITerm2\n\t\t? await buildITerm2SingleTabScript(options)\n\t\t: await buildAppleScript(options)\n\n\ttry {\n\t\tawait execa('osascript', ['-e', applescript])\n\n\t\t// Activate the appropriate terminal application (only needed for Terminal.app)\n\t\t// iTerm2 script includes its own activation\n\t\tif (!hasITerm2) {\n\t\t\tawait execa('osascript', ['-e', 'tell application \"Terminal\" to activate'])\n\t\t}\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open terminal window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n\n/**\n * Build AppleScript for macOS Terminal.app\n */\nasync function buildAppleScript(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tbackgroundColor,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\t// Build command sequence\n\tconst commands: string[] = []\n\n\t// Navigate to workspace\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapePathForAppleScript(workspacePath)}'`)\n\t}\n\n\t// Source all dotenv-flow files\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\t// Export PORT variable\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\t// Add custom command\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\t// Join with &&\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\t// Most shells (bash/zsh) ignore commands starting with space when HISTCONTROL=ignorespace\n\tconst historyFreeCommand = ` ${fullCommand}`\n\n\t// Build AppleScript\n\tlet script = `tell application \"Terminal\"\\n`\n\tscript += ` set newTab to do script \"${escapeForAppleScript(historyFreeCommand)}\"\\n`\n\n\t// Apply background color if provided\n\tif (backgroundColor) {\n\t\tconst { r, g, b } = backgroundColor\n\t\t// Convert 8-bit RGB (0-255) to 16-bit RGB (0-65535)\n\t\tscript += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += `end tell`\n\n\treturn script\n}\n\n/**\n * Escape path for AppleScript string\n * Single quotes in path need special escaping\n */\nfunction escapePathForAppleScript(path: string): string {\n\t// Replace single quote with '\\''\n\treturn path.replace(/'/g, \"'\\\\''\")\n}\n\n/**\n * Escape command for AppleScript do script\n * Must handle double quotes and backslashes\n */\nfunction escapeForAppleScript(command: string): string {\n\treturn (\n\t\tcommand\n\t\t\t.replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n\t\t\t.replace(/\"/g, '\\\\\"') // Escape double quotes\n\t)\n}\n\n/**\n * Build iTerm2 AppleScript for single tab\n */\nasync function buildITerm2SingleTabScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set s1 to current session of current window\\n\\n'\n\n\t// Set background color\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\t// Execute command\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t// Set session name (tab title)\n\tif (options.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t}\n\n\t// Activate iTerm2\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\n\treturn script\n}\n\n/**\n * Build command sequence for terminal\n */\nasync function buildCommandSequence(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\tconst commands: string[] = []\n\n\t// Navigate to workspace\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapePathForAppleScript(workspacePath)}'`)\n\t}\n\n\t// Source all dotenv-flow files\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\t// Export PORT variable\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\t// Add custom command\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\t// Join with &&\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\treturn ` ${fullCommand}`\n}\n\n/**\n * Build iTerm2 AppleScript for multiple tabs (2+) in single window\n */\nasync function buildITerm2MultiTabScript(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<string> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('buildITerm2MultiTabScript requires at least 2 terminal options')\n\t}\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set newWindow to current window\\n'\n\n\t// First tab\n\tconst options1 = optionsArray[0]\n\tif (!options1) {\n\t\tthrow new Error('First terminal option is undefined')\n\t}\n\tconst command1 = await buildCommandSequence(options1)\n\n\tscript += ' set s1 to current session of newWindow\\n\\n'\n\n\t// Set background color for first tab\n\tif (options1.backgroundColor) {\n\t\tconst { r, g, b } = options1.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\t// Execute command in first tab\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command1)}\"\\n\\n`\n\n\t// Set tab title for first tab\n\tif (options1.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options1.title)}\"\\n\\n`\n\t}\n\n\t// Subsequent tabs (2, 3, ...)\n\tfor (let i = 1; i < optionsArray.length; i++) {\n\t\tconst options = optionsArray[i]\n\t\tif (!options) {\n\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t}\n\t\tconst command = await buildCommandSequence(options)\n\t\tconst sessionVar = `s${i + 1}`\n\n\t\t// Create tab\n\t\tscript += ' tell newWindow\\n'\n\t\tscript += ` set newTab${i} to (create tab with default profile)\\n`\n\t\tscript += ' end tell\\n'\n\t\tscript += ` set ${sessionVar} to current session of newTab${i}\\n\\n`\n\n\t\t// Set background color\n\t\tif (options.backgroundColor) {\n\t\t\tconst { r, g, b } = options.backgroundColor\n\t\t\tscript += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t\t}\n\n\t\t// Execute command\n\t\tscript += ` tell ${sessionVar} to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t\t// Set tab title\n\t\tif (options.title) {\n\t\t\tscript += ` set name of ${sessionVar} to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t\t}\n\t}\n\n\t// Activate iTerm2\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\n\treturn script\n}\n\n/**\n * Open multiple terminal windows/tabs (2+) with specified options\n * If iTerm2 is available on macOS, creates single window with multiple tabs\n * Otherwise falls back to multiple separate Terminal.app windows\n */\nexport async function openMultipleTerminalWindows(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<void> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.')\n\t}\n\n\tconst platform = detectPlatform()\n\n\tif (platform !== 'darwin') {\n\t\tthrow new Error(\n\t\t\t`Terminal window launching not yet supported on ${platform}. ` +\n\t\t\t\t`Currently only macOS is supported.`\n\t\t)\n\t}\n\n\t// Detect if iTerm2 is available\n\tconst hasITerm2 = await detectITerm2()\n\n\tif (hasITerm2) {\n\t\t// Use iTerm2 with multiple tabs in single window\n\t\tconst applescript = await buildITerm2MultiTabScript(optionsArray)\n\n\t\ttry {\n\t\t\tawait execa('osascript', ['-e', applescript])\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to open iTerm2 window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t} else {\n\t\t// Fall back to multiple Terminal.app windows\n\t\tfor (let i = 0; i < optionsArray.length; i++) {\n\t\t\tconst options = optionsArray[i]\n\t\t\tif (!options) {\n\t\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t\t}\n\t\t\tawait openTerminalWindow(options)\n\n\t\t\t// Brief pause between terminals (except after last one)\n\t\t\tif (i < optionsArray.length - 1) {\n\t\t\t\t// eslint-disable-next-line no-undef\n\t\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, 1000))\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Open dual terminal windows/tabs with specified options\n * If iTerm2 is available on macOS, creates single window with two tabs\n * Otherwise falls back to two separate Terminal.app windows\n */\nexport async function openDualTerminalWindow(\n\toptions1: TerminalWindowOptions,\n\toptions2: TerminalWindowOptions\n): Promise<void> {\n\t// Delegate to openMultipleTerminalWindows for consistency\n\tawait openMultipleTerminalWindows([options1, options2])\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/color.ts"],"sourcesContent":["import { createHash } from 'crypto'\nimport logger from './logger'\n\n/**\n * RGB color representation\n */\nexport interface RgbColor {\n\tr: number\n\tg: number\n\tb: number\n}\n\n/**\n * Complete color data with RGB, hex, and palette index\n */\nexport interface ColorData {\n\trgb: RgbColor\n\thex: string\n\tindex: number\n}\n\n/**\n * Get the predefined color palette (16 visually distinct colors)\n * Reduced from 40 colors to ensure minimum euclidean distance >= 30 between all pairs\n * This prevents near-identical colors being assigned to different looms\n *\n * @returns Array of 16 RGB colors\n */\nexport function getColorPalette(): RgbColor[] {\n\treturn [\n\t\t{ r: 220, g: 235, b: 255 }, // 0: Soft blue\n\t\t{ r: 255, g: 220, b: 235 }, // 1: Soft pink\n\t\t{ r: 220, g: 255, b: 235 }, // 2: Soft green\n\t\t{ r: 255, g: 245, b: 220 }, // 3: Soft cream\n\t\t{ r: 245, g: 220, b: 255 }, // 4: Soft lavender\n\t\t{ r: 220, g: 245, b: 255 }, // 5: Soft cyan\n\t\t{ r: 235, g: 235, b: 235 }, // 6: Soft grey\n\t\t{ r: 255, g: 230, b: 230 }, // 7: Soft coral\n\t\t{ r: 230, g: 255, b: 230 }, // 8: Soft mint\n\t\t{ r: 255, g: 245, b: 230 }, // 9: Soft peach\n\t\t{ r: 220, g: 255, b: 255 }, // 10: Soft aqua\n\t\t{ r: 255, g: 220, b: 255 }, // 11: Soft magenta\n\t\t{ r: 255, g: 255, b: 220 }, // 12: Soft yellow\n\t\t{ r: 235, g: 220, b: 255 }, // 13: Soft violet\n\t\t{ r: 220, g: 255, b: 245 }, // 14: Soft sea green\n\t\t{ r: 255, g: 235, b: 220 }, // 15: Soft salmon\n\t]\n}\n\n/**\n * Convert RGB values to hex color format\n *\n * @param r - Red value (0-255)\n * @param g - Green value (0-255)\n * @param b - Blue value (0-255)\n * @returns Hex color string (e.g., \"#dcebf8\")\n * @throws Error if RGB values are out of range\n */\nexport function rgbToHex(r: number, g: number, b: number): string {\n\t// Validate RGB values\n\tif (r < 0 || r > 255 || g < 0 || g > 255 || b < 0 || b > 255) {\n\t\tthrow new Error('RGB values must be between 0 and 255')\n\t}\n\n\t// Convert to hex and pad with zeros\n\tconst rHex = r.toString(16).padStart(2, '0')\n\tconst gHex = g.toString(16).padStart(2, '0')\n\tconst bHex = b.toString(16).padStart(2, '0')\n\n\treturn `#${rHex}${gHex}${bHex}`\n}\n\n/**\n * Convert hex color format to RGB values\n *\n * @param hex - Hex color string (with or without # prefix)\n * @returns RGB color object\n * @throws Error if hex format is invalid\n */\nexport function hexToRgb(hex: string): RgbColor {\n\t// Remove # prefix if present\n\tconst cleanHex = hex.startsWith('#') ? hex.slice(1) : hex\n\n\t// Validate format (must be exactly 6 hex characters)\n\tif (cleanHex.length !== 6 || !/^[0-9a-fA-F]{6}$/.test(cleanHex)) {\n\t\tthrow new Error('Invalid hex color format. Expected format: #RRGGBB or RRGGBB')\n\t}\n\n\t// Parse hex values\n\tconst r = parseInt(cleanHex.slice(0, 2), 16)\n\tconst g = parseInt(cleanHex.slice(2, 4), 16)\n\tconst b = parseInt(cleanHex.slice(4, 6), 16)\n\n\treturn { r, g, b }\n}\n\n/**\n * Generate deterministic color from branch name using SHA256 hash\n * Matches the bash implementation in bash/new-branch-workflow.sh\n *\n * @param branchName - Branch name to generate color from\n * @returns ColorData with RGB, hex, and palette index\n */\nexport function generateColorFromBranchName(branchName: string): ColorData {\n\t// Generate SHA256 hash of branch name\n\tconst hash = createHash('sha256').update(branchName).digest('hex')\n\n\t// Take first 8 hex characters and convert to index (0-39)\n\t// Matches bash: local index=$(( 0x$hash % ${#colors[@]} ))\n\tconst hashPrefix = hash.slice(0, 8)\n\tconst palette = getColorPalette()\n\tconst hashAsInt = parseInt(hashPrefix, 16)\n\tconst index = hashAsInt % palette.length\n\tlogger.debug(`[generateColorFromBranchName] Branch name: ${branchName}, Hash: ${hash}, Hash prefix: ${hashPrefix}, Hash as int: ${hashAsInt}, Index: ${index}`)\n\n\t// Get color from palette\n\tconst rgb = palette[index]\n\n\t// This should never happen as index is always in range [0, palette.length)\n\tif (!rgb) {\n\t\tthrow new Error(`Invalid color index: ${index}`)\n\t}\n\n\t// Convert to hex format\n\tconst hex = rgbToHex(rgb.r, rgb.g, rgb.b)\n\n\treturn {\n\t\trgb,\n\t\thex,\n\t\tindex,\n\t}\n}\n\n/**\n * Calculate euclidean distance between two RGB colors\n */\nexport function colorDistance(a: RgbColor, b: RgbColor): number {\n\treturn Math.sqrt(\n\t\tMath.pow(a.r - b.r, 2) +\n\t\tMath.pow(a.g - b.g, 2) +\n\t\tMath.pow(a.b - b.b, 2)\n\t)\n}\n\n/**\n * Minimum distance threshold for colors to be considered \"distinct\"\n * Note: With RGB constrained to 220-255 range (subtle backgrounds),\n * the maximum possible distance between any two colors is ~60.6\n * A threshold of 20 ensures colors are visually distinguishable\n * (vs the original palette minimum of 3.61) while allowing enough\n * palette diversity for typical concurrent loom counts (5-10).\n */\nexport const MIN_COLOR_DISTANCE = 20\n\n/**\n * Select a color for a branch, avoiding colors that are too similar to hex colors in use\n * This function is robust against palette changes since it compares hex colors directly.\n *\n * @param branchName - Branch name to generate base color from\n * @param usedHexColors - Array of hex colors (e.g., \"#dcebff\") already in use by active looms\n * @returns ColorData with the selected color\n */\nexport function selectDistinctColor(branchName: string, usedHexColors: string[]): ColorData {\n\tconst palette = getColorPalette()\n\tconst hashBasedColor = generateColorFromBranchName(branchName)\n\n\t// If no colors in use, return hash-based selection\n\tif (usedHexColors.length === 0) {\n\t\treturn hashBasedColor\n\t}\n\n\t// Convert used hex colors to RGB for distance calculation\n\tconst usedRgbColors: RgbColor[] = []\n\tfor (const hex of usedHexColors) {\n\t\ttry {\n\t\t\tusedRgbColors.push(hexToRgb(hex))\n\t\t} catch {\n\t\t\t// Skip invalid hex colors\n\t\t\tlogger.debug(`[selectDistinctColor] Skipping invalid hex color: ${hex}`)\n\t\t}\n\t}\n\n\t// If all hex colors were invalid, return hash-based selection\n\tif (usedRgbColors.length === 0) {\n\t\treturn hashBasedColor\n\t}\n\n\t// Check if hash-based color is distinct enough from all used colors\n\tconst isTooSimilar = usedRgbColors.some(usedRgb =>\n\t\tcolorDistance(hashBasedColor.rgb, usedRgb) < MIN_COLOR_DISTANCE\n\t)\n\n\tif (!isTooSimilar) {\n\t\treturn hashBasedColor\n\t}\n\n\t// Find the first available color that's distinct from all used colors\n\tfor (let i = 0; i < palette.length; i++) {\n\t\tconst candidateRgb = palette[i]\n\t\tif (!candidateRgb) continue\n\n\t\tconst isDistinct = usedRgbColors.every(usedRgb =>\n\t\t\tcolorDistance(candidateRgb, usedRgb) >= MIN_COLOR_DISTANCE\n\t\t)\n\n\t\tif (isDistinct) {\n\t\t\treturn {\n\t\t\t\trgb: candidateRgb,\n\t\t\t\thex: rgbToHex(candidateRgb.r, candidateRgb.g, candidateRgb.b),\n\t\t\t\tindex: i,\n\t\t\t}\n\t\t}\n\t}\n\n\t// Fallback: all colors too similar, return hash-based (best effort)\n\tlogger.debug(`[selectDistinctColor] No distinct color found, falling back to hash-based for ${branchName}`)\n\treturn hashBasedColor\n}\n\n/**\n * Lighten a color by a given amount\n * Useful for creating slightly lighter variants for hover states\n *\n * @param rgb - RGB color to lighten\n * @param amount - Amount to lighten (0-1, where 0.1 = 10% lighter)\n * @returns Lightened RGB color\n */\nexport function lightenColor(rgb: RgbColor, amount: number): RgbColor {\n\tconst clamp = (value: number): number => Math.min(255, Math.max(0, Math.round(value)))\n\n\treturn {\n\t\tr: clamp(rgb.r + (255 - rgb.r) * amount),\n\t\tg: clamp(rgb.g + (255 - rgb.g) * amount),\n\t\tb: clamp(rgb.b + (255 - rgb.b) * amount),\n\t}\n}\n\n/**\n * Saturate a color by pushing it away from grey towards its dominant hue\n * Makes subtle colors more vivid while maintaining their hue\n *\n * @param rgb - RGB color to saturate\n * @param amount - Amount to saturate (0-1, where 0.4 = 40% more saturated)\n * @returns Saturated RGB color\n */\nexport function saturateColor(rgb: RgbColor, amount: number): RgbColor {\n\tconst clamp = (value: number): number => Math.min(255, Math.max(0, Math.round(value)))\n\n\t// Calculate average (grey point)\n\tconst avg = (rgb.r + rgb.g + rgb.b) / 3\n\n\t// Push each channel away from grey\n\treturn {\n\t\tr: clamp(rgb.r + (rgb.r - avg) * amount),\n\t\tg: clamp(rgb.g + (rgb.g - avg) * amount),\n\t\tb: clamp(rgb.b + (rgb.b - avg) * amount),\n\t}\n}\n\n/**\n * Calculate appropriate foreground color (black or white) for a given background\n * Uses relative luminance formula from WCAG 2.0\n *\n * @param rgb - Background RGB color\n * @returns '#000000' for light backgrounds, '#ffffff' for dark backgrounds\n */\nexport function calculateForegroundColor(rgb: RgbColor): string {\n\t// Convert RGB to relative luminance (WCAG 2.0 formula)\n\tconst toLinear = (channel: number): number => {\n\t\tconst c = channel / 255\n\t\treturn c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4)\n\t}\n\n\tconst r = toLinear(rgb.r)\n\tconst g = toLinear(rgb.g)\n\tconst b = toLinear(rgb.b)\n\n\tconst luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b\n\n\t// Use black text for light backgrounds (luminance > 0.5)\n\t// Use white text for dark backgrounds\n\treturn luminance > 0.5 ? '#000000' : '#ffffff'\n}\n"],"mappings":"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","names":[]}
|
package/dist/chunk-Z5NXYJIG.js
DELETED
|
@@ -1,207 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
logger
|
|
4
|
-
} from "./chunk-UYVWLISQ.js";
|
|
5
|
-
|
|
6
|
-
// src/utils/env.ts
|
|
7
|
-
import path from "path";
|
|
8
|
-
import dotenvFlow from "dotenv-flow";
|
|
9
|
-
function parseEnvFile(content) {
|
|
10
|
-
const envMap = /* @__PURE__ */ new Map();
|
|
11
|
-
const lines = content.split("\n");
|
|
12
|
-
for (const line of lines) {
|
|
13
|
-
const trimmedLine = line.trim();
|
|
14
|
-
if (!trimmedLine || trimmedLine.startsWith("#")) {
|
|
15
|
-
continue;
|
|
16
|
-
}
|
|
17
|
-
const cleanLine = trimmedLine.startsWith("export ") ? trimmedLine.substring(7) : trimmedLine;
|
|
18
|
-
const equalsIndex = cleanLine.indexOf("=");
|
|
19
|
-
if (equalsIndex === -1) {
|
|
20
|
-
continue;
|
|
21
|
-
}
|
|
22
|
-
const key = cleanLine.substring(0, equalsIndex).trim();
|
|
23
|
-
let value = cleanLine.substring(equalsIndex + 1);
|
|
24
|
-
if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
|
|
25
|
-
value = value.substring(1, value.length - 1);
|
|
26
|
-
value = value.replace(/\\"/g, '"').replace(/\\'/g, "'");
|
|
27
|
-
value = value.replace(/\\n/g, "\n");
|
|
28
|
-
}
|
|
29
|
-
if (key) {
|
|
30
|
-
envMap.set(key, value);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return envMap;
|
|
34
|
-
}
|
|
35
|
-
function formatEnvLine(key, value) {
|
|
36
|
-
const escapedValue = value.replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\r/g, "\\r");
|
|
37
|
-
return `${key}="${escapedValue}"`;
|
|
38
|
-
}
|
|
39
|
-
function validateEnvVariable(key, _value) {
|
|
40
|
-
if (!key || key.length === 0) {
|
|
41
|
-
return {
|
|
42
|
-
valid: false,
|
|
43
|
-
error: "Environment variable key cannot be empty"
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
if (!isValidEnvKey(key)) {
|
|
47
|
-
return {
|
|
48
|
-
valid: false,
|
|
49
|
-
error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
return { valid: true };
|
|
53
|
-
}
|
|
54
|
-
function extractPort(envContent) {
|
|
55
|
-
const portValue = envContent.get("PORT");
|
|
56
|
-
if (!portValue) {
|
|
57
|
-
return null;
|
|
58
|
-
}
|
|
59
|
-
const port = parseInt(portValue, 10);
|
|
60
|
-
if (isNaN(port)) {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
return port;
|
|
64
|
-
}
|
|
65
|
-
function isValidEnvKey(key) {
|
|
66
|
-
if (!key || key.length === 0) {
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
70
|
-
return validKeyRegex.test(key);
|
|
71
|
-
}
|
|
72
|
-
function loadEnvIntoProcess(options) {
|
|
73
|
-
logger.debug("Loading environment variables with dotenv-flow", {
|
|
74
|
-
options: {
|
|
75
|
-
path: (options == null ? void 0 : options.path) ?? "current working directory",
|
|
76
|
-
nodeEnv: (options == null ? void 0 : options.nodeEnv) ?? "not specified",
|
|
77
|
-
defaultNodeEnv: (options == null ? void 0 : options.defaultNodeEnv) ?? "development (default)"
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
const configOptions = {
|
|
81
|
-
silent: true
|
|
82
|
-
// Don't throw errors if .env files are missing
|
|
83
|
-
};
|
|
84
|
-
if ((options == null ? void 0 : options.path) !== void 0) {
|
|
85
|
-
configOptions.path = options.path;
|
|
86
|
-
logger.debug(`Using custom path: ${options.path}`);
|
|
87
|
-
}
|
|
88
|
-
if ((options == null ? void 0 : options.nodeEnv) !== void 0) {
|
|
89
|
-
configOptions.node_env = options.nodeEnv;
|
|
90
|
-
logger.debug(`Using NODE_ENV: ${options.nodeEnv}`);
|
|
91
|
-
}
|
|
92
|
-
if ((options == null ? void 0 : options.defaultNodeEnv) !== void 0) {
|
|
93
|
-
configOptions.default_node_env = options.defaultNodeEnv;
|
|
94
|
-
logger.debug(`Using default NODE_ENV: ${options.defaultNodeEnv}`);
|
|
95
|
-
} else {
|
|
96
|
-
configOptions.default_node_env = "development";
|
|
97
|
-
logger.debug("Using default NODE_ENV: development");
|
|
98
|
-
}
|
|
99
|
-
logger.debug("dotenv-flow config options:", configOptions);
|
|
100
|
-
const result = dotenvFlow.config(configOptions);
|
|
101
|
-
const returnValue = {};
|
|
102
|
-
if (result.parsed) {
|
|
103
|
-
returnValue.parsed = result.parsed;
|
|
104
|
-
const variableCount = Object.keys(result.parsed).length;
|
|
105
|
-
logger.debug(`Successfully loaded ${variableCount} environment variables`);
|
|
106
|
-
} else {
|
|
107
|
-
logger.debug("No environment variables were parsed");
|
|
108
|
-
}
|
|
109
|
-
if (result.error) {
|
|
110
|
-
returnValue.error = result.error;
|
|
111
|
-
logger.debug("dotenv-flow returned an error", {
|
|
112
|
-
error: result.error.message,
|
|
113
|
-
name: result.error.name
|
|
114
|
-
});
|
|
115
|
-
} else {
|
|
116
|
-
logger.debug("dotenv-flow completed without errors");
|
|
117
|
-
}
|
|
118
|
-
return returnValue;
|
|
119
|
-
}
|
|
120
|
-
function isNoEnvFilesFoundError(error) {
|
|
121
|
-
return error.message.startsWith('no ".env*" files matching pattern');
|
|
122
|
-
}
|
|
123
|
-
function loadWorkspaceEnv(workspacePath) {
|
|
124
|
-
const nodeEnv = process.env.NODE_ENV ?? "development";
|
|
125
|
-
logger.debug("Loading workspace environment variables", {
|
|
126
|
-
workspacePath,
|
|
127
|
-
detectedNodeEnv: nodeEnv,
|
|
128
|
-
processNodeEnv: process.env.NODE_ENV ?? "not set"
|
|
129
|
-
});
|
|
130
|
-
return loadEnvIntoProcess({
|
|
131
|
-
path: workspacePath,
|
|
132
|
-
nodeEnv,
|
|
133
|
-
defaultNodeEnv: "development"
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
var DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? "development";
|
|
137
|
-
function getDotenvFlowFiles() {
|
|
138
|
-
return [
|
|
139
|
-
".env",
|
|
140
|
-
".env.local",
|
|
141
|
-
`.env.${DOTENV_FLOW_NODE_ENV}`,
|
|
142
|
-
`.env.${DOTENV_FLOW_NODE_ENV}.local`
|
|
143
|
-
];
|
|
144
|
-
}
|
|
145
|
-
function getLocalEquivalent(filename) {
|
|
146
|
-
if (filename.endsWith(".local")) {
|
|
147
|
-
return filename;
|
|
148
|
-
}
|
|
149
|
-
return `${filename}.local`;
|
|
150
|
-
}
|
|
151
|
-
async function findEnvFileForDatabaseUrl(workspacePath, variableName, isFileTracked, fileExists, getEnvVariable) {
|
|
152
|
-
const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable);
|
|
153
|
-
if (file === null) {
|
|
154
|
-
return ".env.local";
|
|
155
|
-
}
|
|
156
|
-
const isTracked = await isFileTracked(file, workspacePath);
|
|
157
|
-
if (isTracked) {
|
|
158
|
-
return getLocalEquivalent(file);
|
|
159
|
-
}
|
|
160
|
-
return file;
|
|
161
|
-
}
|
|
162
|
-
async function buildEnvSourceCommands(workspacePath, fileExists) {
|
|
163
|
-
const files = getDotenvFlowFiles();
|
|
164
|
-
const commands = [];
|
|
165
|
-
for (const file of files) {
|
|
166
|
-
const fullPath = path.join(workspacePath, file);
|
|
167
|
-
const exists = await fileExists(fullPath);
|
|
168
|
-
if (exists) {
|
|
169
|
-
commands.push(`source ${file}`);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return commands;
|
|
173
|
-
}
|
|
174
|
-
async function findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
175
|
-
const files = getDotenvFlowFiles().reverse();
|
|
176
|
-
for (const file of files) {
|
|
177
|
-
const fullPath = path.join(workspacePath, file);
|
|
178
|
-
if (!await fileExists(fullPath)) {
|
|
179
|
-
continue;
|
|
180
|
-
}
|
|
181
|
-
const value = await getEnvVariable(fullPath, variableName);
|
|
182
|
-
if (value !== null) {
|
|
183
|
-
return file;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
return null;
|
|
187
|
-
}
|
|
188
|
-
async function hasVariableInAnyEnvFile(workspacePath, variableName, fileExists, getEnvVariable) {
|
|
189
|
-
const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable);
|
|
190
|
-
return file !== null;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
export {
|
|
194
|
-
parseEnvFile,
|
|
195
|
-
formatEnvLine,
|
|
196
|
-
validateEnvVariable,
|
|
197
|
-
extractPort,
|
|
198
|
-
loadEnvIntoProcess,
|
|
199
|
-
isNoEnvFilesFoundError,
|
|
200
|
-
loadWorkspaceEnv,
|
|
201
|
-
getDotenvFlowFiles,
|
|
202
|
-
findEnvFileForDatabaseUrl,
|
|
203
|
-
buildEnvSourceCommands,
|
|
204
|
-
findEnvFileContainingVariable,
|
|
205
|
-
hasVariableInAnyEnvFile
|
|
206
|
-
};
|
|
207
|
-
//# sourceMappingURL=chunk-Z5NXYJIG.js.map
|