@akanjs/devkit 1.0.20 → 2.1.0-rc.0

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.
Files changed (194) hide show
  1. package/aiEditor.ts +304 -0
  2. package/akanApp/akanApp.host.ts +393 -0
  3. package/akanApp/index.ts +1 -0
  4. package/akanConfig/akanConfig.test.ts +236 -0
  5. package/akanConfig/akanConfig.ts +384 -0
  6. package/akanConfig/index.ts +2 -0
  7. package/akanConfig/types.ts +23 -0
  8. package/applicationBuildReporter.ts +69 -0
  9. package/applicationBuildRunner.ts +302 -0
  10. package/applicationReleasePackager.ts +206 -0
  11. package/artifact/implicitRootLayout.ts +155 -0
  12. package/artifact/index.ts +1 -0
  13. package/artifact/routeSeedIndex.test.ts +98 -0
  14. package/artifact/routeSeedIndex.ts +130 -0
  15. package/auth.ts +41 -0
  16. package/builder.ts +164 -0
  17. package/capacitor.base.config.ts +88 -0
  18. package/capacitorApp.ts +440 -0
  19. package/commandDecorators/argMeta.ts +102 -0
  20. package/commandDecorators/command.ts +343 -0
  21. package/commandDecorators/commandBuilder.ts +224 -0
  22. package/commandDecorators/commandDecorators.test.ts +212 -0
  23. package/commandDecorators/commandMeta.ts +7 -0
  24. package/commandDecorators/dependencyBuilder.ts +100 -0
  25. package/{esm/src/commandDecorators/helpFormatter.js → commandDecorators/helpFormatter.ts} +100 -47
  26. package/{esm/src/commandDecorators/index.js → commandDecorators/index.ts} +4 -2
  27. package/commandDecorators/targetMeta.ts +31 -0
  28. package/commandDecorators/types.ts +10 -0
  29. package/constants.ts +25 -0
  30. package/createTunnel.ts +36 -0
  31. package/dependencyScanner.ts +357 -0
  32. package/devkitUtils.test.ts +259 -0
  33. package/executors.test.ts +315 -0
  34. package/executors.ts +1390 -0
  35. package/{esm/src/extractDeps.js → extractDeps.ts} +26 -20
  36. package/{esm/src/fileEditor.js → fileEditor.ts} +51 -32
  37. package/fileSys.ts +39 -0
  38. package/frontendBuild/allRoutesBuilder.ts +103 -0
  39. package/frontendBuild/buildRouteClient.test.ts +190 -0
  40. package/frontendBuild/clientBuildTypes.ts +114 -0
  41. package/frontendBuild/clientEntriesBundler.ts +303 -0
  42. package/frontendBuild/clientEntryDiscovery.ts +199 -0
  43. package/frontendBuild/csrArtifactBuilder.ts +237 -0
  44. package/frontendBuild/cssCompiler.ts +286 -0
  45. package/frontendBuild/cssImportResolver.ts +116 -0
  46. package/frontendBuild/fontOptimizer.ts +427 -0
  47. package/frontendBuild/frontendBuild.test.ts +204 -0
  48. package/frontendBuild/hmrChangeClassifier.ts +28 -0
  49. package/frontendBuild/hmrWatcher.ts +102 -0
  50. package/frontendBuild/index.ts +18 -0
  51. package/frontendBuild/pagesBundleBuilder.ts +137 -0
  52. package/frontendBuild/pagesEntrySourceGenerator.ts +37 -0
  53. package/frontendBuild/precompressArtifacts.ts +59 -0
  54. package/frontendBuild/routeClientBuilder.ts +290 -0
  55. package/frontendBuild/routesManifestArtifactSerializer.ts +62 -0
  56. package/frontendBuild/ssrBaseArtifactBuilder.ts +139 -0
  57. package/frontendBuild/vendorSpecifiers.ts +16 -0
  58. package/frontendBuild/watchRootResolver.ts +28 -0
  59. package/getCredentials.ts +19 -0
  60. package/getDirname.ts +3 -0
  61. package/getModelFileData.ts +59 -0
  62. package/getRelatedCnsts.ts +313 -0
  63. package/guideline.ts +19 -0
  64. package/incrementalBuilder/incrementalBuilder.host.test.ts +51 -0
  65. package/incrementalBuilder/incrementalBuilder.host.ts +152 -0
  66. package/incrementalBuilder/incrementalBuilder.proc.ts +331 -0
  67. package/incrementalBuilder/index.ts +1 -0
  68. package/{esm/src/index.js → index.ts} +28 -15
  69. package/lint/no-deep-internal-import.grit +25 -0
  70. package/lint/no-import-client-functions.grit +32 -0
  71. package/lint/no-import-external-library.grit +21 -0
  72. package/lint/no-js-private-class-method.grit +42 -0
  73. package/lint/no-use-client-in-server.grit +7 -0
  74. package/lint/non-scalar-props-restricted.grit +13 -0
  75. package/linter.ts +271 -0
  76. package/mobile/index.ts +1 -0
  77. package/mobile/mobileTarget.test.ts +53 -0
  78. package/mobile/mobileTarget.ts +88 -0
  79. package/package.json +48 -31
  80. package/prompter.ts +72 -0
  81. package/scanInfo.ts +606 -0
  82. package/selectModel.ts +11 -0
  83. package/{esm/src/spinner.js → spinner.ts} +22 -28
  84. package/{esm/src/capacitorApp.js → src/capacitorApp.ts} +82 -81
  85. package/sshTunnel.ts +152 -0
  86. package/{esm/src/streamAi.js → streamAi.ts} +18 -12
  87. package/transforms/barrelAnalyzer.ts +278 -0
  88. package/transforms/barrelImportsPlugin.ts +504 -0
  89. package/transforms/externalizeFrameworkPlugin.ts +185 -0
  90. package/transforms/index.ts +5 -0
  91. package/transforms/rscUseClientTransform.ts +59 -0
  92. package/transforms/transforms.test.ts +208 -0
  93. package/transforms/useClientBundlePlugin.ts +47 -0
  94. package/tsconfig.json +37 -0
  95. package/typeChecker.ts +264 -0
  96. package/types.ts +44 -0
  97. package/ui/MultiScrollList.tsx +242 -0
  98. package/ui/ScrollList.tsx +107 -0
  99. package/ui/index.ts +2 -0
  100. package/{esm/src/uploadRelease.js → uploadRelease.ts} +50 -34
  101. package/{esm/src/useStdoutDimensions.js → useStdoutDimensions.ts} +5 -5
  102. package/README.md +0 -7
  103. package/cjs/index.js +0 -21
  104. package/cjs/src/aiEditor.js +0 -311
  105. package/cjs/src/auth.js +0 -72
  106. package/cjs/src/builder.js +0 -114
  107. package/cjs/src/capacitorApp.js +0 -313
  108. package/cjs/src/commandDecorators/argMeta.js +0 -88
  109. package/cjs/src/commandDecorators/command.js +0 -324
  110. package/cjs/src/commandDecorators/commandMeta.js +0 -30
  111. package/cjs/src/commandDecorators/helpFormatter.js +0 -211
  112. package/cjs/src/commandDecorators/index.js +0 -31
  113. package/cjs/src/commandDecorators/targetMeta.js +0 -57
  114. package/cjs/src/commandDecorators/types.js +0 -15
  115. package/cjs/src/constants.js +0 -46
  116. package/cjs/src/createTunnel.js +0 -49
  117. package/cjs/src/dependencyScanner.js +0 -220
  118. package/cjs/src/executors.js +0 -964
  119. package/cjs/src/extractDeps.js +0 -103
  120. package/cjs/src/fileEditor.js +0 -120
  121. package/cjs/src/getCredentials.js +0 -44
  122. package/cjs/src/getDirname.js +0 -38
  123. package/cjs/src/getModelFileData.js +0 -66
  124. package/cjs/src/getRelatedCnsts.js +0 -260
  125. package/cjs/src/guideline.js +0 -15
  126. package/cjs/src/index.js +0 -65
  127. package/cjs/src/linter.js +0 -238
  128. package/cjs/src/prompter.js +0 -85
  129. package/cjs/src/scanInfo.js +0 -491
  130. package/cjs/src/selectModel.js +0 -46
  131. package/cjs/src/spinner.js +0 -93
  132. package/cjs/src/streamAi.js +0 -62
  133. package/cjs/src/typeChecker.js +0 -207
  134. package/cjs/src/types.js +0 -15
  135. package/cjs/src/uploadRelease.js +0 -112
  136. package/cjs/src/useStdoutDimensions.js +0 -43
  137. package/esm/index.js +0 -1
  138. package/esm/src/aiEditor.js +0 -282
  139. package/esm/src/auth.js +0 -42
  140. package/esm/src/builder.js +0 -81
  141. package/esm/src/commandDecorators/argMeta.js +0 -54
  142. package/esm/src/commandDecorators/command.js +0 -290
  143. package/esm/src/commandDecorators/commandMeta.js +0 -7
  144. package/esm/src/commandDecorators/targetMeta.js +0 -33
  145. package/esm/src/commandDecorators/types.js +0 -0
  146. package/esm/src/constants.js +0 -17
  147. package/esm/src/createTunnel.js +0 -26
  148. package/esm/src/dependencyScanner.js +0 -187
  149. package/esm/src/executors.js +0 -928
  150. package/esm/src/getCredentials.js +0 -11
  151. package/esm/src/getDirname.js +0 -5
  152. package/esm/src/getModelFileData.js +0 -33
  153. package/esm/src/getRelatedCnsts.js +0 -221
  154. package/esm/src/guideline.js +0 -0
  155. package/esm/src/linter.js +0 -205
  156. package/esm/src/prompter.js +0 -51
  157. package/esm/src/scanInfo.js +0 -455
  158. package/esm/src/selectModel.js +0 -13
  159. package/esm/src/typeChecker.js +0 -174
  160. package/esm/src/types.js +0 -0
  161. package/index.d.ts +0 -1
  162. package/src/aiEditor.d.ts +0 -50
  163. package/src/auth.d.ts +0 -9
  164. package/src/builder.d.ts +0 -18
  165. package/src/capacitorApp.d.ts +0 -39
  166. package/src/commandDecorators/argMeta.d.ts +0 -67
  167. package/src/commandDecorators/command.d.ts +0 -2
  168. package/src/commandDecorators/commandMeta.d.ts +0 -2
  169. package/src/commandDecorators/helpFormatter.d.ts +0 -3
  170. package/src/commandDecorators/index.d.ts +0 -6
  171. package/src/commandDecorators/targetMeta.d.ts +0 -19
  172. package/src/commandDecorators/types.d.ts +0 -1
  173. package/src/constants.d.ts +0 -26
  174. package/src/createTunnel.d.ts +0 -8
  175. package/src/dependencyScanner.d.ts +0 -23
  176. package/src/executors.d.ts +0 -296
  177. package/src/extractDeps.d.ts +0 -7
  178. package/src/fileEditor.d.ts +0 -16
  179. package/src/getCredentials.d.ts +0 -12
  180. package/src/getDirname.d.ts +0 -1
  181. package/src/getModelFileData.d.ts +0 -16
  182. package/src/getRelatedCnsts.d.ts +0 -53
  183. package/src/guideline.d.ts +0 -19
  184. package/src/index.d.ts +0 -23
  185. package/src/linter.d.ts +0 -109
  186. package/src/prompter.d.ts +0 -14
  187. package/src/scanInfo.d.ts +0 -82
  188. package/src/selectModel.d.ts +0 -1
  189. package/src/spinner.d.ts +0 -20
  190. package/src/streamAi.d.ts +0 -6
  191. package/src/typeChecker.d.ts +0 -52
  192. package/src/types.d.ts +0 -31
  193. package/src/uploadRelease.d.ts +0 -10
  194. package/src/useStdoutDimensions.d.ts +0 -1
@@ -0,0 +1,242 @@
1
+ "use client";
2
+ import { Box, Text, useInput } from "ink";
3
+ import { useEffect, useState } from "react";
4
+ import { useStdoutDimensions } from "../useStdoutDimensions";
5
+
6
+ interface MultiScrollListProps {
7
+ logList: {
8
+ title: string;
9
+ logs: {
10
+ type: string;
11
+ content: string;
12
+ }[];
13
+ color: string;
14
+ }[];
15
+
16
+ maxLength?: number;
17
+ }
18
+
19
+ /**
20
+ * @param logList 로그 목록
21
+ * @param maxLength 최대 로그 길이 (기본 100)
22
+ */
23
+ const HEADER_HEIGHT = 1;
24
+ const FOOTER_HEIGHT = 1;
25
+ const OUTER_BORDER_HEIGHT = 2;
26
+ const BORDER_HEIGHT = 2;
27
+ const ANSI_ESCAPE_RE = new RegExp(`${String.fromCharCode(27)}(?:[@-Z\\\\-_]|\\[[\\s\\S]*?[@-~])`, "g");
28
+
29
+ export const MultiScrollList = ({ logList, maxLength = 100 }: MultiScrollListProps) => {
30
+ // 창 너비, 높이
31
+ const [width, height] = useStdoutDimensions();
32
+ // 탭별 로그 렌더링
33
+
34
+ const [focusLog, setFocusLog] = useState<{ type: string; content: string }[]>([]);
35
+ // 탭별 로그 길이 저장 (스크롤시 로그 길이 변화로 위치 조정)
36
+ const [lengthMap, setLengthMap] = useState<Map<number, number>>(new Map());
37
+ // 스크롤 위치
38
+ const [scrollPos, setScrollPos] = useState(0);
39
+ // 현재 포커싱탭 인덱스
40
+ const [tabIndex, setTabIndex] = useState<number>(0);
41
+ // 스크롤 실행 여부
42
+ const [isRunning, setIsRunning] = useState(false);
43
+ // 박스 높이 (보더 사이즈 2, 헤더 사이즈 1, 푸터 사이즈 5 기본 1)
44
+ const [boxHeight, setBoxHeight] = useState(
45
+ height - HEADER_HEIGHT - OUTER_BORDER_HEIGHT - FOOTER_HEIGHT - BORDER_HEIGHT,
46
+ );
47
+ const boxWidth = width - 27;
48
+
49
+ // maxLength에 따라 로그 배열을 제한하는 유틸리티 함수
50
+ const getLimitedLogs = (logs: { type: string; content: string }[]) => {
51
+ const sortedLogs = logs.reduce<{ type: string; content: string }[]>((acc, log) => {
52
+ // log.content.length가 boxWidth보다 큰 경우 잘라서 줄 수 만큼 추가
53
+ // ANSI 코드 보관
54
+
55
+ const content = log.content.replace(ANSI_ESCAPE_RE, "");
56
+ if (content.length > boxWidth) {
57
+ const lines = Math.ceil(content.length / boxWidth);
58
+ for (let i = 0; i < lines; i++) {
59
+ acc.push({ type: log.type, content: content.slice(i * boxWidth, (i + 1) * boxWidth) });
60
+ }
61
+ } else {
62
+ acc.push(log);
63
+ }
64
+ return acc;
65
+ }, []);
66
+ return sortedLogs.length > maxLength ? sortedLogs.slice(sortedLogs.length - maxLength) : sortedLogs;
67
+ };
68
+
69
+ // 입력 이벤트 처리
70
+ useInput((input, key) => {
71
+ // 탭 키 이벤트 처리(포커싱 탭 변경)
72
+ if (key.tab) {
73
+ setTabIndex((prev: number) => (prev + 1) % logList.length);
74
+ setScrollPos(0);
75
+ setIsRunning(false);
76
+ }
77
+ // 스크롤 중지 이벤트 처리 (포커싱까지 완전히 종료)
78
+ if (key.escape) {
79
+ setScrollPos(0);
80
+ setIsRunning(false);
81
+ }
82
+ // 스크롤 중지 이벤트 처리 (포커싱 유지)
83
+ if (input === " ") {
84
+ setScrollPos(0);
85
+ setIsRunning(false);
86
+ }
87
+ // 스크롤 다운 이벤트 처리
88
+ if (key.downArrow && scrollPos > 0) {
89
+ if (key.shift) {
90
+ const newScrollPos = scrollPos - 10;
91
+ // 스크롤 최소 위치에 도달 경우에 대한 예외 처리
92
+ if (newScrollPos < 0) {
93
+ setScrollPos(0);
94
+ } else {
95
+ setScrollPos(newScrollPos);
96
+ }
97
+ } else {
98
+ const newScrollPos = scrollPos - 1;
99
+ setScrollPos(newScrollPos);
100
+ }
101
+ }
102
+ // 스크롤 업 이벤트 처리
103
+ if (key.upArrow && scrollPos < logList[tabIndex].logs.length - boxHeight) {
104
+ const limitedLogs = getLimitedLogs(logList[tabIndex].logs);
105
+ if (scrollPos < limitedLogs.length - boxHeight) {
106
+ // 스크롤 업 이벤트 처리 (스크롤 속도 증가)
107
+ if (key.shift) {
108
+ const newScrollPos = scrollPos + 10;
109
+ // 스크롤 최대 위치에 도달 경우에 대한 예외 처리
110
+ if (newScrollPos > limitedLogs.length - boxHeight) {
111
+ setScrollPos(limitedLogs.length - boxHeight);
112
+ } else {
113
+ setScrollPos(newScrollPos);
114
+ }
115
+ } else {
116
+ setScrollPos(scrollPos + 1);
117
+ }
118
+ if (!isRunning) setIsRunning(true);
119
+ }
120
+ }
121
+ });
122
+
123
+ useEffect(() => {
124
+ // 공통 로직을 함수로 추출
125
+ const getLogsToRender = (logs: { type: string; content: string }[], index: number) => {
126
+ // maxLength에 따라 로그 제한
127
+ const limitedLogs = getLimitedLogs(logs);
128
+ // 로그 중 boxWidth보다 긴 것이 있는 경우 잘라서 출력
129
+
130
+ // 활성 탭이고 스크롤 중인 특별한 경우
131
+ if (scrollPos > 0 && tabIndex === index) {
132
+ return limitedLogs.slice(limitedLogs.length - boxHeight - scrollPos, limitedLogs.length - scrollPos);
133
+ }
134
+ // 로그가 표시 영역보다 큰 경우 (공통 로직)
135
+ else if (limitedLogs.length > boxHeight) {
136
+ return limitedLogs.slice(limitedLogs.length - boxHeight, limitedLogs.length);
137
+ }
138
+ // 로그가 표시 영역에 모두 들어가는 경우 (공통 로직)
139
+ else {
140
+ return limitedLogs;
141
+ }
142
+ };
143
+
144
+ // isRunning일 때 로직
145
+ if (isRunning) {
146
+ // 선택된 탭의 로그 길이 변화 확인 및 스크롤 포지션 업데이트
147
+ if (lengthMap.has(tabIndex)) {
148
+ const tabLength = lengthMap.get(tabIndex);
149
+ const limitedLogsLength = Math.min(logList[tabIndex].logs.length, maxLength);
150
+ if (tabLength && tabLength < limitedLogsLength) {
151
+ setScrollPos(scrollPos + 1);
152
+ lengthMap.set(tabIndex, limitedLogsLength);
153
+ }
154
+ }
155
+
156
+ // 스크롤 위치에 따른 로그 렌더링 업데이트
157
+
158
+ setFocusLog(getLogsToRender(logList[tabIndex].logs, tabIndex));
159
+ }
160
+ // isRunning이 아닐 때 로직
161
+ else {
162
+ // lengthMap 업데이트 및 초기 렌더링
163
+ setFocusLog(getLogsToRender(logList[tabIndex].logs, tabIndex));
164
+ }
165
+ }, [logList, isRunning, scrollPos, tabIndex, boxHeight, maxLength]);
166
+
167
+ useEffect(() => {
168
+ setBoxHeight(height - HEADER_HEIGHT - OUTER_BORDER_HEIGHT - FOOTER_HEIGHT - BORDER_HEIGHT);
169
+ }, [height]);
170
+
171
+ // 초기 로그 사이즈 설정
172
+ useEffect(() => {
173
+ setLengthMap(new Map(logList.map((log, index) => [index, Math.min(log.logs.length, maxLength)])));
174
+ }, [logList, maxLength]);
175
+
176
+ return (
177
+ <Box width={width} height={height} borderStyle="round" borderColor="blackBright" flexDirection="column">
178
+ <Box width={"100%"} height={boxHeight + BORDER_HEIGHT + HEADER_HEIGHT} flexDirection="row">
179
+ <Box width={30} height="100%" flexDirection="column">
180
+ <Box>
181
+ <Text>
182
+ List {tabIndex + 1}/{logList.length}
183
+ </Text>
184
+ </Box>
185
+ <Box borderStyle="round" borderColor="blackBright" width={"100%"} height="100%" flexDirection="column">
186
+ {logList.map((log, index) => {
187
+ return (
188
+ <Text key={index} color={index === tabIndex ? "green" : "white"}>
189
+ <Text>●</Text>&nbsp;
190
+ {log.title.length > 25 ? `${log.title.slice(0, 25)}...` : log.title}
191
+ </Text>
192
+ );
193
+ })}
194
+ </Box>
195
+ </Box>
196
+ <Box width={"100%"} height="100%" flexDirection="column">
197
+ <Box height={1}>
198
+ <Text color={logList[tabIndex].color}>
199
+ {logList[tabIndex].title} {logList[tabIndex].logs.length}
200
+ </Text>
201
+ </Box>
202
+ <Box
203
+ borderStyle={isRunning ? "double" : "round"}
204
+ flexDirection="column"
205
+ borderColor={logList[tabIndex].color}
206
+ width="100%"
207
+ height="100%"
208
+ >
209
+ {scrollPos > 0 ? (
210
+ <>
211
+ {focusLog.slice(0, focusLog.length - 1).map((log, index) => {
212
+ return (
213
+ <Text underline={false} color={log.type === "error" ? "red" : "white"} key={index}>
214
+ {log.content}
215
+ </Text>
216
+ );
217
+ })}
218
+ <Text underline={false} backgroundColor="green">
219
+ Scrolling... +{scrollPos}
220
+ </Text>
221
+ </>
222
+ ) : (
223
+ focusLog.map((log, index) => {
224
+ return (
225
+ <Text underline={false} color={log.type === "error" ? "red" : "white"} key={index}>
226
+ {log.content}
227
+ </Text>
228
+ );
229
+ })
230
+ )}
231
+ </Box>
232
+ </Box>
233
+ </Box>
234
+ {/* <Text>{renderMultiLogs[tabIndex][0]}</Text> */}
235
+ <Box width={"100%"} height={FOOTER_HEIGHT}>
236
+ <Text dimColor={true}>
237
+ Tab : switch tab | Up / Down(shift : x10) : scroll | Space : back last position | Esc : stop scrolling
238
+ </Text>
239
+ </Box>
240
+ </Box>
241
+ );
242
+ };
@@ -0,0 +1,107 @@
1
+ "use client";
2
+ import { Box, type BoxProps, Newline, Text, useInput } from "ink";
3
+ import { type ReactNode, useEffect, useState } from "react";
4
+ import { useStdoutDimensions } from "../useStdoutDimensions";
5
+
6
+ interface ScrollListProps extends BoxProps {
7
+ list: ReactNode[];
8
+ }
9
+
10
+ export const ScrollList = ({ list, ...props }: ScrollListProps) => {
11
+ const [renderLogs, setRenderLogs] = useState<ReactNode[]>(list);
12
+ const [width, height] = useStdoutDimensions();
13
+ const [scrollPos, setScrollPos] = useState(0);
14
+ const [isRunning, setIsRunning] = useState(false);
15
+ const [boxHeight, setBoxHeight] = useState(height - 3);
16
+
17
+ useInput((input, key) => {
18
+ if (key.escape) {
19
+ setIsRunning(false);
20
+ setScrollPos(0);
21
+ }
22
+ if (input === " " && isRunning) {
23
+ setIsRunning(false);
24
+ setScrollPos(0);
25
+ }
26
+ if (key.downArrow && scrollPos > 0) {
27
+ if (key.shift) {
28
+ setScrollPos(scrollPos - 10);
29
+ } else {
30
+ setScrollPos(scrollPos - 1);
31
+ }
32
+ }
33
+ if (key.upArrow && scrollPos < list.length - boxHeight) {
34
+ if (key.shift) {
35
+ setScrollPos(scrollPos + 10);
36
+ } else {
37
+ setScrollPos(scrollPos + 1);
38
+ }
39
+ }
40
+ });
41
+
42
+ useEffect(() => {
43
+ //1 로그가 박스 높이보다 크면 스크롤 위치 조정
44
+ //2. scrollPos값에 따라 포커싱 위치 변경하고 pos 활성시 포커싱 위치 고정
45
+ if (isRunning) {
46
+ setScrollPos(scrollPos + 1);
47
+ return;
48
+ }
49
+ if (list.length > boxHeight) {
50
+ setRenderLogs(list.slice(list.length - boxHeight, list.length));
51
+ } else {
52
+ setRenderLogs(list);
53
+ }
54
+ }, [list, isRunning]);
55
+
56
+ useEffect(() => {
57
+ setBoxHeight(Math.floor(height * 0.9));
58
+ }, [height]);
59
+
60
+ useEffect(() => {
61
+ if (scrollPos > 0) {
62
+ setRenderLogs(list.slice(list.length - boxHeight - scrollPos, list.length - scrollPos));
63
+ setIsRunning(true);
64
+ } else {
65
+ setRenderLogs(list.slice(list.length - boxHeight, list.length));
66
+ setIsRunning(false);
67
+ }
68
+ }, [scrollPos]);
69
+
70
+ return (
71
+ <Box {...props} width={width} height={"100%"} flexDirection="column">
72
+ <Box borderStyle="round" width={width} height={height - 3}>
73
+ <Newline />
74
+ <Text>
75
+ {isRunning ? (
76
+ <>
77
+ {renderLogs.slice(0, renderLogs.length - 1).map((log, index) => (
78
+ <>
79
+ <Text key={index}>{log}</Text>
80
+ <Newline />
81
+ </>
82
+ ))}
83
+ <Text backgroundColor="green">scrolling... + {scrollPos}</Text>
84
+ </>
85
+ ) : (
86
+ <>
87
+ {renderLogs.map((log, index) => (
88
+ <>
89
+ <Text key={index}>{log}</Text>
90
+ <Newline />
91
+ </>
92
+ ))}
93
+ </>
94
+ )}
95
+ </Text>
96
+ </Box>
97
+ <Box>
98
+ <Text dimColor={true}>
99
+ You can use the following shortcuts:
100
+ <Newline />* <Text backgroundColor="green">up</Text> and <Text backgroundColor="green">down</Text> to scroll.{" "}
101
+ <Text backgroundColor="green">shift</Text> to scroll faster.
102
+ <Newline />* <Text backgroundColor="green">escape</Text> to stop scrolling.
103
+ </Text>
104
+ </Box>
105
+ </Box>
106
+ );
107
+ };
package/ui/index.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./MultiScrollList";
2
+ export * from "./ScrollList";
@@ -1,71 +1,90 @@
1
- import { Logger } from "@akanjs/common";
2
- import axios from "axios";
3
- import FormData from "form-data";
4
- import fs from "fs";
1
+ import { HttpClient, Logger } from "akanjs/common";
2
+
5
3
  import { Spinner } from "./spinner";
6
- const spinning = (message) => {
4
+
5
+ const spinning = (message: string) => {
7
6
  const spinner = new Spinner(message, { prefix: message, enableSpin: true }).start();
8
7
  return spinner;
9
8
  };
10
- const uploadRelease = async (appName, {
11
- workspaceRoot,
12
- environment,
13
- buildNum,
14
- platformVersion,
15
- os,
16
- local
17
- }) => {
9
+ export const uploadRelease = async (
10
+ appName: string,
11
+ {
12
+ workspaceRoot,
13
+ environment,
14
+ buildNum,
15
+ platformVersion,
16
+ os,
17
+ local,
18
+ }: {
19
+ workspaceRoot: string;
20
+ environment: string;
21
+ buildNum: number;
22
+ platformVersion?: string;
23
+ os?: "android" | "ios";
24
+ local?: boolean;
25
+ },
26
+ ) => {
18
27
  const logger = new Logger("uploadRelease");
19
- const basePath = local ? "http://localhost:8080/backend" : "https://cloud.akanjs.com/backend";
28
+ const basePath = local ? "http://localhost:8282/backend" : "https://cloud.akanjs.com/backend";
29
+ const httpClient = new HttpClient(basePath);
20
30
  const buildPath = `${workspaceRoot}/releases/builds/${appName}-release.tar.gz`;
21
31
  const appBuildPath = `${workspaceRoot}/releases/builds/${appName}-appBuild.zip`;
22
32
  const sourcePath = `${workspaceRoot}/releases/sources/${appName}-source.tar.gz`;
33
+
23
34
  const readingFilesSpinner = spinning("Reading files...");
24
35
  try {
25
- const build = fs.readFileSync(buildPath);
26
- const source = fs.readFileSync(sourcePath);
27
- const appBuild = fs.readFileSync(appBuildPath);
28
- const buildStat = fs.statSync(buildPath);
29
- const sourceStat = fs.statSync(sourcePath);
30
- const appBuildStat = fs.statSync(appBuildPath);
36
+ const buildFile = Bun.file(buildPath);
37
+ const sourceFile = Bun.file(sourcePath);
38
+ const appBuildFile = Bun.file(appBuildPath);
39
+ const buildStat = { mtime: new Date(buildFile.lastModified), size: buildFile.size };
40
+ const sourceStat = { mtime: new Date(sourceFile.lastModified), size: sourceFile.size };
41
+ const appBuildStat = { mtime: new Date(appBuildFile.lastModified), size: appBuildFile.size };
31
42
  readingFilesSpinner.succeed("Reading files... done");
43
+
32
44
  const preparingFormSpinner = spinning("Preparing form data...");
33
45
  const formData = new FormData();
34
- formData.append("files", build, `${appName}-release.tar.gz`);
35
- formData.append("files", source, `${appName}-source.tar.gz`);
36
- formData.append("files", appBuild, `${appName}-appBuild.zip`);
46
+ formData.append("files", buildFile, `${appName}-release.tar.gz`);
47
+ formData.append("files", sourceFile, `${appName}-source.tar.gz`);
48
+ formData.append("files", appBuildFile, `${appName}-appBuild.zip`);
37
49
  formData.append(
38
50
  "metas",
39
51
  JSON.stringify([
40
52
  { lastModifiedAt: buildStat.mtime, size: buildStat.size },
41
53
  { lastModifiedAt: sourceStat.mtime, size: sourceStat.size },
42
- { lastModifiedAt: appBuildStat.mtime, size: appBuildStat.size }
43
- ])
54
+ { lastModifiedAt: appBuildStat.mtime, size: appBuildStat.size },
55
+ ]),
44
56
  );
45
57
  formData.append("type", "release");
46
58
  preparingFormSpinner.succeed("Preparing form data... done");
59
+
47
60
  try {
48
61
  const uploadingFilesSpinner = spinning("Uploading files to server...");
49
- const [buildFile, sourceFile, appBuildFile] = (await axios.post(`${basePath}/file/addFilesRestApi`, formData)).data;
62
+ const [buildFile, sourceFile, appBuildFile] = await httpClient.post<
63
+ [{ id: string }, { id: string }, { id: string }]
64
+ >("/file/addFilesRestApi", formData);
50
65
  uploadingFilesSpinner.succeed("Uploading files to server... done");
66
+
51
67
  const fetchingAppSpinner = spinning(`Fetching dev app information for ${appName}...`);
52
68
  const major = platformVersion ? parseInt(platformVersion.split(".")[0]) : 1;
53
69
  const minor = platformVersion ? parseInt(platformVersion.split(".")[1]) : 0;
54
70
  const patch = platformVersion ? parseInt(platformVersion.split(".")[2]) : 0;
55
- const devApp = (await axios.get(`${basePath}/devApp/devAppInName/${appName}`)).data;
71
+
72
+ const devApp = await httpClient.get<{ id: string }>(`/devApp/devAppInName/${appName}`);
56
73
  fetchingAppSpinner.succeed(`Fetching dev app information for ${appName}... done`);
74
+
57
75
  const pushingReleaseSpinner = spinning(`Pushing release to ${environment} environment...`);
58
- const release = (await axios.post(
59
- `${basePath}/release/pushRelease/${devApp.id}/${environment}/${major}/${minor}/${patch}/${sourceFile.id}/${buildFile.id}/${appBuildFile.id}${os ? `/${os}` : ""}`
60
- )).data;
76
+ const release = await httpClient.post<{ id: string }>(
77
+ `/release/pushRelease/${devApp.id}/${environment}/${major}/${minor}/${patch}/${sourceFile.id}/${buildFile.id}/${appBuildFile.id}${os ? `/${os}` : ""}`,
78
+ );
61
79
  pushingReleaseSpinner.succeed(`Pushing release to ${environment} environment... done`);
62
80
  new Spinner(`Successfully pushed release to ${appName}-${environment} server. `, {
63
81
  prefix: `Successfully pushed release to ${appName}-${environment} server. `,
64
- enableSpin: false
82
+ enableSpin: false,
65
83
  }).succeed(`Successfully pushed release to ${appName}-${environment} server. `);
66
84
  return release;
67
85
  } catch (e) {
68
86
  const errorMessage = e instanceof Error ? e.message : "Unknown error";
87
+ logger.error(`Upload release failed: ${errorMessage}`);
69
88
  return null;
70
89
  }
71
90
  } catch (e) {
@@ -74,6 +93,3 @@ const uploadRelease = async (appName, {
74
93
  return null;
75
94
  }
76
95
  };
77
- export {
78
- uploadRelease
79
- };
@@ -1,9 +1,11 @@
1
1
  "use client";
2
2
  import { useStdout } from "ink";
3
3
  import { useEffect, useState } from "react";
4
- const useStdoutDimensions = () => {
4
+
5
+ export const useStdoutDimensions = (): [number, number] => {
5
6
  const { stdout } = useStdout();
6
- const [dimensions, setDimensions] = useState([stdout.columns, stdout.rows]);
7
+ const [dimensions, setDimensions] = useState<[number, number]>([stdout.columns, stdout.rows]);
8
+
7
9
  useEffect(() => {
8
10
  const handler = () => {
9
11
  setDimensions([stdout.columns, stdout.rows]);
@@ -13,8 +15,6 @@ const useStdoutDimensions = () => {
13
15
  stdout.off("resize", handler);
14
16
  };
15
17
  }, [stdout]);
18
+
16
19
  return dimensions;
17
20
  };
18
- export {
19
- useStdoutDimensions
20
- };
package/README.md DELETED
@@ -1,7 +0,0 @@
1
- > 🎉 **Akanjs v2 has been released!**
2
- >
3
- > This package is under maintenance for existing users, but we recommend using Akanjs v2 for new projects.
4
- >
5
- > For the unified and latest version package, please visit [akanjs](https://www.npmjs.com/package/akanjs).
6
-
7
- This package is a sub-library of akanjs. For more information, please refer to [@akanjs/cli](https://www.npmjs.com/package/@akanjs/cli) and the [Akan.js Github](https://github.com/akan-team/akanjs).
package/cjs/index.js DELETED
@@ -1,21 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __getOwnPropNames = Object.getOwnPropertyNames;
4
- var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __copyProps = (to, from, except, desc) => {
6
- if (from && typeof from === "object" || typeof from === "function") {
7
- for (let key of __getOwnPropNames(from))
8
- if (!__hasOwnProp.call(to, key) && key !== except)
9
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
10
- }
11
- return to;
12
- };
13
- var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
- var devkit_exports = {};
16
- module.exports = __toCommonJS(devkit_exports);
17
- __reExport(devkit_exports, require("./src"), module.exports);
18
- // Annotate the CommonJS export names for ESM import in node:
19
- 0 && (module.exports = {
20
- ...require("./src")
21
- });