@koishi-ce/plugin-market 1.1.3 → 1.2.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.
- package/dist/index.js +2 -2
- package/dist/style.css +1 -1
- package/lib/index.d.ts +58 -17
- package/lib/index.mjs +192 -58
- package/package.json +6 -6
- package/src/node/__tests__/commands.test.ts +349 -0
- package/src/node/__tests__/helpers.ts +380 -0
- package/src/node/__tests__/provider.test.ts +340 -0
- package/src/node/__tests__/retry.test.ts +169 -0
- package/src/node/dependencies/service.ts +118 -0
- package/src/node/dependencies/snapshot.test.ts +176 -0
- package/src/node/dependencies/snapshot.ts +92 -0
- package/src/node/dependencies/types.ts +39 -0
- package/src/node/deps.ts +1 -14
- package/src/node/index.ts +7 -8
- package/src/node/installer/index.ts +38 -20
- package/src/node/installer/installer.test.ts +282 -0
- package/src/node/installer/manifest.ts +15 -0
- package/src/index.test.ts +0 -1242
package/dist/style.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.confirm-panel td.arrow{padding:0}.confirm-panel td.arrow span{justify-content:center;align-items:center;display:flex}.confirm-panel .el-dialog__footer{justify-content:space-between;align-items:center;display:flex}.manual-panel .k-comment{margin-top:0}.dep-package-view[data-v-0fc4cb55]{height:3rem;position:relative}.dep-package-view .el-button[data-v-0fc4cb55]{width:4rem}.page-deps{flex-flow:column;display:flex}.page-deps .body-container{margin-top:-1px;transform:translateY(1px)}.page-deps table tr:first-child{border-top:none}.page-deps tbody tr{transition:all .3s}.page-deps tbody tr:hover{background-color:var(--k-side-bg)}@media (width<=768px){.page-deps td{padding:.5em}}.theme-color.primary{color:var(--primary)}.theme-color.success{color:var(--success)}.theme-color.warning{color:var(--warning)}.theme-color.danger{color:var(--danger)}.install-panel .el-dialog__header{align-items:center;gap:0 .5em;padding-bottom:4px;padding-right:36px;display:flex}.install-panel .el-dialog__header .el-dialog__title{color:var(--fg1);flex:none;margin-right:.5rem;font-weight:500}.install-panel .el-dialog__header .el-select{flex:auto;max-width:12.5rem;margin:-2px 0 -4px}.install-panel .warning{color:var(--k-color-warning)}.install-panel .danger{color:var(--k-color-danger)}.install-panel .version-badges{float:right;margin-right:-12px}.install-panel .el-dialog__body{min-height:40px;padding:0 20px}.install-panel .el-dialog__body>div{margin:1rem 0}.install-panel .el-dialog__body:last-child{padding-bottom:1rem}.install-panel table thead td,.install-panel table thead th,.install-panel table tbody td,.install-panel table tbody th{white-space:nowrap;padding:.5em .875em}.install-panel span.link:hover{cursor:pointer;text-decoration:underline}.install-panel .el-button+.el-button{margin-left:1rem}.install-panel .el-dialog__footer{justify-content:space-between;align-items:center;display:flex}.install-panel .wrapper{display:inline-flex;position:relative}.install-panel .wrapper .shadow{letter-spacing:1px;visibility:hidden;padding-right:22px}.install-panel .wrapper .el-select{position:absolute;top:50%;left:0;right:0;transform:translateY(-50%)}.dot-hint:before{content:"";background-color:currentColor;border-radius:100%;width:.5rem;height:.5rem;transition:background-color .3s;position:absolute;top:50%;right:20px;transform:translateY(-50%);box-shadow:1px 1px 2px #3333}.market-filter-item[data-v-23068a68]{box-sizing:border-box;color:var(--k-text-normal);z-index:2;cursor:pointer;border-radius:8px;align-items:center;height:28px;margin:2px 0;padding:0 .5rem;transition:color .2s,background-color .2s;display:flex}.market-filter-item[data-v-23068a68]:hover{color:var(--k-text-dark);background-color:var(--k-hover-bg)}.market-filter-item.active[data-v-23068a68]{color:var(--k-color-primary);background-color:color-mix(in srgb, var(--k-color-primary) 10%, transparent)}.market-filter-item.active .text[data-v-23068a68]{font-weight:600}.market-filter-item.active.verified[data-v-23068a68],.market-filter-item.active.newborn[data-v-23068a68]{color:var(--k-color-success);background-color:color-mix(in srgb, var(--k-color-success) 10%, transparent)}.market-filter-item.active.preview[data-v-23068a68],.market-filter-item.active.portable[data-v-23068a68]{color:var(--k-color-warning);background-color:color-mix(in srgb, var(--k-color-warning) 10%, transparent)}.market-filter-item.active.insecure[data-v-23068a68]{color:var(--k-color-danger);background-color:color-mix(in srgb, var(--k-color-danger) 10%, transparent)}.market-filter-item.disabled[data-v-23068a68]{opacity:.5;text-decoration:line-through;text-decoration-thickness:2px}.market-filter-item .icon[data-v-23068a68]{justify-content:center;align-items:center;width:1.75rem;margin-right:4px;display:inline-flex}.market-filter-item:not(.active) .order[data-v-23068a68]{display:none}.market-filter-item .order[data-v-23068a68]{justify-content:center;align-items:center;width:1.75rem;display:inline-flex}.market-filter-item svg[data-v-23068a68]{max-width:1.125rem;height:1rem}.market-filter-item .text[data-v-23068a68],.market-filter-item .count[data-v-23068a68]{font-size:14px;font-weight:500;line-height:20px}.market-filter-item .count[data-v-23068a68]{opacity:.7;margin-right:4px;font-size:12px}.market-filter-item .spacer[data-v-23068a68]{flex:1}.cat-adapter[data-v-715b4290]{--c:#38bdf8}.cat-general[data-v-715b4290]{--c:#4ade80}.cat-extension[data-v-715b4290]{--c:#a78bfa}.cat-webui[data-v-715b4290]{--c:#fb923c}.cat-manage[data-v-715b4290]{--c:#facc15}.cat-preset[data-v-715b4290]{--c:#60a5fa}.cat-image[data-v-715b4290]{--c:#f472b6}.cat-media[data-v-715b4290]{--c:#e879f9}.cat-tool[data-v-715b4290]{--c:#94a3b8}.cat-life[data-v-715b4290]{--c:#34d399}.cat-ai[data-v-715b4290]{--c:#818cf8}.cat-meme[data-v-715b4290]{--c:#fbbf24}.cat-game[data-v-715b4290]{--c:#f87171}.cat-gametool[data-v-715b4290]{--c:#c084fc}.cat-other[data-v-715b4290]{--c:#64748b}.market-package[data-v-715b4290]{box-sizing:border-box;background-color:var(--k-card-bg);border:1px solid var(--k-color-border);contain:layout paint style;border-radius:12px;width:100%;max-width:540px;height:calc(12.5rem + 2px);margin:0;padding:1rem 1.25rem;transition:border-color .18s,box-shadow .18s,background-color .18s;position:relative}.market-package[data-v-715b4290]:hover{border-color:var(--k-color-primary);box-shadow:0 4px 12px #0000000f}.market-package .market-icon[data-v-715b4290]{height:1em;display:inline}.market-package .header[data-v-715b4290],.market-package .footer[data-v-715b4290]{flex:none}.market-package .header[data-v-715b4290]{position:relative}.market-package .header .left[data-v-715b4290]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--c) 35%, var(--k-color-border));background:linear-gradient(135deg, color-mix(in srgb, var(--c) 18%, var(--k-card-bg)), color-mix(in srgb, var(--c) 10%, var(--k-card-bg)));width:3.5rem;height:3.5rem;transition:var(--color-transition);border-radius:10px}.market-package .header .left svg[data-v-715b4290]{height:1.75rem;color:var(--c)}.market-package .header h2[data-v-715b4290]{align-items:center;margin:0;font-size:1.125rem;font-weight:600;line-height:1.2;display:flex}.market-package .header h2 .title[data-v-715b4290]{flex:0 auto;line-height:1.5rem;display:inline-block}.market-package .header .heartbeat[data-v-715b4290]{height:1.5rem;color:var(--k-text-light);align-items:center;gap:5px;font-size:12px;display:inline-flex}.market-package .header .heartbeat .market-icon[data-v-715b4290]{width:12px;height:12px;color:color-mix(in srgb, #eb4d55 var(--heart-mix,0%), var(--k-text-light));opacity:var(--heart-opacity,.5);filter:drop-shadow(0 0 calc(var(--heart-glow,0) * 4px) rgb(235, 77, 85, calc(var(--heart-glow,0) * .45)));flex:none;transition:color .3s,opacity .3s}.market-package .badge-float[data-v-715b4290]{position:absolute;bottom:2.5rem;right:1.25rem}.market-package .badge-pill[data-v-715b4290]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--k-color-success) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-success) 10%, transparent);height:20px;color:var(--k-color-success);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:10px;align-items:center;gap:3px;padding:0 6px;font-size:12px;font-weight:500;line-height:20px;display:inline-flex}.market-package .badge-pill .market-icon[data-v-715b4290]{width:12px;height:12px}.market-package .badge-pill.preview[data-v-715b4290]{border-color:color-mix(in srgb, var(--k-color-warning) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-warning) 10%, transparent);color:var(--k-color-warning)}.market-package .badge-pill.insecure[data-v-715b4290]{border-color:color-mix(in srgb, var(--k-color-danger) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-danger) 10%, transparent);color:var(--k-color-danger)}.market-package .desc[data-v-715b4290]{color:var(--k-text-light);word-break:break-word;text-overflow:ellipsis;-webkit-line-clamp:3;-webkit-box-orient:vertical;flex:auto;margin:0;font-size:14px;line-height:1.6;display:-webkit-box;overflow:hidden}.market-package .footer[data-v-715b4290]{cursor:default;height:1.5rem;color:var(--k-text-light);align-items:center;gap:.5rem;margin-bottom:-.25rem;font-size:13px;transition:color .3s;display:flex;overflow:hidden}.market-package .footer[data-v-715b4290]>*{flex:none}.market-package .footer .spacer[data-v-715b4290]{flex:0 2 .5rem}.market-package .footer .long-spacer[data-v-715b4290]{flex:auto}.market-package .footer .market-icon[data-v-715b4290]{vertical-align:-1px;width:16px;height:12px;margin-right:6px}.market-package .footer .avatars[data-v-715b4290]{gap:.25rem;display:flex}.market-package .footer .avatars .avatar[data-v-715b4290]{cursor:pointer;border-radius:100%;width:1.5rem;height:1.5rem}.market-package .footer .avatars .avatar img[data-v-715b4290]{vertical-align:middle;border-radius:100%;width:1.5rem;height:1.5rem}.market-package .footer .avatars .avatar.fallback[data-v-715b4290]{box-sizing:border-box;background:linear-gradient(135deg, color-mix(in srgb, var(--c) 30%, var(--k-card-bg)), color-mix(in srgb, var(--c) 12%, var(--k-card-bg)));color:color-mix(in srgb, var(--c) 80%, var(--k-text-dark));justify-content:center;align-items:center;font-size:.68rem;font-weight:700;display:inline-flex}.market-package .footer .avatars .avatar.fallback[data-v-715b4290]:before{content:attr(data-initial)}@media (width<=420px){.market-package[data-v-715b4290]{height:auto;min-height:11rem;padding:.82rem .9rem}.market-package .header .left[data-v-715b4290]{width:3rem;height:3rem}.market-package h2[data-v-715b4290]{font-size:1rem}.market-package .badge-float[data-v-715b4290]{bottom:2.3rem;right:.9rem}.market-package .footer[data-v-715b4290]{flex-wrap:wrap;height:auto}.market-package .footer .long-spacer[data-v-715b4290]{display:none}}.package-list[data-v-7274b89c]{gap:var(--card-margin);flex:1 0 auto;grid-template-columns:repeat(auto-fill,minmax(336px,1fr));justify-items:center;display:grid}.pagination[data-v-7274b89c]{margin:var(--card-margin) 0;justify-content:center}.k-empty[data-v-7274b89c]{flex:1 0 auto}.search-box[data-v-98462ea9]{border:1.5px solid var(--k-color-border);box-sizing:border-box;background-color:var(--k-card-bg);border-radius:2rem;align-items:center;width:100%;max-width:640px;margin:2rem auto 0;transition:border-color .2s,box-shadow .2s;display:flex;box-shadow:0 2px 12px #0000000f,0 1px 3px #0000000a}.search-box[data-v-98462ea9]:focus-within{border-color:var(--k-color-primary);box-shadow:0 0 0 3px color-mix(in srgb, var(--k-color-primary) 15%, transparent), 0 2px 12px #0000000f, 0 1px 3px #0000000a}.search-container[data-v-98462ea9]{flex-wrap:wrap;flex:auto;align-items:center;gap:8px 6px;padding:.75rem 0 .75rem 1.25rem;display:flex}.search-container input[data-v-98462ea9]{box-sizing:border-box;min-width:10rem;height:1.25rem;color:inherit;background-color:#0000;border:none;outline:none;flex:auto;padding:0;font-size:.925rem}.search-action[data-v-98462ea9]{cursor:pointer;flex-direction:column;flex:none;justify-content:center;align-items:center;width:3rem;height:2.5rem;display:flex}.search-action .market-icon[data-v-98462ea9]{opacity:.45;height:1rem;transition:opacity .2s}.search-action:hover .market-icon[data-v-98462ea9]{opacity:.85}.search-action:hover .market-icon.search[data-v-98462ea9],.search-action:not(:hover) .market-icon.close[data-v-98462ea9]{display:none}.search-word[data-v-98462ea9]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--k-color-primary) 25%, transparent);background-color:color-mix(in srgb, var(--k-color-primary) 12%, transparent);height:1.375rem;color:var(--k-color-primary);white-space:nowrap;vertical-align:baseline;cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;flex:none;padding:0 8px;font-size:12px;font-weight:500;line-height:calc(1.375rem - 2px);transition:opacity .3s,background-color .3s,border-color .3s;display:inline-block}.search-word.invalid[data-v-98462ea9]{opacity:.5;text-decoration:line-through}.search-word.invalid[data-v-98462ea9]:hover{opacity:1}@media (width<=420px){.search-box[data-v-98462ea9]{border-radius:12px}}.page-market .layout-main .el-scrollbar__view{padding:0 var(--card-margin);flex-direction:column;min-height:100%;display:flex}.page-market .layout-left .market-filter-group{margin:1.5rem 0;padding:0 1rem}.page-market .layout-left h2{letter-spacing:.08em;text-transform:uppercase;color:var(--k-text-light);opacity:.7;margin:0;padding:6px .5rem;font-size:11px;font-weight:700}.market-loading{flex-direction:column;flex:1 0 auto;justify-content:center;align-items:center;gap:2rem;min-height:50vh;display:flex}.market-loading .el-loading-spinner{margin-top:0}.market-slow.k-comment{max-width:640px}.market-hint{width:100%;color:var(--el-text-color-regular);font-size:var(--el-font-size-base);font-weight:var(--el-font-weight-primary);margin:1rem 0 .75rem;transition:color .3s}.market-container .k-button{margin-left:1rem;padding:.35em .85em;transform:translateY(-1px)}.market-error.k-comment{margin-left:2rem;margin-right:2rem}.page-market .el-scrollbar__thumb{background-clip:content-box;background-color:color-mix(in srgb, var(--k-color-primary) 26%, var(--fg3));border:2px solid #0000;border-radius:999px;min-height:32px}.page-market .el-scrollbar__thumb:hover{background-color:color-mix(in srgb, var(--k-color-primary) 44%, var(--fg3))}.k-status .el-progress-bar{width:120px;margin-right:2px}.dialog-config-fork .el-dialog__header .el-dialog__title{color:var(--fg1);flex:none;margin-right:.5rem;font-weight:500}.dialog-config-fork .status-light{margin-right:.75rem}.dialog-config-fork .actions{justify-content:flex-end;align-items:center;gap:0 .5rem;display:flex}.dialog-config-fork .action{cursor:pointer;width:1.25rem;color:var(--fg2);transition:var(--color-transition);justify-content:center;display:inline-flex}.dialog-config-fork .action:hover{color:var(--fg1)}.dialog-config-fork .el-dialog__footer{justify-content:space-between;align-items:center;font-size:.9em;display:flex}.modifier,.plugin-view .markdown.usage{margin-bottom:2rem}.plugin-view .markdown.usage h2{font-size:1.25rem}.plugin-tree{width:100%;height:100%;overflow:auto}.plugin-tree .el-scrollbar__view{padding:1rem 0;line-height:2.25rem}.plugin-tree .search{padding:0 1.5rem}.plugin-tree .k-icon-filter{height:15px}.plugin-tree .el-tree-node.is-group>.el-tree-node__content{font-weight:700}.plugin-tree .el-tree-node__content .item{flex:1;justify-content:space-between;align-items:center;height:100%;display:flex;overflow:hidden}.plugin-tree .el-tree-node__content .label{text-overflow:ellipsis;transition:var(--color-transition);overflow:hidden}.plugin-tree .el-tree-node__content .right{height:100%;margin:0 1.5rem 0 .5rem}.end{margin-right:.5rem}.config-header{margin:0 0 2rem;font-size:1.375rem;line-height:2rem}.config-header .k-button{float:right}.plugin-view .k-content>:first-child{margin-top:0}.plugin-select .el-dialog__header{border-bottom:1px solid var(--k-color-divider);justify-content:space-between;align-items:center;margin-right:0;padding:12px 20px;display:flex}.plugin-select .el-dialog__header button{top:2px}.plugin-select .el-dialog__header .title{flex:none}.plugin-select .el-dialog__header .el-input{width:220px;height:2rem;display:inline-block}.plugin-select .el-dialog__body{height:50vh;padding:0;display:flex}.plugin-select .el-dialog__body .tabs{border-right:1px solid var(--k-color-divider);flex:none;width:7.5rem;font-size:15px}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs{width:3rem}}.plugin-select .el-dialog__body .tabs .el-scrollbar__view{padding:.5rem 0}.plugin-select .el-dialog__body .tabs .tab-item{cursor:pointer;height:2rem;transition:var(--color-transition);justify-content:center;align-items:center;padding:0 1rem;font-size:.875rem;display:flex}.plugin-select .el-dialog__body .tabs .tab-item:hover{background-color:var(--k-hover-bg)}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs .tab-item{padding:0}}.plugin-select .el-dialog__body .tabs .tab-item .market-icon{width:1.25rem;height:1rem}.plugin-select .el-dialog__body .tabs .tab-item.active{color:var(--primary)}.plugin-select .el-dialog__body .tabs .tab-item .title{width:3.5rem;margin-left:.5rem}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs .tab-item .title{display:none}}.plugin-select .el-dialog__body .content{flex:auto}.plugin-select .el-dialog__body .content .package{cursor:pointer;transition:var(--color-transition);padding:.5rem 1rem}.plugin-select .el-dialog__body .content .package h3{margin:0 0 .25rem;font-size:16px}.plugin-select .el-dialog__body .content .package p{margin:0;font-size:14px}.plugin-select .el-dialog__body .content .package:hover{background-color:var(--k-hover-bg)}.absolute{position:absolute}.relative{position:relative}.grid{display:grid}.my-8{margin-top:2rem;margin-bottom:2rem}.inline{display:inline}.inline-block{display:inline-block}.hidden{display:none}.h2{height:.5rem}.h3{height:.75rem}.flex{display:flex}.inline-flex{display:inline-flex}.shrink-0{flex-shrink:0}.grow-1{flex-grow:1}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.items-center{align-items:center}.justify-center{justify-content:center}.justify-around{justify-content:space-around}.gap-1{gap:.25rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-4{column-gap:1rem}.gap-y-2{row-gap:.5rem}.overflow-hidden{overflow:hidden}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.b,.border{border-width:1px}.pl-8{padding-left:2rem}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color,#0000001a),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color,#0000001a);box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow)}.outline{outline-style:solid}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease{transition-timing-function:cubic-bezier(.4,0,.2,1)}.dialog-config-fork .status-light,.plugin-tree .status-light{width:.625rem;height:.625rem;transition:var(--color-transition);border-radius:100%;display:inline-block}.dialog-config-fork .status-light.active,.plugin-tree .status-light.active{background-color:var(--k-color-success)}.dialog-config-fork .status-light.pending,.plugin-tree .status-light.pending{background-color:var(--k-color-warning)}.dialog-config-fork .status-light.loading,.plugin-tree .status-light.loading{background-color:var(--k-color-warning);animation:1s infinite status-flash}.dialog-config-fork .status-light.failed,.plugin-tree .status-light.failed{background-color:var(--k-color-danger)}.dialog-config-fork .status-light.disabled:not(.ignore-disabled),.plugin-tree .status-light.disabled:not(.ignore-disabled){opacity:.5;background-color:var(--k-color-disabled)}@keyframes status-flash{0%,to{opacity:0}50%{opacity:1}}
|
|
1
|
+
.confirm-panel td.arrow{padding:0}.confirm-panel td.arrow span{justify-content:center;align-items:center;display:flex}.confirm-panel .el-dialog__footer{justify-content:space-between;align-items:center;display:flex}.theme-color.primary{color:var(--primary)}.theme-color.success{color:var(--success)}.theme-color.warning{color:var(--warning)}.theme-color.danger{color:var(--danger)}.install-panel .el-dialog__header{align-items:center;gap:0 .5em;padding-bottom:4px;padding-right:36px;display:flex}.install-panel .el-dialog__header .el-dialog__title{color:var(--fg1);flex:none;margin-right:.5rem;font-weight:500}.install-panel .el-dialog__header .el-select{flex:auto;max-width:12.5rem;margin:-2px 0 -4px}.install-panel .warning{color:var(--k-color-warning)}.install-panel .danger{color:var(--k-color-danger)}.install-panel .version-badges{float:right;margin-right:-12px}.install-panel .el-dialog__body{min-height:40px;padding:0 20px}.install-panel .el-dialog__body>div{margin:1rem 0}.install-panel .el-dialog__body:last-child{padding-bottom:1rem}.install-panel table thead td,.install-panel table thead th,.install-panel table tbody td,.install-panel table tbody th{white-space:nowrap;padding:.5em .875em}.install-panel span.link:hover{cursor:pointer;text-decoration:underline}.install-panel .el-button+.el-button{margin-left:1rem}.install-panel .el-dialog__footer{justify-content:space-between;align-items:center;display:flex}.install-panel .wrapper{display:inline-flex;position:relative}.install-panel .wrapper .shadow{letter-spacing:1px;visibility:hidden;padding-right:22px}.install-panel .wrapper .el-select{position:absolute;top:50%;left:0;right:0;transform:translateY(-50%)}.dot-hint:before{content:"";background-color:currentColor;border-radius:100%;width:.5rem;height:.5rem;transition:background-color .3s;position:absolute;top:50%;right:20px;transform:translateY(-50%);box-shadow:1px 1px 2px #3333}.market-filter-item[data-v-cc4310be]{box-sizing:border-box;color:var(--k-text-normal);z-index:2;cursor:pointer;border-radius:8px;align-items:center;height:28px;margin:2px 0;padding:0 .5rem;transition:color .2s,background-color .2s;display:flex}.market-filter-item[data-v-cc4310be]:hover{color:var(--k-text-dark);background-color:var(--k-hover-bg)}.market-filter-item.active[data-v-cc4310be]{color:var(--k-color-primary);background-color:color-mix(in srgb, var(--k-color-primary) 10%, transparent)}.market-filter-item.active .text[data-v-cc4310be]{font-weight:600}.market-filter-item.active.verified[data-v-cc4310be],.market-filter-item.active.newborn[data-v-cc4310be]{color:var(--k-color-success);background-color:color-mix(in srgb, var(--k-color-success) 10%, transparent)}.market-filter-item.active.preview[data-v-cc4310be],.market-filter-item.active.portable[data-v-cc4310be]{color:var(--k-color-warning);background-color:color-mix(in srgb, var(--k-color-warning) 10%, transparent)}.market-filter-item.active.insecure[data-v-cc4310be]{color:var(--k-color-danger);background-color:color-mix(in srgb, var(--k-color-danger) 10%, transparent)}.market-filter-item.disabled[data-v-cc4310be]{opacity:.5;text-decoration:line-through;text-decoration-thickness:2px}.market-filter-item .icon[data-v-cc4310be]{justify-content:center;align-items:center;width:1.75rem;margin-right:4px;display:inline-flex}.market-filter-item:not(.active) .order[data-v-cc4310be]{display:none}.market-filter-item .order[data-v-cc4310be]{justify-content:center;align-items:center;width:1.75rem;display:inline-flex}.market-filter-item svg[data-v-cc4310be]{max-width:1.125rem;height:1rem}.market-filter-item .text[data-v-cc4310be],.market-filter-item .count[data-v-cc4310be]{font-size:14px;font-weight:500;line-height:20px}.market-filter-item .count[data-v-cc4310be]{opacity:.7;margin-right:4px;font-size:12px}.market-filter-item .spacer[data-v-cc4310be]{flex:1}.cat-adapter[data-v-d2f1ac33]{--c:#38bdf8}.cat-general[data-v-d2f1ac33]{--c:#4ade80}.cat-extension[data-v-d2f1ac33]{--c:#a78bfa}.cat-webui[data-v-d2f1ac33]{--c:#fb923c}.cat-manage[data-v-d2f1ac33]{--c:#facc15}.cat-preset[data-v-d2f1ac33]{--c:#60a5fa}.cat-image[data-v-d2f1ac33]{--c:#f472b6}.cat-media[data-v-d2f1ac33]{--c:#e879f9}.cat-tool[data-v-d2f1ac33]{--c:#94a3b8}.cat-life[data-v-d2f1ac33]{--c:#34d399}.cat-ai[data-v-d2f1ac33]{--c:#818cf8}.cat-meme[data-v-d2f1ac33]{--c:#fbbf24}.cat-game[data-v-d2f1ac33]{--c:#f87171}.cat-gametool[data-v-d2f1ac33]{--c:#c084fc}.cat-other[data-v-d2f1ac33]{--c:#64748b}.market-package[data-v-d2f1ac33]{box-sizing:border-box;background-color:var(--k-card-bg);border:1px solid var(--k-color-border);contain:layout paint style;border-radius:12px;width:100%;max-width:540px;height:calc(12.5rem + 2px);margin:0;padding:1rem 1.25rem;transition:border-color .18s,box-shadow .18s,background-color .18s;position:relative}.market-package[data-v-d2f1ac33]:hover{border-color:var(--k-color-primary);box-shadow:0 4px 12px #0000000f}.market-package .market-icon[data-v-d2f1ac33]{height:1em;display:inline}.market-package .header[data-v-d2f1ac33],.market-package .footer[data-v-d2f1ac33]{flex:none}.market-package .header[data-v-d2f1ac33]{position:relative}.market-package .header .left[data-v-d2f1ac33]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--c) 35%, var(--k-color-border));background:linear-gradient(135deg, color-mix(in srgb, var(--c) 18%, var(--k-card-bg)), color-mix(in srgb, var(--c) 10%, var(--k-card-bg)));width:3.5rem;height:3.5rem;transition:var(--color-transition);border-radius:10px}.market-package .header .left svg[data-v-d2f1ac33]{height:1.75rem;color:var(--c)}.market-package .header h2[data-v-d2f1ac33]{align-items:center;margin:0;font-size:1.125rem;font-weight:600;line-height:1.2;display:flex}.market-package .header h2 .title[data-v-d2f1ac33]{flex:0 auto;line-height:1.5rem;display:inline-block}.market-package .header .heartbeat[data-v-d2f1ac33]{height:1.5rem;color:var(--k-text-light);align-items:center;gap:5px;font-size:12px;display:inline-flex}.market-package .header .heartbeat .market-icon[data-v-d2f1ac33]{width:12px;height:12px;color:color-mix(in srgb, #eb4d55 var(--heart-mix,0%), var(--k-text-light));opacity:var(--heart-opacity,.5);filter:drop-shadow(0 0 calc(var(--heart-glow,0) * 4px) rgb(235, 77, 85, calc(var(--heart-glow,0) * .45)));flex:none;transition:color .3s,opacity .3s}.market-package .badge-row[data-v-d2f1ac33]{flex:none;justify-content:flex-end;margin:-6px 0;display:flex}.market-package .badge-pill[data-v-d2f1ac33]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--k-color-success) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-success) 10%, transparent);height:20px;color:var(--k-color-success);cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:10px;align-items:center;gap:3px;padding:0 6px;font-size:12px;font-weight:500;line-height:20px;display:inline-flex}.market-package .badge-pill .market-icon[data-v-d2f1ac33]{width:12px;height:12px}.market-package .badge-pill.preview[data-v-d2f1ac33]{border-color:color-mix(in srgb, var(--k-color-warning) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-warning) 10%, transparent);color:var(--k-color-warning)}.market-package .badge-pill.insecure[data-v-d2f1ac33]{border-color:color-mix(in srgb, var(--k-color-danger) 20%, transparent);background-color:color-mix(in srgb, var(--k-color-danger) 10%, transparent);color:var(--k-color-danger)}.market-package .desc[data-v-d2f1ac33]{color:var(--k-text-light);word-break:break-word;text-overflow:ellipsis;-webkit-line-clamp:3;-webkit-box-orient:vertical;flex:auto;margin:0;font-size:14px;line-height:1.6;display:-webkit-box;overflow:hidden}.market-package .footer[data-v-d2f1ac33]{cursor:default;height:1.5rem;color:var(--k-text-light);align-items:center;gap:.5rem;margin-bottom:-.25rem;font-size:13px;transition:color .3s;display:flex;overflow:hidden}.market-package .footer[data-v-d2f1ac33]>*{flex:none}.market-package .footer .spacer[data-v-d2f1ac33]{flex:0 2 .5rem}.market-package .footer .long-spacer[data-v-d2f1ac33]{flex:auto}.market-package .footer .market-icon[data-v-d2f1ac33]{vertical-align:-1px;width:16px;height:12px;margin-right:6px}.market-package .footer .avatars[data-v-d2f1ac33]{gap:.25rem;display:flex}.market-package .footer .avatars .avatar[data-v-d2f1ac33]{cursor:pointer;border-radius:100%;width:1.5rem;height:1.5rem}.market-package .footer .avatars .avatar img[data-v-d2f1ac33]{vertical-align:middle;border-radius:100%;width:1.5rem;height:1.5rem}.market-package .footer .avatars .avatar.fallback[data-v-d2f1ac33]{box-sizing:border-box;background:linear-gradient(135deg, color-mix(in srgb, var(--c) 30%, var(--k-card-bg)), color-mix(in srgb, var(--c) 12%, var(--k-card-bg)));color:color-mix(in srgb, var(--c) 80%, var(--k-text-dark));justify-content:center;align-items:center;font-size:.68rem;font-weight:700;display:inline-flex}.market-package .footer .avatars .avatar.fallback[data-v-d2f1ac33]:before{content:attr(data-initial)}@media (width<=420px){.market-package[data-v-d2f1ac33]{height:auto;min-height:11rem;padding:.82rem .9rem}.market-package .header .left[data-v-d2f1ac33]{width:3rem;height:3rem}.market-package h2[data-v-d2f1ac33]{font-size:1rem}.market-package .footer[data-v-d2f1ac33]{flex-wrap:wrap;height:auto}.market-package .footer .long-spacer[data-v-d2f1ac33]{display:none}}.package-list[data-v-a6a009ba]{gap:var(--card-margin);flex:1 0 auto;grid-template-columns:repeat(auto-fill,minmax(336px,1fr));justify-items:center;display:grid}.pagination[data-v-a6a009ba]{margin:var(--card-margin) 0;justify-content:center}.k-empty[data-v-a6a009ba]{flex:1 0 auto}.search-box[data-v-283643d9]{border:1.5px solid var(--k-color-border);box-sizing:border-box;background-color:var(--k-card-bg);border-radius:2rem;align-items:center;width:100%;max-width:640px;margin:2rem auto 0;transition:border-color .2s,box-shadow .2s;display:flex;box-shadow:0 2px 12px #0000000f,0 1px 3px #0000000a}.search-box[data-v-283643d9]:focus-within{border-color:var(--k-color-primary);box-shadow:0 0 0 3px color-mix(in srgb, var(--k-color-primary) 15%, transparent), 0 2px 12px #0000000f, 0 1px 3px #0000000a}.search-container[data-v-283643d9]{flex-wrap:wrap;flex:auto;align-items:center;gap:8px 6px;padding:.75rem 0 .75rem 1.25rem;display:flex}.search-container input[data-v-283643d9]{box-sizing:border-box;min-width:10rem;height:1.25rem;color:inherit;background-color:#0000;border:none;outline:none;flex:auto;padding:0;font-size:.925rem}.search-action[data-v-283643d9]{cursor:pointer;flex-direction:column;flex:none;justify-content:center;align-items:center;width:3rem;height:2.5rem;display:flex}.search-action .market-icon[data-v-283643d9]{opacity:.45;height:1rem;transition:opacity .2s}.search-action:hover .market-icon[data-v-283643d9]{opacity:.85}.search-action:hover .market-icon.search[data-v-283643d9],.search-action:not(:hover) .market-icon.close[data-v-283643d9]{display:none}.search-word[data-v-283643d9]{box-sizing:border-box;border:1px solid color-mix(in srgb, var(--k-color-primary) 25%, transparent);background-color:color-mix(in srgb, var(--k-color-primary) 12%, transparent);height:1.375rem;color:var(--k-color-primary);white-space:nowrap;vertical-align:baseline;cursor:pointer;-webkit-user-select:none;user-select:none;border-radius:6px;flex:none;padding:0 8px;font-size:12px;font-weight:500;line-height:calc(1.375rem - 2px);transition:opacity .3s,background-color .3s,border-color .3s;display:inline-block}.search-word.invalid[data-v-283643d9]{opacity:.5;text-decoration:line-through}.search-word.invalid[data-v-283643d9]:hover{opacity:1}@media (width<=420px){.search-box[data-v-283643d9]{border-radius:12px}}.page-market .layout-main .el-scrollbar__view{padding:0 var(--card-margin);flex-direction:column;min-height:100%;display:flex}.page-market .layout-left .market-filter-group{margin:1.5rem 0;padding:0 1rem}.page-market .layout-left h2{letter-spacing:.08em;text-transform:uppercase;color:var(--k-text-light);opacity:.7;margin:0;padding:6px .5rem;font-size:11px;font-weight:700}.market-loading{flex-direction:column;flex:1 0 auto;justify-content:center;align-items:center;gap:2rem;min-height:50vh;display:flex}.market-loading .el-loading-spinner{margin-top:0}.market-slow.k-comment{max-width:640px}.market-hint{width:100%;color:var(--el-text-color-regular);font-size:var(--el-font-size-base);font-weight:var(--el-font-weight-primary);margin:1rem 0 .75rem;transition:color .3s}.market-container .k-button{margin-left:1rem;padding:.35em .85em;transform:translateY(-1px)}.market-error.k-comment{margin-left:2rem;margin-right:2rem}.page-market .el-scrollbar__thumb{background-clip:content-box;background-color:color-mix(in srgb, var(--k-color-primary) 26%, var(--fg3));border:2px solid #0000;border-radius:999px;min-height:32px}.page-market .el-scrollbar__thumb:hover{background-color:color-mix(in srgb, var(--k-color-primary) 44%, var(--fg3))}.k-status .el-progress-bar{width:120px;margin-right:2px}.manual-panel .k-comment{margin-top:0}.page-deps{flex-flow:column;display:flex}.page-deps .body-container{margin-top:-1px;transform:translateY(1px)}.deps-toolbar{align-items:center;gap:.75rem;padding:.75rem 1.5rem .75rem 1.25rem;display:flex}.deps-toolbar .deps-filter{flex:none;width:10rem}.deps-toolbar .deps-prerelease{border:1px solid var(--k-border-color);border-radius:var(--el-border-radius-base);height:1.75rem;color:var(--fg2);cursor:pointer;background:0 0;flex:none;align-items:center;gap:.375rem;padding:0 .625rem;font-size:.75rem;transition:color .3s,border-color .3s;display:inline-flex}.deps-toolbar .deps-prerelease .market-icon{width:.875rem;height:.875rem}.deps-toolbar .deps-prerelease:hover,.deps-toolbar .deps-prerelease.active{color:var(--k-color-primary);border-color:var(--k-color-primary)}.deps-toolbar .deps-search{flex:auto;max-width:20rem}.deps-toolbar .deps-summary{color:var(--fg3);white-space:nowrap;gap:.875rem;margin-left:auto;font-size:.8125rem;display:flex}.deps-toolbar .deps-summary .primary{color:var(--k-color-primary)}.deps-toolbar .deps-summary .success{color:var(--k-color-success)}.deps-toolbar .deps-summary .danger{color:var(--k-color-danger)}.deps-toolbar .deps-summary .loading{color:var(--fg3)}.deps-content{flex-flow:column;gap:1.25rem;padding:0 1.25rem 2rem;display:flex}.dep-group>header{border-bottom:1px solid var(--k-border-color);cursor:pointer;-webkit-user-select:none;user-select:none;justify-content:space-between;align-items:center;margin-bottom:.75rem;padding:.375rem .5rem;display:flex}.dep-group>header h2{color:var(--fg1);align-items:center;gap:.5rem;margin:0;font-size:.9375rem;font-weight:600;display:flex}.dep-group>header h2 .market-icon{width:1rem;height:1rem;color:var(--fg3)}.dep-group>header .dep-group-side{align-items:center;gap:.5rem;display:flex}.dep-group>header .dep-group-side .dep-group-count{text-align:center;min-width:1.5rem;color:var(--fg3);background-color:var(--k-side-bg);border-radius:.75rem;padding:.0625rem .5rem;font-size:.75rem}.dep-group>header .dep-group-side .dep-chevron{width:.875rem;height:.875rem;color:var(--fg3);transition:transform .3s}.dep-group>header .dep-group-side .dep-chevron.collapsed{transform:rotate(180deg)}.dep-group.pending>header .market-icon{color:var(--k-color-primary)}.dep-group.updatable>header .market-icon{color:var(--k-color-success)}.dep-group.error>header .market-icon,.dep-group.invalid>header .market-icon{color:var(--k-color-danger)}.dep-grid{grid-template-columns:repeat(auto-fill,minmax(21rem,1fr));gap:.75rem;display:grid}.dep-card{border:1px solid var(--k-border-color);border-radius:var(--el-border-radius-base);background-color:var(--k-side-bg);flex-flow:column;gap:.5rem;padding:.875rem 1rem;transition:border-color .3s;display:flex}.dep-card:hover,.dep-card.pending{border-color:var(--k-color-primary)}.dep-card .dep-card-head{justify-content:space-between;align-items:flex-start;gap:.75rem;display:flex}.dep-card .dep-card-head .dep-card-title{flex-flow:column;min-width:0;display:flex}.dep-card .dep-card-head .dep-card-title h3{color:var(--fg1);text-overflow:ellipsis;white-space:nowrap;margin:0;font-size:.9375rem;font-weight:600;overflow:hidden}.dep-card .dep-card-head .dep-card-title .dep-sub{color:var(--fg3);text-overflow:ellipsis;white-space:nowrap;font-size:.75rem;overflow:hidden}.dep-card .dep-card-head .dep-card-badges{flex:none;align-items:center;gap:.375rem;display:flex}.dep-card .dep-badge{white-space:nowrap;border:1px solid #0000;border-radius:.625rem;padding:.25rem .5rem;font-size:.6875rem;line-height:1}.dep-card .dep-badge.pending{color:var(--k-color-primary);border-color:var(--k-color-primary)}.dep-card .dep-badge.local,.dep-card .dep-badge.ignored{color:var(--fg2);border-color:var(--k-border-color)}.dep-card .dep-badge.invalid,.dep-card .dep-badge.error{color:var(--k-color-danger);border-color:var(--k-color-danger)}.dep-card .dep-badge.updatable{color:var(--k-color-success);border-color:var(--k-color-success)}.dep-card .dep-badge.installed{color:var(--fg3);border-color:var(--k-border-color)}.dep-card .dep-card-meta{flex-wrap:wrap;gap:.5rem 1.25rem;font-size:.8125rem;display:flex}.dep-card .dep-card-meta .dep-meta-item{align-items:baseline;gap:.375rem;display:flex}.dep-card .dep-card-meta .dep-meta-item label{color:var(--fg3)}.dep-card .dep-card-meta .dep-meta-item strong{color:var(--fg1);font-weight:500}.dep-card .dep-card-status{margin:0;font-size:.8125rem}.dep-card .dep-card-status.pending{color:var(--k-color-primary)}.dep-card .dep-card-status.error{color:var(--k-color-danger)}.dep-card .dep-card-actions{flex-wrap:wrap;align-items:center;gap:.5rem;margin-top:auto;display:flex}.dep-card .dep-card-actions .dep-version-select{width:9.5rem}.dep-card .dep-card-actions .dep-version-placeholder{border:1px dashed var(--k-border-color);border-radius:var(--el-border-radius-base);height:1.5rem;color:var(--fg2);cursor:pointer;background:0 0;align-items:center;padding:0 .625rem;font-size:.8125rem;display:inline-flex}.dep-card .dep-card-actions .dep-version-placeholder.static{cursor:default;border-style:solid}.dep-card .dep-card-actions .dep-card-buttons{gap:.5rem;margin-left:auto;display:flex}.deps-apply-bar{z-index:100;border:1px solid var(--k-color-primary);background-color:var(--el-bg-color);border-radius:.5rem;align-items:center;gap:1.5rem;padding:.75rem 1.25rem;display:flex;position:fixed;bottom:1.5rem;left:50%;transform:translate(-50%);box-shadow:0 4px 16px #00000026}.deps-apply-bar .deps-apply-text{flex-flow:column;gap:.125rem;display:flex}.deps-apply-bar .deps-apply-text strong{color:var(--k-color-primary);font-size:.875rem}.deps-apply-bar .deps-apply-text span{color:var(--fg3);font-size:.75rem}@media (width<=768px){.dep-grid{grid-template-columns:1fr}.deps-toolbar{flex-wrap:wrap}.deps-toolbar .deps-search{max-width:none}.deps-toolbar .deps-summary{width:100%;margin-left:0}}.dialog-config-fork .el-dialog__header .el-dialog__title{color:var(--fg1);flex:none;margin-right:.5rem;font-weight:500}.dialog-config-fork .status-light{margin-right:.75rem}.dialog-config-fork .actions{justify-content:flex-end;align-items:center;gap:0 .5rem;display:flex}.dialog-config-fork .action{cursor:pointer;width:1.25rem;color:var(--fg2);transition:var(--color-transition);justify-content:center;display:inline-flex}.dialog-config-fork .action:hover{color:var(--fg1)}.dialog-config-fork .el-dialog__footer{justify-content:space-between;align-items:center;font-size:.9em;display:flex}.modifier,.plugin-view .markdown.usage{margin-bottom:2rem}.plugin-view .markdown.usage h2{font-size:1.25rem}.plugin-tree{width:100%;height:100%;overflow:auto}.plugin-tree .el-scrollbar__view{padding:1rem 0;line-height:2.25rem}.plugin-tree .search{padding:0 1.5rem}.plugin-tree .k-icon-filter{height:15px}.plugin-tree .el-tree-node.is-group>.el-tree-node__content{font-weight:700}.plugin-tree .el-tree-node__content .item{flex:1;justify-content:space-between;align-items:center;height:100%;display:flex;overflow:hidden}.plugin-tree .el-tree-node__content .label{text-overflow:ellipsis;transition:var(--color-transition);overflow:hidden}.plugin-tree .el-tree-node__content .right{height:100%;margin:0 1.5rem 0 .5rem}.end{margin-right:.5rem}.config-header{margin:0 0 2rem;font-size:1.375rem;line-height:2rem}.config-header .k-button{float:right}.plugin-view .k-content>:first-child{margin-top:0}.plugin-select .el-dialog__header{border-bottom:1px solid var(--k-color-divider);justify-content:space-between;align-items:center;margin-right:0;padding:12px 20px;display:flex}.plugin-select .el-dialog__header button{top:2px}.plugin-select .el-dialog__header .title{flex:none}.plugin-select .el-dialog__header .el-input{width:220px;height:2rem;display:inline-block}.plugin-select .el-dialog__body{height:50vh;padding:0;display:flex}.plugin-select .el-dialog__body .tabs{border-right:1px solid var(--k-color-divider);flex:none;width:7.5rem;font-size:15px}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs{width:3rem}}.plugin-select .el-dialog__body .tabs .el-scrollbar__view{padding:.5rem 0}.plugin-select .el-dialog__body .tabs .tab-item{cursor:pointer;height:2rem;transition:var(--color-transition);justify-content:center;align-items:center;padding:0 1rem;font-size:.875rem;display:flex}.plugin-select .el-dialog__body .tabs .tab-item:hover{background-color:var(--k-hover-bg)}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs .tab-item{padding:0}}.plugin-select .el-dialog__body .tabs .tab-item .market-icon{width:1.25rem;height:1rem}.plugin-select .el-dialog__body .tabs .tab-item.active{color:var(--primary)}.plugin-select .el-dialog__body .tabs .tab-item .title{width:3.5rem;margin-left:.5rem}@media screen and (width<=768px){.plugin-select .el-dialog__body .tabs .tab-item .title{display:none}}.plugin-select .el-dialog__body .content{flex:auto}.plugin-select .el-dialog__body .content .package{cursor:pointer;transition:var(--color-transition);padding:.5rem 1rem}.plugin-select .el-dialog__body .content .package h3{margin:0 0 .25rem;font-size:16px}.plugin-select .el-dialog__body .content .package p{margin:0;font-size:14px}.plugin-select .el-dialog__body .content .package:hover{background-color:var(--k-hover-bg)}.absolute{position:absolute}.relative{position:relative}.static{position:static}.grid{display:grid}.my-8{margin-top:2rem;margin-bottom:2rem}.inline{display:inline}.inline-block{display:inline-block}.hidden{display:none}.h2{height:.5rem}.h3{height:.75rem}.flex{display:flex}.inline-flex{display:inline-flex}.shrink-0{flex-shrink:0}.grow-1{flex-grow:1}.flex-row{flex-direction:row}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.transform{transform:translateX(var(--un-translate-x)) translateY(var(--un-translate-y)) translateZ(var(--un-translate-z)) rotate(var(--un-rotate)) rotateX(var(--un-rotate-x)) rotateY(var(--un-rotate-y)) rotateZ(var(--un-rotate-z)) skewX(var(--un-skew-x)) skewY(var(--un-skew-y)) scaleX(var(--un-scale-x)) scaleY(var(--un-scale-y)) scaleZ(var(--un-scale-z))}.items-center{align-items:center}.justify-center{justify-content:center}.justify-around{justify-content:space-around}.gap-1{gap:.25rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-x-4{column-gap:1rem}.gap-y-2{row-gap:.5rem}.overflow-hidden{overflow:hidden}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.border{border-width:1px}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.line-through{text-decoration-line:line-through}.underline{text-decoration-line:underline}.shadow{--un-shadow:var(--un-shadow-inset) 0 1px 3px 0 var(--un-shadow-color,#0000001a),var(--un-shadow-inset) 0 1px 2px -1px var(--un-shadow-color,#0000001a);box-shadow:var(--un-ring-offset-shadow), var(--un-ring-shadow), var(--un-shadow)}.outline{outline-style:solid}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.ease{transition-timing-function:cubic-bezier(.4,0,.2,1)}.dialog-config-fork .status-light,.plugin-tree .status-light{width:.625rem;height:.625rem;transition:var(--color-transition);border-radius:100%;display:inline-block}.dialog-config-fork .status-light.active,.plugin-tree .status-light.active{background-color:var(--k-color-success)}.dialog-config-fork .status-light.pending,.plugin-tree .status-light.pending{background-color:var(--k-color-warning)}.dialog-config-fork .status-light.loading,.plugin-tree .status-light.loading{background-color:var(--k-color-warning);animation:1s infinite status-flash}.dialog-config-fork .status-light.failed,.plugin-tree .status-light.failed{background-color:var(--k-color-danger)}.dialog-config-fork .status-light.disabled:not(.ignore-disabled),.plugin-tree .status-light.disabled:not(.ignore-disabled){opacity:.5;background-color:var(--k-color-disabled)}@keyframes status-flash{0%,to{opacity:0}50%{opacity:1}}
|
|
2
2
|
/*$vite$:1*/
|
package/lib/index.d.ts
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import { Awaitable, Context, Dict, HTTP, Schema, Service } from "@koishi-ce/koishi";
|
|
2
2
|
import { DataService } from "@koishi-ce/console";
|
|
3
3
|
import { DependencyMetaKey, RemotePackage, SearchObject, SearchResult } from "@koishi-ce/registry";
|
|
4
|
-
//#region src/node/
|
|
5
|
-
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
//#region src/node/dependencies/types.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* 依赖条目类型定义(dependencies 数据通道的值类型)。
|
|
7
|
+
*
|
|
8
|
+
* 单个依赖条目的请求范围、已装版本与来源标记;latest / error / fetching
|
|
9
|
+
* 三个可选字段由元数据刷新阶段填充,前端依赖页的分类状态机据此判定
|
|
10
|
+
* 六态。类型集中在此,node 侧声明与 client 侧镜像(console-services.ts)
|
|
11
|
+
* 均从这里取形状。
|
|
12
|
+
*/
|
|
13
|
+
/** registry 元数据拉取失败的归类:404(registry 无此包)与其余(网络等) */
|
|
14
|
+
type DependencyError = "not-found" | "network";
|
|
15
|
+
/** 依赖条目:请求范围、已装版本、来源标记与最新版信息。 */
|
|
9
16
|
interface Dependency {
|
|
10
17
|
/**
|
|
11
18
|
* requested semver range
|
|
@@ -23,13 +30,55 @@ interface Dependency {
|
|
|
23
30
|
invalid?: boolean | undefined;
|
|
24
31
|
/** latest version */
|
|
25
32
|
latest?: string | undefined;
|
|
33
|
+
/** registry 元数据拉取失败的归类(缺失代表尚在拉取或已成功) */
|
|
34
|
+
error?: DependencyError | undefined;
|
|
35
|
+
/** 本轮元数据尚未拉取完成(前端据此显示加载中而非错误) */
|
|
36
|
+
fetching?: boolean | undefined;
|
|
26
37
|
}
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/node/dependencies/service.d.ts
|
|
40
|
+
export declare class DependencyService extends DataService<Dict<Dependency>> {
|
|
41
|
+
static inject: string[];
|
|
42
|
+
/** 快照代次:每次 get() 自增,用于判定后台刷新结果是否已过期 */
|
|
43
|
+
private serial;
|
|
44
|
+
/** 进行中的元数据刷新任务(单飞去重) */
|
|
45
|
+
private task;
|
|
46
|
+
/** 最近一轮快照(新快照构建时复用 latest 与 404 负缓存) */
|
|
47
|
+
private snapshot;
|
|
48
|
+
constructor(ctx: Context);
|
|
49
|
+
get(): Promise<Dict<Dependency>>;
|
|
50
|
+
private ensureMetadata;
|
|
51
|
+
/**
|
|
52
|
+
* 元数据刷新循环:拉完本轮全部 fetching 条目后,若快照代次未变则
|
|
53
|
+
* 触发通道刷新(二拍推送);代次已变(期间有新的 get())则重扫
|
|
54
|
+
* fetching 条目继续,直到无新增且代次一致。
|
|
55
|
+
*/
|
|
56
|
+
private refreshMetadata;
|
|
57
|
+
/** 单个条目的元数据解析:拉取版本表并填充 latest / error。 */
|
|
58
|
+
private resolveMetadata;
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
//#region src/node/installer/versions.d.ts
|
|
62
|
+
/** 归一化后的版本表:版本号 → 依赖元信息(键序即降序,首项为最新版) */
|
|
63
|
+
type VersionMap = Dict<Pick<RemotePackage, DependencyMetaKey>>;
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/node/deps.d.ts
|
|
66
|
+
declare class RegistryProvider extends DataService<Dict<Dict<Pick<RemotePackage, DependencyMetaKey>>>> {
|
|
67
|
+
constructor(ctx: Context);
|
|
68
|
+
get(): Promise<Dict<VersionMap>>;
|
|
69
|
+
}
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/node/installer/index.d.ts
|
|
27
72
|
declare class Installer extends Service {
|
|
28
73
|
http: HTTP;
|
|
29
74
|
endpoint: string | undefined;
|
|
30
75
|
fullCache: Dict<VersionMap>;
|
|
31
76
|
tempCache: Dict<VersionMap>;
|
|
32
77
|
private pkgTasks;
|
|
78
|
+
/** 各包最近一次拉取失败的归类(404 与否);依赖页的 error 徽标消费 */
|
|
79
|
+
pkgErrors: Dict<{
|
|
80
|
+
notFound: boolean;
|
|
81
|
+
}>;
|
|
33
82
|
private manifest;
|
|
34
83
|
private depTask;
|
|
35
84
|
private flushData;
|
|
@@ -46,6 +95,8 @@ declare class Installer extends Service {
|
|
|
46
95
|
getDeps(): Promise<Dict<Dependency>>;
|
|
47
96
|
refreshData(): void;
|
|
48
97
|
refresh(refresh?: boolean): void;
|
|
98
|
+
/** 轻量重建:重读宿主清单并重置依赖汇总任务(registry 缓存不动)。 */
|
|
99
|
+
reload(): void;
|
|
49
100
|
exec(args: string[]): Promise<number>;
|
|
50
101
|
override(deps: Dict<string | null>): Promise<void>;
|
|
51
102
|
private _install;
|
|
@@ -60,16 +111,6 @@ declare namespace Installer {
|
|
|
60
111
|
}
|
|
61
112
|
}
|
|
62
113
|
//#endregion
|
|
63
|
-
//#region src/node/deps.d.ts
|
|
64
|
-
declare class DependencyProvider extends DataService<Dict<Dependency>> {
|
|
65
|
-
constructor(ctx: Context);
|
|
66
|
-
get(): Promise<Dict<Dependency>>;
|
|
67
|
-
}
|
|
68
|
-
declare class RegistryProvider extends DataService<Dict<Dict<Pick<RemotePackage, DependencyMetaKey>>>> {
|
|
69
|
-
constructor(ctx: Context);
|
|
70
|
-
get(): Promise<Dict<VersionMap>>;
|
|
71
|
-
}
|
|
72
|
-
//#endregion
|
|
73
114
|
//#region src/shared/index.d.ts
|
|
74
115
|
declare module "@koishi-ce/console" {
|
|
75
116
|
interface Events {
|
|
@@ -164,7 +205,7 @@ declare module "@koishi-ce/koishi" {
|
|
|
164
205
|
declare module "@koishi-ce/console" {
|
|
165
206
|
namespace Console {
|
|
166
207
|
interface Services {
|
|
167
|
-
dependencies:
|
|
208
|
+
dependencies: DependencyService;
|
|
168
209
|
registry: RegistryProvider;
|
|
169
210
|
}
|
|
170
211
|
}
|
|
@@ -190,4 +231,4 @@ export interface Config {
|
|
|
190
231
|
export declare const Config: Schema<Config>;
|
|
191
232
|
export declare function apply(ctx: Context, config: Config): void;
|
|
192
233
|
//#endregion
|
|
193
|
-
export {
|
|
234
|
+
export { type Dependency, Installer, RegistryProvider };
|
package/lib/index.mjs
CHANGED
|
@@ -5,18 +5,186 @@ import messageZhCN from "./assets/message.zh-CN-D1DbsO3I.yml";
|
|
|
5
5
|
import schemaZhCN from "./assets/schema.zh-CN-Bj0_jaVr.yml";
|
|
6
6
|
import { DataService } from "@koishi-ce/console";
|
|
7
7
|
import Scanner, { isResidentInCache, mapLimit, resolvePackageJson } from "@koishi-ce/registry";
|
|
8
|
-
import { spawn } from "node:child_process";
|
|
9
8
|
import { existsSync, readFileSync, realpathSync } from "node:fs";
|
|
9
|
+
import { spawn } from "node:child_process";
|
|
10
10
|
import { NPM_OFFICIAL_REGISTRY, getLocalRegistry } from "@koishi-ce/utils";
|
|
11
|
-
//#region src/node/
|
|
12
|
-
|
|
11
|
+
//#region src/node/installer/manifest.ts
|
|
12
|
+
/**
|
|
13
|
+
* 项目根 package.json(安装清单)的读写与护栏判定。
|
|
14
|
+
*
|
|
15
|
+
* 只做纯 fs 的清单操作,与 registry 的交互(版本探测、http 缓存)无关,
|
|
16
|
+
* 故独立于 installer 服务;依赖链接的探测属安装完整性校验,见
|
|
17
|
+
* ./integrity.ts。
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* 判断依赖声明是否受护栏保护、不可被安装清单覆盖或删除。两类:
|
|
21
|
+
* - `workspace:` 声明是本仓库(monorepo)对上游名的归属(如 koishi
|
|
22
|
+
* 裸名 shim,见 packages/shim/koishi);
|
|
23
|
+
* - `npm:@koishi-ce/...` alias 是下游脚手架生成项目对上游名的归属
|
|
24
|
+
* (如 "koishi": "npm:@koishi-ce/koishi-shim@^4.18.11",见
|
|
25
|
+
* packages/shim/koishi-shim)。
|
|
26
|
+
* 两者被覆盖或删除都会让 peer 解析失去归属,重新拉下 npm 官方包形成
|
|
27
|
+
* 第二份框架副本。
|
|
28
|
+
*/
|
|
29
|
+
function isGuardedRequest(request) {
|
|
30
|
+
return request?.startsWith("workspace:") === true || request?.startsWith("npm:@koishi-ce") === true;
|
|
31
|
+
}
|
|
32
|
+
function loadManifest(name) {
|
|
33
|
+
const filename = resolvePackageJson(name);
|
|
34
|
+
const meta = JSON.parse(readFileSync(filename, "utf8"));
|
|
35
|
+
meta.dependencies ||= {};
|
|
36
|
+
defineProperty(meta, "$workspace", !filename.includes("node_modules"));
|
|
37
|
+
return meta;
|
|
38
|
+
}
|
|
39
|
+
/** 读取项目根 package.json 原文(安装前的备份快照)。 */
|
|
40
|
+
async function backupManifest(cwd) {
|
|
41
|
+
return Bun.file(resolve(cwd, "package.json")).text();
|
|
42
|
+
}
|
|
43
|
+
/** 把备份原文原样写回项目根 package.json(安装失败的回滚路径)。 */
|
|
44
|
+
async function restoreManifest(cwd, backup) {
|
|
45
|
+
await Bun.write(resolve(cwd, "package.json"), backup);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* 把依赖增删写回项目根 package.json,返回写回后的清单。
|
|
49
|
+
*
|
|
50
|
+
* 现读现写:调用方持有的清单原为构造期的启动快照,运行期间根
|
|
51
|
+
* package.json 可能已被外部更新,基于快照整体重写会抹掉变更,故此处
|
|
52
|
+
* 重新读盘。受护栏保护的声明(见 isGuardedRequest)既不覆盖也不删除。
|
|
53
|
+
*
|
|
54
|
+
* @param cwd 项目根目录
|
|
55
|
+
* @param deps 依赖增删清单(值为 null 表示卸载该依赖)
|
|
56
|
+
*/
|
|
57
|
+
async function writeManifest(cwd, deps) {
|
|
58
|
+
const filename = resolve(cwd, "package.json");
|
|
59
|
+
const manifest = JSON.parse(readFileSync(filename, "utf8"));
|
|
60
|
+
manifest.dependencies ||= {};
|
|
61
|
+
for (const key in deps) if (deps[key]) {
|
|
62
|
+
if (isGuardedRequest(manifest.dependencies[key])) continue;
|
|
63
|
+
manifest.dependencies[key] = deps[key];
|
|
64
|
+
} else if (!isGuardedRequest(manifest.dependencies[key])) delete manifest.dependencies[key];
|
|
65
|
+
manifest.dependencies = Object.fromEntries(Object.entries(manifest.dependencies).sort((a, b) => a[0].localeCompare(b[0])));
|
|
66
|
+
await Bun.write(filename, `${JSON.stringify(manifest, null, " ")}\n`);
|
|
67
|
+
return manifest;
|
|
68
|
+
}
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region src/node/dependencies/snapshot.ts
|
|
71
|
+
/** 以宿主 dependencies 声明为底构建快照骨架(元数据字段全部置为待拉取)。 */
|
|
72
|
+
function collectDependencyRequests(dependencies) {
|
|
73
|
+
const result = {};
|
|
74
|
+
for (const [name, request] of Object.entries(dependencies)) result[name] = {
|
|
75
|
+
request: request.replace(/^[~^]/, ""),
|
|
76
|
+
fetching: true
|
|
77
|
+
};
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* 单个依赖条目的本地解析:已装版本 / workspace 标记 / invalid 标记,
|
|
82
|
+
* 就地修改传入的 dep。node_modules 内无此包时 resolved 留空,由后续
|
|
83
|
+
* 元数据刷新阶段补齐。
|
|
84
|
+
*/
|
|
85
|
+
function resolveLocalDependency(name, dep, ctx) {
|
|
86
|
+
try {
|
|
87
|
+
const meta = loadManifest(name);
|
|
88
|
+
dep.resolved = meta.version;
|
|
89
|
+
dep.workspace = meta.$workspace;
|
|
90
|
+
if (meta.$workspace) delete dep.fetching;
|
|
91
|
+
} catch {}
|
|
92
|
+
if (!dep.workspace && !valid(dep.request)) {
|
|
93
|
+
dep.invalid = true;
|
|
94
|
+
delete dep.fetching;
|
|
95
|
+
}
|
|
96
|
+
const { previous } = ctx;
|
|
97
|
+
if (previous && previous.request === dep.request && previous.resolved === dep.resolved) {
|
|
98
|
+
if (previous.latest) {
|
|
99
|
+
dep.latest = previous.latest;
|
|
100
|
+
delete dep.fetching;
|
|
101
|
+
}
|
|
102
|
+
if (previous.error === "not-found") {
|
|
103
|
+
dep.error = "not-found";
|
|
104
|
+
delete dep.fetching;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/node/dependencies/service.ts
|
|
110
|
+
/**
|
|
111
|
+
* 依赖管理数据服务(`dependencies` 通道)。
|
|
112
|
+
*
|
|
113
|
+
* 单向数据流的 node 侧源头:get() 同步构建本地快照(纯磁盘读取)先行
|
|
114
|
+
* 推送(条目带 fetching 标记),随后在后台并发拉取 registry 元数据填充
|
|
115
|
+
* latest / error,完成后触发通道刷新二拍推送——前端首屏因此有明确的
|
|
116
|
+
* 「加载中」态,不会把未拉取完的条目误显示为错误。
|
|
117
|
+
*
|
|
118
|
+
* node 侧并发纪律(对标参照实现):
|
|
119
|
+
* - 单飞去重:元数据刷新任务同一时刻至多一个,并发调用复用同一任务;
|
|
120
|
+
* - 循环重扫:刷新循环每轮从快照里重新收集 fetching 条目,期间新的
|
|
121
|
+
* get()(安装完成、客户端接入)带来的新条目自动被后续轮次接管,
|
|
122
|
+
* 不会因单飞复用旧任务而漏拉;
|
|
123
|
+
* - 过期不覆盖:拉取完成后若快照代次已更新,跳过通道刷新(新循环
|
|
124
|
+
* 完成后自会推送)。
|
|
125
|
+
*/
|
|
126
|
+
/** registry 元数据并发拉取上限 */
|
|
127
|
+
const CONCURRENCY = 4;
|
|
128
|
+
var DependencyService = class extends DataService {
|
|
129
|
+
static inject = ["console", "installer"];
|
|
130
|
+
/** 快照代次:每次 get() 自增,用于判定后台刷新结果是否已过期 */
|
|
131
|
+
serial = 0;
|
|
132
|
+
/** 最近一轮快照(新快照构建时复用 latest 与 404 负缓存) */
|
|
133
|
+
snapshot = {};
|
|
13
134
|
constructor(ctx) {
|
|
14
135
|
super(ctx, "dependencies", { authority: 4 });
|
|
15
136
|
}
|
|
16
137
|
async get() {
|
|
17
|
-
|
|
138
|
+
this.serial++;
|
|
139
|
+
const snapshot = collectDependencyRequests(loadManifest(this.ctx.baseDir).dependencies);
|
|
140
|
+
for (const [name, dep] of Object.entries(snapshot)) resolveLocalDependency(name, dep, { previous: this.snapshot[name] });
|
|
141
|
+
this.snapshot = snapshot;
|
|
142
|
+
this.ensureMetadata();
|
|
143
|
+
return snapshot;
|
|
144
|
+
}
|
|
145
|
+
ensureMetadata() {
|
|
146
|
+
if (this.task) return;
|
|
147
|
+
this.task = this.refreshMetadata().finally(() => {
|
|
148
|
+
this.task = void 0;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* 元数据刷新循环:拉完本轮全部 fetching 条目后,若快照代次未变则
|
|
153
|
+
* 触发通道刷新(二拍推送);代次已变(期间有新的 get())则重扫
|
|
154
|
+
* fetching 条目继续,直到无新增且代次一致。
|
|
155
|
+
*/
|
|
156
|
+
async refreshMetadata() {
|
|
157
|
+
for (;;) {
|
|
158
|
+
const serial = this.serial;
|
|
159
|
+
const targets = Object.entries(this.snapshot).filter(([, dep]) => dep.fetching).map(([name]) => name);
|
|
160
|
+
if (!targets.length) return;
|
|
161
|
+
await mapLimit(targets, CONCURRENCY, async (name) => {
|
|
162
|
+
await this.resolveMetadata(name);
|
|
163
|
+
});
|
|
164
|
+
if (serial !== this.serial) continue;
|
|
165
|
+
this.ctx.get("console")?.refresh("dependencies");
|
|
166
|
+
this.ctx.get("console")?.refresh("registry");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** 单个条目的元数据解析:拉取版本表并填充 latest / error。 */
|
|
171
|
+
async resolveMetadata(name) {
|
|
172
|
+
const dep = this.snapshot[name];
|
|
173
|
+
if (!dep?.fetching) return;
|
|
174
|
+
const installer = this.ctx.installer;
|
|
175
|
+
const versions = await installer.getPackage(name);
|
|
176
|
+
delete dep.fetching;
|
|
177
|
+
if (!Object.keys(versions).length) {
|
|
178
|
+
dep.error = installer.pkgErrors[name]?.notFound ? "not-found" : "network";
|
|
179
|
+
delete dep.latest;
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
const [latest] = Object.keys(versions);
|
|
183
|
+
if (latest !== void 0) dep.latest = latest;
|
|
18
184
|
}
|
|
19
185
|
};
|
|
186
|
+
//#endregion
|
|
187
|
+
//#region src/node/deps.ts
|
|
20
188
|
var RegistryProvider = class extends DataService {
|
|
21
189
|
constructor(ctx) {
|
|
22
190
|
super(ctx, "registry", { authority: 4 });
|
|
@@ -158,57 +326,6 @@ function findMissingDeps(root, deps) {
|
|
|
158
326
|
return problems;
|
|
159
327
|
}
|
|
160
328
|
//#endregion
|
|
161
|
-
//#region src/node/installer/manifest.ts
|
|
162
|
-
/**
|
|
163
|
-
* 项目根 package.json(安装清单)的读写与护栏判定。
|
|
164
|
-
*
|
|
165
|
-
* 只做纯 fs 的清单操作,与 registry 的交互(版本探测、http 缓存)无关,
|
|
166
|
-
* 故独立于 installer 服务;依赖链接的探测属安装完整性校验,见
|
|
167
|
-
* ./integrity.ts。
|
|
168
|
-
*/
|
|
169
|
-
/**
|
|
170
|
-
* 判断依赖声明是否受护栏保护、不可被安装清单覆盖或删除。两类:
|
|
171
|
-
* - `workspace:` 声明是本仓库(monorepo)对上游名的归属(如 koishi
|
|
172
|
-
* 裸名 shim,见 packages/shim/koishi);
|
|
173
|
-
* - `npm:@koishi-ce/...` alias 是下游脚手架生成项目对上游名的归属
|
|
174
|
-
* (如 "koishi": "npm:@koishi-ce/koishi-shim@^4.18.11",见
|
|
175
|
-
* packages/shim/koishi-shim)。
|
|
176
|
-
* 两者被覆盖或删除都会让 peer 解析失去归属,重新拉下 npm 官方包形成
|
|
177
|
-
* 第二份框架副本。
|
|
178
|
-
*/
|
|
179
|
-
function isGuardedRequest(request) {
|
|
180
|
-
return request?.startsWith("workspace:") === true || request?.startsWith("npm:@koishi-ce") === true;
|
|
181
|
-
}
|
|
182
|
-
function loadManifest(name) {
|
|
183
|
-
const filename = resolvePackageJson(name);
|
|
184
|
-
const meta = JSON.parse(readFileSync(filename, "utf8"));
|
|
185
|
-
meta.dependencies ||= {};
|
|
186
|
-
defineProperty(meta, "$workspace", !filename.includes("node_modules"));
|
|
187
|
-
return meta;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* 把依赖增删写回项目根 package.json,返回写回后的清单。
|
|
191
|
-
*
|
|
192
|
-
* 现读现写:调用方持有的清单原为构造期的启动快照,运行期间根
|
|
193
|
-
* package.json 可能已被外部更新,基于快照整体重写会抹掉变更,故此处
|
|
194
|
-
* 重新读盘。受护栏保护的声明(见 isGuardedRequest)既不覆盖也不删除。
|
|
195
|
-
*
|
|
196
|
-
* @param cwd 项目根目录
|
|
197
|
-
* @param deps 依赖增删清单(值为 null 表示卸载该依赖)
|
|
198
|
-
*/
|
|
199
|
-
async function writeManifest(cwd, deps) {
|
|
200
|
-
const filename = resolve(cwd, "package.json");
|
|
201
|
-
const manifest = JSON.parse(readFileSync(filename, "utf8"));
|
|
202
|
-
manifest.dependencies ||= {};
|
|
203
|
-
for (const key in deps) if (deps[key]) {
|
|
204
|
-
if (isGuardedRequest(manifest.dependencies[key])) continue;
|
|
205
|
-
manifest.dependencies[key] = deps[key];
|
|
206
|
-
} else if (!isGuardedRequest(manifest.dependencies[key])) delete manifest.dependencies[key];
|
|
207
|
-
manifest.dependencies = Object.fromEntries(Object.entries(manifest.dependencies).sort((a, b) => a[0].localeCompare(b[0])));
|
|
208
|
-
await Bun.write(filename, `${JSON.stringify(manifest, null, " ")}\n`);
|
|
209
|
-
return manifest;
|
|
210
|
-
}
|
|
211
|
-
//#endregion
|
|
212
329
|
//#region src/node/installer/versions.ts
|
|
213
330
|
/**
|
|
214
331
|
* 远端包版本探测与归一化。
|
|
@@ -247,6 +364,8 @@ var Installer = class extends Service {
|
|
|
247
364
|
fullCache = {};
|
|
248
365
|
tempCache = {};
|
|
249
366
|
pkgTasks = {};
|
|
367
|
+
/** 各包最近一次拉取失败的归类(404 与否);依赖页的 error 徽标消费 */
|
|
368
|
+
pkgErrors = {};
|
|
250
369
|
manifest;
|
|
251
370
|
flushData;
|
|
252
371
|
config;
|
|
@@ -292,10 +411,14 @@ var Installer = class extends Service {
|
|
|
292
411
|
async _getPackage(name) {
|
|
293
412
|
try {
|
|
294
413
|
const versions = await fetchVersions(this.http, name);
|
|
414
|
+
delete this.pkgErrors[name];
|
|
295
415
|
this.fullCache[name] = this.tempCache[name] = versions;
|
|
296
416
|
this.flushData();
|
|
297
417
|
return versions;
|
|
298
418
|
} catch (error) {
|
|
419
|
+
const notFound = this.http.isError(error) && error.response?.status === 404;
|
|
420
|
+
this.pkgErrors[name] = { notFound };
|
|
421
|
+
if (!notFound) delete this.pkgTasks[name];
|
|
299
422
|
logger$2.warn(error);
|
|
300
423
|
return {};
|
|
301
424
|
}
|
|
@@ -336,12 +459,18 @@ var Installer = class extends Service {
|
|
|
336
459
|
}
|
|
337
460
|
refresh(refresh = false) {
|
|
338
461
|
this.pkgTasks = {};
|
|
462
|
+
this.pkgErrors = {};
|
|
339
463
|
this.fullCache = {};
|
|
340
464
|
this.tempCache = {};
|
|
341
465
|
this.depTask = this._getDeps();
|
|
342
466
|
if (!refresh) return;
|
|
343
467
|
this.refreshData();
|
|
344
468
|
}
|
|
469
|
+
/** 轻量重建:重读宿主清单并重置依赖汇总任务(registry 缓存不动)。 */
|
|
470
|
+
reload() {
|
|
471
|
+
this.manifest = loadManifest(this.cwd);
|
|
472
|
+
this.depTask = void 0;
|
|
473
|
+
}
|
|
345
474
|
async exec(args) {
|
|
346
475
|
args.unshift("install");
|
|
347
476
|
return runBun(args, this.cwd);
|
|
@@ -367,6 +496,7 @@ var Installer = class extends Service {
|
|
|
367
496
|
}
|
|
368
497
|
async install(deps, forced) {
|
|
369
498
|
const localDeps = this._getLocalDeps(deps);
|
|
499
|
+
const backup = await backupManifest(this.cwd);
|
|
370
500
|
await this.override(deps);
|
|
371
501
|
let shouldInstall = forced === true;
|
|
372
502
|
for (const name in deps) {
|
|
@@ -378,7 +508,11 @@ var Installer = class extends Service {
|
|
|
378
508
|
}
|
|
379
509
|
if (shouldInstall) {
|
|
380
510
|
const code = await this._install();
|
|
381
|
-
if (code)
|
|
511
|
+
if (code) {
|
|
512
|
+
await restoreManifest(this.cwd, backup);
|
|
513
|
+
this.reload();
|
|
514
|
+
return code;
|
|
515
|
+
}
|
|
382
516
|
const missing = findMissingDeps(this.cwd, deps);
|
|
383
517
|
if (missing.length) {
|
|
384
518
|
logger$2.warn(`检测到增量安装未建立部分依赖链接(isolated 布局已知缺陷),正在补装: ${missing.join("; ")}`);
|
|
@@ -677,7 +811,7 @@ function apply(ctx, config) {
|
|
|
677
811
|
});
|
|
678
812
|
});
|
|
679
813
|
ctx.inject(["console", "installer"], (ctx) => {
|
|
680
|
-
ctx.plugin(
|
|
814
|
+
ctx.plugin(DependencyService);
|
|
681
815
|
ctx.plugin(RegistryProvider);
|
|
682
816
|
ctx.plugin(MarketProvider$1, config.search);
|
|
683
817
|
ctx.console.addEntry({
|
|
@@ -698,4 +832,4 @@ function apply(ctx, config) {
|
|
|
698
832
|
});
|
|
699
833
|
}
|
|
700
834
|
//#endregion
|
|
701
|
-
export { Config,
|
|
835
|
+
export { Config, DependencyService, Installer, MarketProvider, RegistryProvider, apply, inject, name, usage };
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koishi-ce/plugin-market",
|
|
3
3
|
"description": "Manage your bots and plugins with console",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.mjs",
|
|
7
|
-
"
|
|
7
|
+
"types": "lib/index.d.ts",
|
|
8
8
|
"files": [
|
|
9
9
|
"lib",
|
|
10
10
|
"dist",
|
|
@@ -60,10 +60,10 @@
|
|
|
60
60
|
}
|
|
61
61
|
},
|
|
62
62
|
"devDependencies": {
|
|
63
|
-
"@koishi-ce/plugin-database-memory": "^1.1.
|
|
64
|
-
"@koishi-ce/client": "^1.3.
|
|
65
|
-
"@koishi-ce/loader": "^1.1.
|
|
66
|
-
"@koishi-ce/plugin-config": "^1.1.
|
|
63
|
+
"@koishi-ce/plugin-database-memory": "^1.1.1",
|
|
64
|
+
"@koishi-ce/client": "^1.3.1",
|
|
65
|
+
"@koishi-ce/loader": "^1.1.1",
|
|
66
|
+
"@koishi-ce/plugin-config": "^1.1.5",
|
|
67
67
|
"@koishi-ce/components": "^1.0.4",
|
|
68
68
|
"@types/semver": "^7.5.8",
|
|
69
69
|
"@vueuse/core": "^14.4.0",
|