@lievclouds/dsh-cortex 0.5.4 → 1.0.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.
Potentially problematic release.
This version of @lievclouds/dsh-cortex might be problematic. Click here for more details.
- package/README.md +1 -1
- package/client.js +434 -412
- package/index.js +7 -0
- package/locale/en.json +6 -6
- package/locale/zh.json +6 -6
- package/package.json +115 -110
- package/src/cortex-ui/dsh/css-overrides.css +8 -0
- package/src/cortex-ui/renderer/App.tsx +39 -0
- package/src/cortex-ui/renderer/components/miniapp/FileTree.tsx +161 -0
- package/src/cortex-ui/renderer/components/miniapp/MiniappCard.tsx +263 -0
- package/src/cortex-ui/renderer/components/miniapp/MiniappDetail.tsx +1493 -0
- package/src/cortex-ui/renderer/components/retest/CurlImportDialog.tsx +158 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterCollectionsDialog.tsx +327 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterHistoryDialog.tsx +242 -0
- package/src/cortex-ui/renderer/components/retest/RepeaterPanel.tsx +291 -137
- package/src/cortex-ui/renderer/components/retest/YakitSendPanel.tsx +411 -0
- package/src/cortex-ui/renderer/i18n/messages/common.ts +2 -0
- package/src/cortex-ui/renderer/i18n/messages/fuzzer.ts +32 -0
- package/src/cortex-ui/renderer/i18n/messages/index.ts +5 -1
- package/src/cortex-ui/renderer/i18n/messages/miniapp.ts +392 -0
- package/src/cortex-ui/renderer/i18n/messages/retest.ts +144 -2
- package/src/cortex-ui/renderer/lib/curl.ts +635 -0
- package/src/cortex-ui/renderer/lib/miniappApi.ts +459 -0
- package/src/cortex-ui/renderer/lib/navigation.ts +13 -1
- package/src/cortex-ui/renderer/lib/repeaterRaw.ts +102 -0
- package/src/cortex-ui/renderer/lib/repeaterStoreApi.ts +163 -0
- package/src/cortex-ui/renderer/lib/retestResponse.ts +64 -17
- package/src/cortex-ui/renderer/pages/FuzzerPage.tsx +212 -0
- package/src/cortex-ui/renderer/pages/MiniappPage.tsx +664 -0
- package/src/host/cortex/index.js +42 -1
- package/src/host/cortex/repeater-store.js +411 -0
- package/src/host/cortex/repeater.js +15 -2
- package/src/host/cortex/tools.js +2 -0
- package/src/host/miniapp/analyze.js +1078 -0
- package/src/host/miniapp/assets-import.js +294 -0
- package/src/host/miniapp/detect.js +426 -0
- package/src/host/miniapp/format.js +263 -0
- package/src/host/miniapp/roots.js +360 -0
- package/src/host/miniapp/routes.js +304 -0
- package/src/host/miniapp/service.js +559 -0
- package/src/host/miniapp/store.js +756 -0
- package/src/host/miniapp/tools.js +335 -0
- package/src/host/miniapp/unpack.js +1010 -0
- package/src/host/miniapp/wxapkg.js +416 -0
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import type { MouseEvent as ReactMouseEvent } from 'react'
|
|
2
|
+
import { Archive, Download, FileSearch, FolderOpen, Loader2, ScanSearch } from 'lucide-react'
|
|
3
|
+
import { Badge } from '@renderer/components/ui/badge'
|
|
4
|
+
import { Button } from '@renderer/components/ui/button'
|
|
5
|
+
import { formatBytes, formatDateTime } from '@renderer/lib/format'
|
|
6
|
+
import type { MiniappRow, MiniappStatus } from '@renderer/lib/miniappApi'
|
|
7
|
+
import { useI18n } from '@renderer/i18n'
|
|
8
|
+
import { cn } from '@renderer/lib/utils'
|
|
9
|
+
|
|
10
|
+
/** Quiet tinted chips matching the rest of the app's status badges. */
|
|
11
|
+
const STATUS_STYLES: Record<MiniappStatus, { badge: string; dot: string }> = {
|
|
12
|
+
detected: {
|
|
13
|
+
badge: 'border-sky-200/70 bg-sky-50 text-sky-700',
|
|
14
|
+
dot: 'bg-sky-500'
|
|
15
|
+
},
|
|
16
|
+
decrypting: {
|
|
17
|
+
badge: 'border-amber-200/70 bg-amber-50 text-amber-800',
|
|
18
|
+
dot: 'bg-amber-500 animate-pulse'
|
|
19
|
+
},
|
|
20
|
+
unpacked: {
|
|
21
|
+
badge: 'border-emerald-200/70 bg-emerald-50 text-emerald-700',
|
|
22
|
+
dot: 'bg-emerald-500'
|
|
23
|
+
},
|
|
24
|
+
unsupported: {
|
|
25
|
+
badge: 'border-orange-200/70 bg-orange-50 text-orange-700',
|
|
26
|
+
dot: 'bg-orange-500'
|
|
27
|
+
},
|
|
28
|
+
failed: {
|
|
29
|
+
badge: 'border-red-200/70 bg-red-50 text-red-700',
|
|
30
|
+
dot: 'bg-red-500'
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function MiniappStatusBadge({ status }: { status: MiniappStatus }) {
|
|
35
|
+
const { t } = useI18n()
|
|
36
|
+
const style = STATUS_STYLES[status] ?? STATUS_STYLES.failed
|
|
37
|
+
return (
|
|
38
|
+
<Badge className={cn(style.badge, 'whitespace-nowrap')}>
|
|
39
|
+
<span aria-hidden="true" className={cn('h-1.5 w-1.5 rounded-full', style.dot)} />
|
|
40
|
+
{t(`miniapp.status.${status}`)}
|
|
41
|
+
</Badge>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function MiniappFormatBadge({ format }: { format: string }) {
|
|
46
|
+
const { t } = useI18n()
|
|
47
|
+
const known = format === 'plain' || format === 'v1mmwx' || format === 'unknown'
|
|
48
|
+
return (
|
|
49
|
+
<Badge variant="outline" className="whitespace-nowrap font-mono text-[10px]">
|
|
50
|
+
{t(`miniapp.format.${known ? format : 'unknown'}`)}
|
|
51
|
+
</Badge>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export type MiniappCardAction = 'unpack' | 'analyze' | 'import' | 'open'
|
|
56
|
+
|
|
57
|
+
interface MiniappCardProps {
|
|
58
|
+
item: MiniappRow
|
|
59
|
+
/** An unpack/analyze/import request for this source is in flight. */
|
|
60
|
+
busy: boolean
|
|
61
|
+
busyAction: MiniappCardAction | null
|
|
62
|
+
onOpen: (item: MiniappRow) => void
|
|
63
|
+
onUnpack: (item: MiniappRow) => void
|
|
64
|
+
onAnalyze: (item: MiniappRow) => void
|
|
65
|
+
onImport: (item: MiniappRow) => void
|
|
66
|
+
onOpenDir: (item: MiniappRow) => void
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* One detected wxapkg source row: identity, version/size/format/status plus the
|
|
71
|
+
* five source actions. The row itself is a button-like surface that opens the
|
|
72
|
+
* detail sheet; the action buttons stop propagation so they never race it.
|
|
73
|
+
*/
|
|
74
|
+
export function MiniappCard({
|
|
75
|
+
item,
|
|
76
|
+
busy,
|
|
77
|
+
busyAction,
|
|
78
|
+
onOpen,
|
|
79
|
+
onUnpack,
|
|
80
|
+
onAnalyze,
|
|
81
|
+
onImport,
|
|
82
|
+
onOpenDir
|
|
83
|
+
}: MiniappCardProps) {
|
|
84
|
+
const { t } = useI18n()
|
|
85
|
+
const unpacked = item.status === 'unpacked'
|
|
86
|
+
const error = (item.error ?? '').trim()
|
|
87
|
+
const failed = item.status === 'unsupported' || item.status === 'failed'
|
|
88
|
+
const versionLabel =
|
|
89
|
+
(item.version ?? '').trim().length > 0
|
|
90
|
+
? t('miniapp.card.version', { version: item.version })
|
|
91
|
+
: t('miniapp.card.noVersion')
|
|
92
|
+
const versionCount = item.version_count ?? 1
|
|
93
|
+
const appName = (item.app_name ?? '').trim()
|
|
94
|
+
const kindLabel =
|
|
95
|
+
item.kind === 'plugin'
|
|
96
|
+
? t('miniapp.kind.plugin')
|
|
97
|
+
: item.kind === 'library'
|
|
98
|
+
? t('miniapp.kind.library')
|
|
99
|
+
: item.kind === 'unknown'
|
|
100
|
+
? t('miniapp.kind.unknown')
|
|
101
|
+
: t('miniapp.unnamed')
|
|
102
|
+
const title = appName.length > 0 ? appName : kindLabel
|
|
103
|
+
|
|
104
|
+
const stop = (event: ReactMouseEvent) => event.stopPropagation()
|
|
105
|
+
const run = (event: ReactMouseEvent, handler: (item: MiniappRow) => void) => {
|
|
106
|
+
event.stopPropagation()
|
|
107
|
+
handler(item)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<li className="border-b border-border last:border-b-0">
|
|
112
|
+
<div
|
|
113
|
+
data-testid="miniapp-row"
|
|
114
|
+
data-miniapp-id={item.id}
|
|
115
|
+
data-status={item.status}
|
|
116
|
+
role="button"
|
|
117
|
+
tabIndex={0}
|
|
118
|
+
aria-label={title}
|
|
119
|
+
onClick={() => onOpen(item)}
|
|
120
|
+
onKeyDown={(event) => {
|
|
121
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
122
|
+
event.preventDefault()
|
|
123
|
+
onOpen(item)
|
|
124
|
+
}
|
|
125
|
+
}}
|
|
126
|
+
className="flex cursor-pointer flex-col gap-2 px-4 py-3 transition-colors duration-150 hover:bg-sidebar focus-visible:bg-accent-soft focus-visible:outline-none"
|
|
127
|
+
>
|
|
128
|
+
<div className="flex min-w-0 flex-wrap items-center gap-2">
|
|
129
|
+
<span className="min-w-0 truncate text-[12.5px] font-medium text-foreground">{title}</span>
|
|
130
|
+
<MiniappStatusBadge status={item.status} />
|
|
131
|
+
<MiniappFormatBadge format={item.format} />
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 font-mono text-[10.5px] text-muted-foreground">
|
|
135
|
+
{item.appid !== title ? <span className="truncate">{item.appid}</span> : null}
|
|
136
|
+
<span className="tabular-nums">{versionLabel}</span>
|
|
137
|
+
{versionCount > 1 ? (
|
|
138
|
+
<span className="tabular-nums">{t('miniapp.card.versions', { count: versionCount })}</span>
|
|
139
|
+
) : null}
|
|
140
|
+
{(item.source_count ?? 1) > 1 ? (
|
|
141
|
+
<span className="tabular-nums" title={item.package_dir}>
|
|
142
|
+
{t('miniapp.card.copies', { count: item.source_count })}
|
|
143
|
+
</span>
|
|
144
|
+
) : null}
|
|
145
|
+
<span className="tabular-nums">{formatBytes(item.size_bytes)}</span>
|
|
146
|
+
{item.file_count > 0 ? (
|
|
147
|
+
<span className="tabular-nums">{t('miniapp.card.files', { count: item.file_count })}</span>
|
|
148
|
+
) : null}
|
|
149
|
+
<span className="tabular-nums">{t('miniapp.card.updated', { time: formatDateTime(item.updated_at) })}</span>
|
|
150
|
+
<span className="min-w-0 truncate" title={item.package_dir}>
|
|
151
|
+
{item.root_kind}
|
|
152
|
+
</span>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
{failed && error.length > 0 ? (
|
|
156
|
+
<p
|
|
157
|
+
role="alert"
|
|
158
|
+
className={
|
|
159
|
+
item.status === 'unsupported'
|
|
160
|
+
? 'break-all rounded-md border border-amber-200 bg-amber-50 px-2 py-1 text-[10.5px] leading-relaxed text-amber-800'
|
|
161
|
+
: 'break-all rounded-md border border-red-200 bg-red-50 px-2 py-1 text-[10.5px] leading-relaxed text-red-700'
|
|
162
|
+
}
|
|
163
|
+
>
|
|
164
|
+
{t(item.status === 'unsupported' ? 'miniapp.card.unsupportedLabel' : 'miniapp.card.errorLabel', {
|
|
165
|
+
error
|
|
166
|
+
})}
|
|
167
|
+
</p>
|
|
168
|
+
) : null}
|
|
169
|
+
|
|
170
|
+
<div
|
|
171
|
+
className="flex flex-wrap items-center gap-1.5"
|
|
172
|
+
onClick={stop}
|
|
173
|
+
onKeyDown={(event) => event.stopPropagation()}
|
|
174
|
+
>
|
|
175
|
+
<Button
|
|
176
|
+
variant="outline"
|
|
177
|
+
size="xs"
|
|
178
|
+
data-testid="miniapp-unpack"
|
|
179
|
+
data-miniapp-id={item.id}
|
|
180
|
+
disabled={busy}
|
|
181
|
+
onClick={(event) => run(event, onUnpack)}
|
|
182
|
+
className="gap-1.5"
|
|
183
|
+
>
|
|
184
|
+
{busy && busyAction === 'unpack' ? (
|
|
185
|
+
<Loader2 aria-hidden="true" className="h-3 w-3 animate-spin" />
|
|
186
|
+
) : (
|
|
187
|
+
<Archive aria-hidden="true" className="h-3 w-3" />
|
|
188
|
+
)}
|
|
189
|
+
{busy && busyAction === 'unpack'
|
|
190
|
+
? t('miniapp.action.unpacking')
|
|
191
|
+
: t('miniapp.action.unpack')}
|
|
192
|
+
</Button>
|
|
193
|
+
<Button
|
|
194
|
+
variant="outline"
|
|
195
|
+
size="xs"
|
|
196
|
+
data-testid="miniapp-browse"
|
|
197
|
+
data-miniapp-id={item.id}
|
|
198
|
+
disabled={!unpacked}
|
|
199
|
+
onClick={(event) => run(event, onOpen)}
|
|
200
|
+
className="gap-1.5"
|
|
201
|
+
>
|
|
202
|
+
<FileSearch aria-hidden="true" className="h-3 w-3" />
|
|
203
|
+
{t('miniapp.action.browse')}
|
|
204
|
+
</Button>
|
|
205
|
+
<Button
|
|
206
|
+
variant="outline"
|
|
207
|
+
size="xs"
|
|
208
|
+
data-testid="miniapp-analyze"
|
|
209
|
+
data-miniapp-id={item.id}
|
|
210
|
+
disabled={!unpacked || busy}
|
|
211
|
+
onClick={(event) => run(event, onAnalyze)}
|
|
212
|
+
className="gap-1.5"
|
|
213
|
+
>
|
|
214
|
+
{busy && busyAction === 'analyze' ? (
|
|
215
|
+
<Loader2 aria-hidden="true" className="h-3 w-3 animate-spin" />
|
|
216
|
+
) : (
|
|
217
|
+
<ScanSearch aria-hidden="true" className="h-3 w-3" />
|
|
218
|
+
)}
|
|
219
|
+
{busy && busyAction === 'analyze'
|
|
220
|
+
? t('miniapp.action.analyzing')
|
|
221
|
+
: t('miniapp.action.analyze')}
|
|
222
|
+
</Button>
|
|
223
|
+
<Button
|
|
224
|
+
variant="outline"
|
|
225
|
+
size="xs"
|
|
226
|
+
data-testid="miniapp-import"
|
|
227
|
+
data-miniapp-id={item.id}
|
|
228
|
+
disabled={!unpacked || busy}
|
|
229
|
+
onClick={(event) => run(event, onImport)}
|
|
230
|
+
className="gap-1.5"
|
|
231
|
+
>
|
|
232
|
+
{busy && busyAction === 'import' ? (
|
|
233
|
+
<Loader2 aria-hidden="true" className="h-3 w-3 animate-spin" />
|
|
234
|
+
) : (
|
|
235
|
+
<Download aria-hidden="true" className="h-3 w-3" />
|
|
236
|
+
)}
|
|
237
|
+
{busy && busyAction === 'import'
|
|
238
|
+
? t('miniapp.action.importing')
|
|
239
|
+
: t('miniapp.action.import')}
|
|
240
|
+
</Button>
|
|
241
|
+
<Button
|
|
242
|
+
variant="ghost"
|
|
243
|
+
size="xs"
|
|
244
|
+
data-testid="miniapp-open"
|
|
245
|
+
data-miniapp-id={item.id}
|
|
246
|
+
disabled={!unpacked || busy}
|
|
247
|
+
onClick={(event) => run(event, onOpenDir)}
|
|
248
|
+
className="gap-1.5"
|
|
249
|
+
>
|
|
250
|
+
{busy && busyAction === 'open' ? (
|
|
251
|
+
<Loader2 aria-hidden="true" className="h-3 w-3 animate-spin" />
|
|
252
|
+
) : (
|
|
253
|
+
<FolderOpen aria-hidden="true" className="h-3 w-3" />
|
|
254
|
+
)}
|
|
255
|
+
{busy && busyAction === 'open'
|
|
256
|
+
? t('miniapp.action.opening')
|
|
257
|
+
: t('miniapp.action.openDir')}
|
|
258
|
+
</Button>
|
|
259
|
+
</div>
|
|
260
|
+
</div>
|
|
261
|
+
</li>
|
|
262
|
+
)
|
|
263
|
+
}
|