llm-simple-router 0.9.31 → 0.9.33
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/admin/upgrade.js +23 -10
- package/dist/config/model-context.js +21 -9
- package/dist/db/index.js +1 -0
- package/dist/db/mappings.js +6 -15
- package/dist/db/providers.d.ts +1 -0
- package/dist/db/providers.js +11 -26
- package/dist/db/router-keys.js +4 -5
- package/dist/proxy/handler/openai.js +5 -4
- package/dist/proxy/routing/mapping-resolver.js +7 -16
- package/frontend-dist/assets/{CardContent-Rx3Yzr25.js → CardContent-CPeHI_vO.js} +1 -1
- package/frontend-dist/assets/{CardTitle-BfXABzCk.js → CardTitle-DiF3FpGs.js} +1 -1
- package/frontend-dist/assets/{Checkbox-CaCKbLQP.js → Checkbox-BpQYgA_C.js} +1 -1
- package/frontend-dist/assets/{CollapsibleContent-C3p4dMa-.js → CollapsibleContent-CUb_IZ--.js} +1 -1
- package/frontend-dist/assets/{CollapsibleTrigger-DRGRANMT.js → CollapsibleTrigger-DSh5Vnmj.js} +1 -1
- package/frontend-dist/assets/{Dashboard-DKeQ9jnE.js → Dashboard-DMaq-T6I.js} +1 -1
- package/frontend-dist/assets/{Input-Zqewz_Ci.js → Input-C9E7es5X.js} +1 -1
- package/frontend-dist/assets/{Label-B1wEVeX4.js → Label-kvNNc1bh.js} +1 -1
- package/frontend-dist/assets/{Login-BWDT9nph.js → Login-CC1aMDOU.js} +1 -1
- package/frontend-dist/assets/{Logs-hyd2jEMr.js → Logs-zr32VuD0.js} +1 -1
- package/frontend-dist/assets/{MappingEntryEditor-By30pZoC.js → MappingEntryEditor-D6ABslWN.js} +1 -1
- package/frontend-dist/assets/{ModelCard-C3DD_FZd.js → ModelCard-Dn_8Lnr-.js} +1 -1
- package/frontend-dist/assets/{ModelMappings-CrWlSNu8.js → ModelMappings-BD7Xd9u_.js} +1 -1
- package/frontend-dist/assets/{Monitor-BN7oLW1v.js → Monitor-CnQrBEqa.js} +1 -1
- package/frontend-dist/assets/{Providers-Drx7U5Sq.js → Providers-CK4mOZS5.js} +1 -1
- package/frontend-dist/assets/{ProxyEnhancement-CYVFvqyn.js → ProxyEnhancement-DQIrpH8f.js} +1 -1
- package/frontend-dist/assets/{QuickSetup-Oom1ygGi.js → QuickSetup-Cp1nlz0G.js} +1 -1
- package/frontend-dist/assets/{RetryRules-CpL1bYTq.js → RetryRules-Botm2DuB.js} +1 -1
- package/frontend-dist/assets/{RouterKeys-_AlXAmum.js → RouterKeys-C9ZluPMi.js} +1 -1
- package/frontend-dist/assets/{RovingFocusItem-BcFr0scT.js → RovingFocusItem-B4cr2rFZ.js} +1 -1
- package/frontend-dist/assets/{Schedules-DU8r-48b.js → Schedules-C3JE7gox.js} +1 -1
- package/frontend-dist/assets/{Settings-CqsVr0kd.js → Settings-Dd9LXNyo.js} +1 -1
- package/frontend-dist/assets/{Setup-fotCrfUW.js → Setup-DXTFJRxq.js} +1 -1
- package/frontend-dist/assets/{Switch-BQas2Rql.js → Switch-CkJ3KppU.js} +1 -1
- package/frontend-dist/assets/{TooltipTrigger-BPsVa_Tw.js → TooltipTrigger-DtY0_zHb.js} +1 -1
- package/frontend-dist/assets/{TransformRulesForm-O68V-z_P.js → TransformRulesForm-DpFk5xx0.js} +1 -1
- package/frontend-dist/assets/{UnifiedRequestDialog-hVtwPhdB.js → UnifiedRequestDialog-Cpn9RNu1.js} +1 -1
- package/frontend-dist/assets/{VisuallyHiddenInput-5jJ6xPkS.js → VisuallyHiddenInput-DvHAsFOO.js} +1 -1
- package/frontend-dist/assets/{button-CRqhqXwT.js → button-CjKaq4D4.js} +2 -2
- package/frontend-dist/assets/{copy-CBD-G6GC.js → copy-BYleSlPg.js} +1 -1
- package/frontend-dist/assets/{dialog-DKAgYLQJ.js → dialog-DlHPBQX7.js} +1 -1
- package/frontend-dist/assets/{index-CwvbWlRW.js → index-C19mbJF3.js} +2 -2
- package/frontend-dist/assets/sidebar-3c8D7l60.js +1 -0
- package/frontend-dist/assets/sidebar-vj4kQ6t1.js +1 -0
- package/frontend-dist/assets/{trash-2-C88b94t5.js → trash-2-C6EEjS9z.js} +1 -1
- package/frontend-dist/assets/{useClipboard-BJc6Gpft.js → useClipboard-C_hBlc9t.js} +1 -1
- package/frontend-dist/assets/{useLogRetention-ed_dDakq.js → useLogRetention-DZGdtwFB.js} +1 -1
- package/frontend-dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend-dist/assets/sidebar-BLkzG956.js +0 -1
- package/frontend-dist/assets/sidebar-Bw1Xt0-q.js +0 -1
package/dist/admin/upgrade.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { getConfigSyncSource, setConfigSyncSource } from '../db/settings.js';
|
|
2
|
-
import { detectDeployment, hasProcessManager, getRestartMethod } from '../upgrade/deployment.js';
|
|
2
|
+
import { detectDeployment, hasProcessManager, resolveRestartBinPath, getRestartMethod } from '../upgrade/deployment.js';
|
|
3
3
|
import { createUpgradeChecker, fetchJson } from '../upgrade/checker.js';
|
|
4
4
|
import { reloadConfig } from '../config/recommended.js';
|
|
5
|
-
import { execSync } from 'node:child_process';
|
|
5
|
+
import { execSync, spawn } from 'node:child_process';
|
|
6
6
|
import fs from 'node:fs';
|
|
7
7
|
import path from 'node:path';
|
|
8
8
|
import { HTTP_BAD_REQUEST, HTTP_INTERNAL_ERROR } from '../core/constants.js';
|
|
@@ -11,8 +11,22 @@ const GITHUB_CONFIG_BASE = 'https://raw.githubusercontent.com/zhushanwen321/llm-
|
|
|
11
11
|
const GITEE_CONFIG_BASE = 'https://gitee.com/zzzzswszzzz/llm-simple-router/raw/main/router/config';
|
|
12
12
|
const CHECK_INTERVAL_MS = 60 * 60 * 1000; // eslint-disable-line no-magic-numbers
|
|
13
13
|
const JSON_INDENT = 2;
|
|
14
|
-
const RESTART_FORCE_EXIT_MS =
|
|
14
|
+
const RESTART_FORCE_EXIT_MS = 5_000;
|
|
15
15
|
const RESTART_RESPONSE_FLUSH_MS = 300;
|
|
16
|
+
function spawnDetached(req) {
|
|
17
|
+
const binPath = resolveRestartBinPath();
|
|
18
|
+
const args = process.argv.slice(2); // eslint-disable-line no-magic-numbers
|
|
19
|
+
req.log.info({ binPath, args }, 'Spawning new process');
|
|
20
|
+
const child = spawn(binPath, args, {
|
|
21
|
+
detached: true,
|
|
22
|
+
stdio: 'ignore',
|
|
23
|
+
env: { ...process.env },
|
|
24
|
+
});
|
|
25
|
+
child.on('error', (err) => {
|
|
26
|
+
req.log.error({ err, binPath }, 'Failed to spawn new process');
|
|
27
|
+
});
|
|
28
|
+
child.unref();
|
|
29
|
+
}
|
|
16
30
|
// 模块级单例:checker、configDir 和定时器
|
|
17
31
|
let checker = null;
|
|
18
32
|
let configDir = '';
|
|
@@ -86,13 +100,6 @@ export const adminUpgradeRoutes = (app, options, done) => {
|
|
|
86
100
|
app.post('/admin/api/upgrade/restart', async (req, reply) => {
|
|
87
101
|
const managed = hasProcessManager();
|
|
88
102
|
const method = getRestartMethod();
|
|
89
|
-
if (!managed) {
|
|
90
|
-
// 无进程管理器(npx / 手动 node)时无法安全自动重启:
|
|
91
|
-
// 1. spawn 路径不可靠(npx 不注册全局 bin)
|
|
92
|
-
// 2. 新旧进程端口竞态(EADDRINUSE)
|
|
93
|
-
// 3. 原始启动参数无法复现
|
|
94
|
-
return reply.code(HTTP_BAD_REQUEST).send(apiError(API_CODE.BAD_REQUEST, 'No process manager detected (PM2/systemd/Docker). Please restart manually.'));
|
|
95
|
-
}
|
|
96
103
|
// 先回复客户端,再执行重启(否则客户端收不到响应)
|
|
97
104
|
reply.send({ ok: true, method });
|
|
98
105
|
// 给响应发送窗口
|
|
@@ -102,12 +109,18 @@ export const adminUpgradeRoutes = (app, options, done) => {
|
|
|
102
109
|
// 强制退出兜底:即使 closeFn 卡住(如活跃代理 SSE 流),也能确保进程退出。
|
|
103
110
|
const forceExitTimer = setTimeout(() => {
|
|
104
111
|
req.log.warn('Graceful shutdown timed out during restart, forcing exit');
|
|
112
|
+
// 超时强制退出前仍尝试 spawn(无进程管理器时)
|
|
113
|
+
if (!managed)
|
|
114
|
+
spawnDetached(req);
|
|
105
115
|
process.exit(0);
|
|
106
116
|
}, RESTART_FORCE_EXIT_MS);
|
|
107
117
|
forceExitTimer.unref();
|
|
108
118
|
// 尝试优雅关闭(closeFn 内部有 2s 优雅等待 + closeAllConnections 兜底)
|
|
109
119
|
await options.closeFn();
|
|
110
120
|
clearTimeout(forceExitTimer);
|
|
121
|
+
// 无进程管理器时,先 closeFn 释放端口,再 spawn 新进程,避免 EADDRINUSE 竞态
|
|
122
|
+
if (!managed)
|
|
123
|
+
spawnDetached(req);
|
|
111
124
|
req.log.info('Exiting current process');
|
|
112
125
|
process.exit(0);
|
|
113
126
|
}
|
|
@@ -88,6 +88,22 @@ export function lookupContextWindow(modelName) {
|
|
|
88
88
|
export function normalizePatchName(name) {
|
|
89
89
|
return name.replace(/-/g, "_");
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* 解析 providers.models 的 JSON 文本。
|
|
93
|
+
*
|
|
94
|
+
* 这是解析 providers.models 字段的唯一合法入口。
|
|
95
|
+
* 禁止直接 JSON.parse(provider.models) —— 数据格式已从 string[] 演进为 ModelEntry[],
|
|
96
|
+
* 直接 JSON.parse 会得到对象数组而非字符串数组,导致运行时错误。
|
|
97
|
+
*
|
|
98
|
+
* ESLint 规则 taste/no-raw-json-parse-models 会强制执行此约束。
|
|
99
|
+
*/
|
|
100
|
+
/** 旧 patch ID 到新 patch ID 的迁移映射 */
|
|
101
|
+
const PATCH_ID_MIGRATION = {
|
|
102
|
+
thinking_param: "thinking_consistency",
|
|
103
|
+
thinking_blocks: "thinking_consistency",
|
|
104
|
+
non_ds_tools: "thinking_consistency",
|
|
105
|
+
cache_control: "thinking_consistency",
|
|
106
|
+
};
|
|
91
107
|
export function parseModels(raw) {
|
|
92
108
|
if (!raw)
|
|
93
109
|
return [];
|
|
@@ -100,20 +116,16 @@ export function parseModels(raw) {
|
|
|
100
116
|
return item ? { name: item, patches: [] } : null;
|
|
101
117
|
}
|
|
102
118
|
const obj = item;
|
|
103
|
-
if (!obj
|
|
119
|
+
if (!obj)
|
|
120
|
+
return null;
|
|
121
|
+
const modelName = obj.name ?? obj.id;
|
|
122
|
+
if (!modelName)
|
|
104
123
|
return null;
|
|
105
|
-
/** 旧 patch ID 到新 patch ID 的运行时迁移映射 */
|
|
106
|
-
const PATCH_ID_MIGRATION = {
|
|
107
|
-
thinking_param: "thinking_consistency",
|
|
108
|
-
thinking_blocks: "thinking_consistency",
|
|
109
|
-
non_ds_tools: "thinking_consistency",
|
|
110
|
-
cache_control: "thinking_consistency",
|
|
111
|
-
};
|
|
112
124
|
const rawPatches = (obj.patches ?? []).map(normalizePatchName);
|
|
113
125
|
const migrated = rawPatches.map(p => PATCH_ID_MIGRATION[p] ?? p);
|
|
114
126
|
const patches = [...new Set(migrated)];
|
|
115
127
|
const result = {
|
|
116
|
-
name:
|
|
128
|
+
name: modelName,
|
|
117
129
|
patches,
|
|
118
130
|
};
|
|
119
131
|
if (obj.stream_timeout_ms != null)
|
package/dist/db/index.js
CHANGED
|
@@ -105,6 +105,7 @@ function runApplicationMigrations(db) {
|
|
|
105
105
|
db.transaction(() => {
|
|
106
106
|
for (const p of providers) {
|
|
107
107
|
try {
|
|
108
|
+
// eslint-disable-next-line taste/no-raw-json-parse-models -- 迁移代码需要操作原始 JSON 结构,parseModels() 会过滤非标准字段
|
|
108
109
|
const raw = JSON.parse(p.models);
|
|
109
110
|
if (!Array.isArray(raw) || raw.length === 0)
|
|
110
111
|
continue;
|
package/dist/db/mappings.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import { buildUpdateQuery, deleteById } from "./helpers.js";
|
|
3
|
+
import { parseModels } from "../config/model-context.js";
|
|
3
4
|
const GROUP_FIELDS = new Set(["client_model", "strategy", "rule", "is_active"]);
|
|
4
5
|
// --- MappingGroups CRUD ---
|
|
5
6
|
export function getMappingGroup(db, clientModel) {
|
|
@@ -35,14 +36,9 @@ export function getActiveProviderModels(db) {
|
|
|
35
36
|
const providers = db.prepare("SELECT name, models, is_active FROM providers WHERE is_active = 1").all();
|
|
36
37
|
const results = [];
|
|
37
38
|
for (const p of providers) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
results.push({ provider_name: p.name, backend_model: m });
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
catch {
|
|
45
|
-
continue;
|
|
39
|
+
const modelEntries = parseModels(p.models);
|
|
40
|
+
for (const m of modelEntries) {
|
|
41
|
+
results.push({ provider_name: p.name, backend_model: m.name });
|
|
46
42
|
}
|
|
47
43
|
}
|
|
48
44
|
return results;
|
|
@@ -83,14 +79,9 @@ export function resolveByProviderModel(db, providerName, backendModel) {
|
|
|
83
79
|
const providerRow = db.prepare("SELECT id, models FROM providers WHERE name = ? AND is_active = 1").get(providerName);
|
|
84
80
|
if (!providerRow)
|
|
85
81
|
return null;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (!models.includes(backendModel))
|
|
89
|
-
return null;
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
82
|
+
const modelEntries = parseModels(providerRow.models);
|
|
83
|
+
if (!modelEntries.some(m => m.name === backendModel))
|
|
92
84
|
return null;
|
|
93
|
-
}
|
|
94
85
|
// 尝试从 mapping_groups 找到包含此 provider+backend_model 的 client_model
|
|
95
86
|
const groups = db.prepare("SELECT client_model, rule FROM mapping_groups").all();
|
|
96
87
|
for (const g of groups) {
|
package/dist/db/providers.d.ts
CHANGED
package/dist/db/providers.js
CHANGED
|
@@ -1,35 +1,20 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import { buildUpdateQuery, deleteById } from "./helpers.js";
|
|
3
|
+
import { parseModels } from "../config/model-context.js";
|
|
3
4
|
/** 默认流式超时 10 分钟 */
|
|
4
5
|
export const DEFAULT_STREAM_TIMEOUT_MS = 600_000;
|
|
5
6
|
/** 从 provider 的 models JSON 中查找指定模型的超时值 */
|
|
6
7
|
export function getModelStreamTimeout(provider, backendModel) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const obj = m;
|
|
18
|
-
if (!obj || typeof obj !== "object")
|
|
19
|
-
continue;
|
|
20
|
-
const modelId = (obj.name ?? obj.id);
|
|
21
|
-
if (modelId === backendModel) {
|
|
22
|
-
const timeout = obj.stream_timeout_ms;
|
|
23
|
-
// stream_timeout_ms: 0 表示禁用超时,返回 Infinity;
|
|
24
|
-
// undefined/null/未设置 表示使用默认值
|
|
25
|
-
if (timeout === 0)
|
|
26
|
-
return Number.POSITIVE_INFINITY;
|
|
27
|
-
return timeout ?? DEFAULT_STREAM_TIMEOUT_MS;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
catch { /* ignore parse errors — models field may be empty or invalid */ } // eslint-disable-line taste/no-silent-catch
|
|
32
|
-
return DEFAULT_STREAM_TIMEOUT_MS;
|
|
8
|
+
const entries = parseModels(provider.models);
|
|
9
|
+
const entry = entries.find(m => m.name === backendModel);
|
|
10
|
+
if (!entry)
|
|
11
|
+
return DEFAULT_STREAM_TIMEOUT_MS;
|
|
12
|
+
const timeout = entry.stream_timeout_ms;
|
|
13
|
+
// stream_timeout_ms: 0 表示禁用超时,返回 Infinity;
|
|
14
|
+
// undefined/null/未设置 表示使用默认值
|
|
15
|
+
if (timeout === 0)
|
|
16
|
+
return Number.POSITIVE_INFINITY;
|
|
17
|
+
return timeout ?? DEFAULT_STREAM_TIMEOUT_MS;
|
|
33
18
|
}
|
|
34
19
|
export const PROVIDER_CONCURRENCY_DEFAULTS = {
|
|
35
20
|
max_concurrency: 0,
|
package/dist/db/router-keys.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import { buildUpdateQuery, deleteById } from "./helpers.js";
|
|
3
|
+
import { parseModels } from "../config/model-context.js";
|
|
3
4
|
export function getRouterKeyByHash(db, hash) {
|
|
4
5
|
return db.prepare("SELECT id, name, allowed_models FROM router_keys WHERE key_hash = ? AND is_active = 1").get(hash);
|
|
5
6
|
}
|
|
@@ -27,11 +28,9 @@ export function getAvailableModels(db) {
|
|
|
27
28
|
const rows = db.prepare("SELECT models FROM providers WHERE is_active = 1").all();
|
|
28
29
|
const set = new Set();
|
|
29
30
|
for (const r of rows) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
catch {
|
|
34
|
-
continue;
|
|
31
|
+
const entries = parseModels(r.models);
|
|
32
|
+
for (const m of entries) {
|
|
33
|
+
set.add(m.name);
|
|
35
34
|
}
|
|
36
35
|
}
|
|
37
36
|
return [...set].sort();
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { randomUUID } from "crypto";
|
|
2
2
|
import fp from "fastify-plugin";
|
|
3
3
|
import { getAllProviders, insertRequestLog } from "../../db/index.js";
|
|
4
|
+
import { parseModels } from "../../config/model-context.js";
|
|
4
5
|
import { createErrorFormatter } from "../proxy-core.js";
|
|
5
6
|
import { handleProxyRequest } from "./proxy-handler.js";
|
|
6
7
|
import { createOrchestrator } from "../orchestration/orchestrator.js";
|
|
@@ -61,10 +62,10 @@ const openaiProxyRaw = (app, opts, done) => {
|
|
|
61
62
|
const modelMeta = new Map();
|
|
62
63
|
for (const p of allProviders) {
|
|
63
64
|
try {
|
|
64
|
-
const
|
|
65
|
-
for (const m of
|
|
66
|
-
if (!modelMeta.has(m))
|
|
67
|
-
modelMeta.set(m, { providerName: p.name, createdAt: p.created_at });
|
|
65
|
+
const modelEntries = parseModels(p.models || '[]');
|
|
66
|
+
for (const m of modelEntries) {
|
|
67
|
+
if (!modelMeta.has(m.name))
|
|
68
|
+
modelMeta.set(m.name, { providerName: p.name, createdAt: p.created_at });
|
|
68
69
|
}
|
|
69
70
|
}
|
|
70
71
|
catch {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getMappingGroup, getActiveProviderByName, getActiveProvidersWithModels, getActiveSchedulesForGroup } from "../../db/index.js";
|
|
2
|
+
import { parseModels } from "../../config/model-context.js";
|
|
2
3
|
// ---------- Type guards ----------
|
|
3
4
|
function isTarget(value) {
|
|
4
5
|
return (typeof value === "object" &&
|
|
@@ -114,14 +115,9 @@ export function resolveMapping(db, clientModel, context) {
|
|
|
114
115
|
const backendModel = slashMatch[2];
|
|
115
116
|
const provider = getActiveProviderByName(db, providerName);
|
|
116
117
|
if (provider) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return { target: { backend_model: backendModel, provider_id: provider.id }, targetCount: 1 };
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
catch {
|
|
124
|
-
return null;
|
|
118
|
+
const modelEntries = parseModels(provider.models);
|
|
119
|
+
if (modelEntries.some(m => m.name === backendModel)) {
|
|
120
|
+
return { target: { backend_model: backendModel, provider_id: provider.id }, targetCount: 1 };
|
|
125
121
|
}
|
|
126
122
|
}
|
|
127
123
|
return null;
|
|
@@ -132,14 +128,9 @@ export function resolveMapping(db, clientModel, context) {
|
|
|
132
128
|
// fallback: 直接查 provider 的 models 字段
|
|
133
129
|
const providers = getActiveProvidersWithModels(db);
|
|
134
130
|
for (const p of providers) {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return { target: { backend_model: clientModel, provider_id: p.id }, targetCount: 1 };
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
continue;
|
|
131
|
+
const modelEntries = parseModels(p.models);
|
|
132
|
+
if (modelEntries.some(m => m.name === clientModel)) {
|
|
133
|
+
return { target: { backend_model: clientModel, provider_id: p.id }, targetCount: 1 };
|
|
143
134
|
}
|
|
144
135
|
}
|
|
145
136
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-
|
|
1
|
+
import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-CjKaq4D4.js";var s=[`data-size`],c=e({__name:`Card`,props:{class:{type:[Boolean,null,String,Object,Array]},size:{default:`default`}},setup(e){let c=e;return(l,u)=>(r(),n(`div`,{"data-slot":`card`,"data-size":e.size,class:t(o(a)(`ring-foreground/10 bg-card text-card-foreground gap-4 overflow-hidden rounded-lg py-4 text-sm ring-1 has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0 data-[size=sm]:gap-3 data-[size=sm]:py-3 data-[size=sm]:has-data-[slot=card-footer]:pb-0 *:[img:first-child]:rounded-t-lg *:[img:last-child]:rounded-b-lg group/card flex flex-col`,c.class))},[i(l.$slots,`default`)],10,s))}}),l=e({__name:`CardContent`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-content`,class:t(o(a)(`px-4 group-data-[size=sm]/card:px-3`,s.class))},[i(e.$slots,`default`)],2))}});export{c as n,l as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-
|
|
1
|
+
import{$ as e,Vt as t,X as n,dt as r,mt as i,r as a,zt as o}from"./button-CjKaq4D4.js";var s=e({__name:`CardHeader`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-header`,class:t(o(a)(`gap-1 rounded-t-xl px-4 group-data-[size=sm]/card:px-3 [.border-b]:pb-4 group-data-[size=sm]/card:[.border-b]:pb-3 group/card-header @container/card-header grid auto-rows-min items-start has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]`,s.class))},[i(e.$slots,`default`)],2))}}),c=e({__name:`CardTitle`,props:{class:{type:[Boolean,null,String,Object,Array]}},setup(e){let s=e;return(e,c)=>(r(),n(`div`,{"data-slot":`card-title`,class:t(o(a)(`text-base leading-snug font-medium group-data-[size=sm]/card:text-sm cn-font-heading`,s.class))},[i(e.$slots,`default`)],2))}});export{s as n,c as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,H as t,Ht as n,J as r,K as i,Q as a,U as o,Y as s,dt as c,gt as l,i as u,m as d,mt as f,o as p,ot as m,r as h,tt as g,wt as _,x as v,zt as y}from"./button-
|
|
1
|
+
import{$ as e,H as t,Ht as n,J as r,K as i,Q as a,U as o,Y as s,dt as c,gt as l,i as u,m as d,mt as f,o as p,ot as m,r as h,tt as g,wt as _,x as v,zt as y}from"./button-CjKaq4D4.js";import{t as b}from"./VisuallyHiddenInput-DvHAsFOO.js";import{t as x}from"./RovingFocusItem-B4cr2rFZ.js";import{B as S,G as C,H as w,L as T,Y as E,nt as D,q as O}from"./index-C19mbJF3.js";function k(e,t){return C(e)?!1:Array.isArray(e)?e.some(e=>E(e,t)):E(e,t)}var[A,j]=O(`CheckboxGroupRoot`);function M(e){return e===`indeterminate`}function N(e){return M(e)?`indeterminate`:e?`checked`:`unchecked`}var[P,F]=O(`CheckboxRoot`),I=e({inheritAttrs:!1,__name:`CheckboxRoot`,props:{defaultValue:{type:null,required:!1},modelValue:{type:null,required:!1,default:void 0},disabled:{type:Boolean,required:!1},value:{type:null,required:!1,default:`on`},id:{type:String,required:!1},trueValue:{type:null,required:!1,default:()=>!0},falseValue:{type:null,required:!1,default:()=>!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`},name:{type:String,required:!1},required:{type:Boolean,required:!1}},emits:[`update:modelValue`],setup(e,{emit:n}){let a=e,h=n,{forwardRef:g,currentElement:v}=p(),S=A(null),T=d(a,`modelValue`,h,{defaultValue:a.defaultValue??a.falseValue,passive:a.modelValue===void 0}),D=i(()=>S?.disabled.value||a.disabled),O=i(()=>E(T.value,a.trueValue)),j=i(()=>C(S?.modelValue.value)?T.value===`indeterminate`?`indeterminate`:O.value:k(S.modelValue.value,a.value));function P(){if(C(S?.modelValue.value))T.value===`indeterminate`?T.value=a.trueValue:T.value=O.value?a.falseValue:a.trueValue;else{let e=[...S.modelValue.value||[]];if(k(e,a.value)){let t=e.findIndex(e=>E(e,a.value));e.splice(t,1)}else e.push(a.value);S.modelValue.value=e}}let I=w(v),L=i(()=>a.id&&v.value?document.querySelector(`[for="${a.id}"]`)?.innerText:void 0);return F({disabled:D,state:j}),(e,n)=>(c(),r(l(y(S)?.rovingFocus.value?y(x):y(u)),m(e.$attrs,{id:e.id,ref:y(g),role:`checkbox`,"as-child":e.asChild,as:e.as,type:e.as===`button`?`button`:void 0,"aria-checked":y(M)(j.value)?`mixed`:j.value,"aria-required":e.required,"aria-label":e.$attrs[`aria-label`]||L.value,"data-state":y(N)(j.value),"data-disabled":D.value?``:void 0,disabled:D.value,focusable:y(S)?.rovingFocus.value?!D.value:void 0,onKeydown:t(o(()=>{},[`prevent`]),[`enter`]),onClick:P}),{default:_(()=>[f(e.$slots,`default`,{modelValue:y(T),state:j.value}),y(I)&&e.name&&!y(S)?(c(),r(y(b),{key:0,type:`checkbox`,checked:!!j.value,name:e.name,value:e.value,disabled:D.value,required:e.required},null,8,[`checked`,`name`,`value`,`disabled`,`required`])):s(`v-if`,!0)]),_:3},16,[`id`,`as-child`,`as`,`type`,`aria-checked`,`aria-required`,`aria-label`,`data-state`,`data-disabled`,`disabled`,`focusable`,`onKeydown`]))}}),L=e({__name:`CheckboxIndicator`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`span`}},setup(e){let{forwardRef:t}=p(),n=P();return(e,i)=>(c(),r(y(T),{present:e.forceMount||y(M)(y(n).state.value)||y(n).state.value===!0},{default:_(()=>[a(y(u),m({ref:y(t),"data-state":y(N)(y(n).state.value),"data-disabled":y(n).disabled.value?``:void 0,style:{pointerEvents:`none`},"as-child":e.asChild,as:e.as},e.$attrs),{default:_(()=>[f(e.$slots,`default`)]),_:3},16,[`data-state`,`data-disabled`,`as-child`,`as`])]),_:3},8,[`present`]))}}),R=e({__name:`Checkbox`,props:{defaultValue:{},modelValue:{},disabled:{type:Boolean},value:{},id:{},trueValue:{},falseValue:{},asChild:{type:Boolean},as:{},name:{},required:{type:Boolean},class:{type:[Boolean,null,String,Object,Array]}},emits:[`update:modelValue`],setup(e,{emit:t}){let i=e,o=t,s=S(v(i,`class`),o);return(e,t)=>(c(),r(y(I),m({"data-slot":`checkbox`},y(s),{class:y(h)(`border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-md border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50`,i.class)}),{default:_(t=>[a(y(L),{"data-slot":`checkbox-indicator`,class:`[&>svg]:size-3.5 grid place-content-center text-current transition-none`},{default:_(()=>[f(e.$slots,`default`,n(g(t)),()=>[a(y(D))])]),_:2},1024)]),_:3},16,[`class`]))}});export{R as t};
|
package/frontend-dist/assets/{CollapsibleContent-C3p4dMa-.js → CollapsibleContent-CUb_IZ--.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,Ht as t,J as n,K as r,Lt as i,Mt as a,Q as o,Y as s,d as c,dt as l,i as u,lt as d,m as f,mt as p,o as m,ot as h,st as g,tt as _,wt as v,xt as y,zt as b}from"./button-
|
|
1
|
+
import{$ as e,Ht as t,J as n,K as r,Lt as i,Mt as a,Q as o,Y as s,d as c,dt as l,i as u,lt as d,m as f,mt as p,o as m,ot as h,st as g,tt as _,wt as v,xt as y,zt as b}from"./button-CjKaq4D4.js";import{B as x,L as S,q as C,z as w}from"./index-C19mbJF3.js";var[T,E]=C(`CollapsibleRoot`),D=e({__name:`CollapsibleRoot`,props:{defaultOpen:{type:Boolean,required:!1,default:!1},open:{type:Boolean,required:!1,default:void 0},disabled:{type:Boolean,required:!1},unmountOnHide:{type:Boolean,required:!1,default:!0},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`update:open`],setup(e,{expose:t,emit:r}){let a=e,o=f(a,`open`,r,{defaultValue:a.defaultOpen,passive:a.open===void 0}),{disabled:s,unmountOnHide:c}=i(a);return E({contentId:``,disabled:s,open:o,unmountOnHide:c,onOpenToggle:()=>{s.value||(o.value=!o.value)}}),t({open:o}),m(),(e,t)=>(l(),n(b(u),{as:e.as,"as-child":a.asChild,"data-state":b(o)?`open`:`closed`,"data-disabled":b(s)?``:void 0},{default:v(()=>[p(e.$slots,`default`,{open:b(o)})]),_:3},8,[`as`,`as-child`,`data-state`,`data-disabled`]))}}),O=e({inheritAttrs:!1,__name:`CollapsibleContent`,props:{forceMount:{type:Boolean,required:!1},asChild:{type:Boolean,required:!1},as:{type:null,required:!1}},emits:[`contentFound`],setup(e,{emit:t}){let i=e,f=t,_=T();_.contentId||=w(void 0,`reka-collapsible-content`);let x=a(),{forwardRef:C,currentElement:E}=m(),D=a(0),O=a(0),k=r(()=>_.open.value),A=a(k.value),j=a();y(()=>[k.value,x.value?.present],async()=>{await g();let e=E.value;if(!e)return;j.value=j.value||{transitionDuration:e.style.transitionDuration,animationName:e.style.animationName},e.style.transitionDuration=`0s`,e.style.animationName=`none`;let t=e.getBoundingClientRect();O.value=t.height,D.value=t.width,A.value||(e.style.transitionDuration=j.value.transitionDuration,e.style.animationName=j.value.animationName)},{immediate:!0});let M=r(()=>A.value&&_.open.value);return d(()=>{requestAnimationFrame(()=>{A.value=!1})}),c(E,`beforematch`,e=>{requestAnimationFrame(()=>{_.onOpenToggle(),f(`contentFound`)})}),(e,t)=>(l(),n(b(S),{ref_key:`presentRef`,ref:x,present:e.forceMount||b(_).open.value,"force-mount":!0},{default:v(({present:t})=>[o(b(u),h(e.$attrs,{id:b(_).contentId,ref:b(C),"as-child":i.asChild,as:e.as,hidden:t?void 0:b(_).unmountOnHide.value?``:`until-found`,"data-state":M.value?void 0:b(_).open.value?`open`:`closed`,"data-disabled":b(_).disabled?.value?``:void 0,style:{"--reka-collapsible-content-height":`${O.value}px`,"--reka-collapsible-content-width":`${D.value}px`}}),{default:v(()=>[!b(_).unmountOnHide.value||t?p(e.$slots,`default`,{key:0}):s(`v-if`,!0)]),_:2},1040,[`id`,`as-child`,`as`,`hidden`,`data-state`,`data-disabled`,`style`])]),_:3},8,[`present`]))}}),k=e({__name:`Collapsible`,props:{defaultOpen:{type:Boolean},open:{type:Boolean},disabled:{type:Boolean},unmountOnHide:{type:Boolean},asChild:{type:Boolean},as:{}},emits:[`update:open`],setup(e,{emit:r}){let i=x(e,r);return(e,r)=>(l(),n(b(D),h({"data-slot":`collapsible`},b(i)),{default:v(n=>[p(e.$slots,`default`,t(_(n)))]),_:3},16))}}),A=e({__name:`CollapsibleContent`,props:{forceMount:{type:Boolean},asChild:{type:Boolean},as:{}},setup(e){let t=e;return(e,r)=>(l(),n(b(O),h({"data-slot":`collapsible-content`},t),{default:v(()=>[p(e.$slots,`default`)]),_:3},16))}});export{k as n,T as r,A as t};
|
package/frontend-dist/assets/{CollapsibleTrigger-DRGRANMT.js → CollapsibleTrigger-DSh5Vnmj.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{$ as e,J as t,dt as n,i as r,mt as i,o as a,ot as o,wt as s,zt as c}from"./button-
|
|
1
|
+
import{$ as e,J as t,dt as n,i as r,mt as i,o as a,ot as o,wt as s,zt as c}from"./button-CjKaq4D4.js";import{r as l}from"./CollapsibleContent-CUb_IZ--.js";var u=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean,required:!1},as:{type:null,required:!1,default:`button`}},setup(e){let o=e;a();let u=l();return(e,a)=>(n(),t(c(r),{type:e.as===`button`?`button`:void 0,as:e.as,"as-child":o.asChild,"aria-controls":c(u).contentId,"aria-expanded":c(u).open.value,"data-state":c(u).open.value?`open`:`closed`,"data-disabled":c(u).disabled?.value?``:void 0,disabled:c(u).disabled?.value,onClick:c(u).onOpenToggle},{default:s(()=>[i(e.$slots,`default`)]),_:3},8,[`type`,`as`,`as-child`,`aria-controls`,`aria-expanded`,`data-state`,`data-disabled`,`disabled`,`onClick`]))}}),d=e({__name:`CollapsibleTrigger`,props:{asChild:{type:Boolean},as:{}},setup(e){let r=e;return(e,a)=>(n(),t(c(u),o({"data-slot":`collapsible-trigger`},r),{default:s(()=>[i(e.$slots,`default`)]),_:3},16))}});export{d as t};
|