nx-kv 0.1.1 → 0.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.
@@ -35,6 +35,17 @@ export function booleanFlagNames(action) {
35
35
  return new Set(flagSpecsOf(action).filter((f) => (f.type || 'string') === 'boolean').map((f) => f.name));
36
36
  }
37
37
 
38
+ // ⚠️ rest flag 在**当前实现里刻意没有启用**。它能让 `--ref 修复登录页 500`
39
+ // 不加引号传整句,但代价是:它必须排在最后,于是没法与 `--pick` 组合——
40
+ // 而「同内容多条 → 用 --pick 消歧」正是最需要 ref 的场景。消歧能力比少打
41
+ // 一对引号重要,所以 ref 走普通 flag(值带空格时加引号)。
42
+ //
43
+ // 保留这个判定函数与装载期自检(runtime/registry.js),是为了让将来真要启用时
44
+ // 那条「必须置尾」的约束已经就位,而不是重新踩一遍。
45
+ export function restFlagNames(action) {
46
+ return new Set(flagSpecsOf(action).filter((f) => f.rest).map((f) => f.name));
47
+ }
48
+
38
49
  function coerceOne(name, spec, raw) {
39
50
  const type = spec.type || 'string';
40
51
  if (!TYPES.has(type)) throw new Error(`action 声明有误:flag "${name}" 的 type 非法 (${type})`);
@@ -131,17 +142,32 @@ export function usageOf(action) {
131
142
  parts.push(a.required ? `<${label}>` : `[${label}]`);
132
143
  }
133
144
 
145
+ // 出现在 rest flag 之后的 flag,都渲染进同一个括号里 —— 它们在命令行上
146
+ // 也是「同一片尾部」,必须整体后置(见 spec.js 顶部 restFlagNames 的说明)。
147
+ let trailing = [];
134
148
  for (const f of flagSpecsOf(action)) {
135
- let token;
136
149
  if (f.type === 'boolean') {
137
- token = `--${f.name}`;
138
- } else {
139
- // 值的占位符优先用 enum 展开(--side <ours|theirs>),其次显式 hint,
140
- // 最后才退回 flag 名——`--http <http>` 这种读起来没有信息量。
141
- const hint = f.enum ? f.enum.join('|') : f.hint || f.name;
142
- token = `--${f.name} <${hint}>`;
150
+ const token = `--${f.name}`;
151
+ const rendered = f.required ? token : `[${token}]`;
152
+ if (trailing.length) trailing.push(rendered);
153
+ else parts.push(rendered);
154
+ continue;
155
+ }
156
+
157
+ // 值的占位符优先用 enum 展开(--side <ours|theirs>),其次显式 hint,
158
+ // 最后才退回 flag 名——`--http <http>` 这种读起来没有信息量。
159
+ const hint = f.enum ? f.enum.join('|') : f.hint || f.name;
160
+ const token = `--${f.name} <${hint}>`;
161
+ const rendered = f.required ? token : `[${token}]`;
162
+
163
+ if (f.rest) {
164
+ parts.push(token + (trailing.length ? ' ' + trailing.join(' ') : ''));
165
+ trailing = [];
166
+ continue;
143
167
  }
144
- parts.push(f.required ? token : `[${token}]`);
168
+ if (trailing.length) trailing.push(rendered);
169
+ else parts.push(rendered);
145
170
  }
171
+ parts.push(...trailing);
146
172
  return parts.join(' ');
147
173
  }
@@ -41,7 +41,7 @@ export default function App() {
41
41
  return (
42
42
  <>
43
43
  <header>
44
- <div className="brand">nx-kv<span className="sub">nx-kv</span></div>
44
+ <div className="brand"><img src="/logo-rounded.png" alt="" />nx-kv<span className="sub">nx-kv</span></div>
45
45
  <nav>
46
46
  {VIEWS.map((v) => (
47
47
  <button
@@ -4,6 +4,10 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title>nx-kv · nx-kv</title>
7
+ <link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png">
8
+ <link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png">
9
+ <link rel="icon" type="image/x-icon" href="/favicon.ico">
10
+ <link rel="apple-touch-icon" href="/logo-rounded.png">
7
11
  <link rel="stylesheet" href="/style.css">
8
12
  </head>
9
13
  <body>
@@ -35,7 +35,8 @@ header {
35
35
  top: 0;
36
36
  z-index: 5;
37
37
  }
38
- .brand { font-weight: 800; letter-spacing: 0.4px; }
38
+ .brand { font-weight: 800; letter-spacing: 0.4px; display: inline-flex; align-items: center; gap: 7px; }
39
+ .brand img { width: 20px; height: 20px; border-radius: 5px; display: block; }
39
40
  .brand .sub { margin-left: 8px; font-weight: 400; color: var(--mid); font-size: 12px; }
40
41
 
41
42
  /* 分段控件:整块浅底 + 圆角滑块,取代带边框的直角 tab */
@@ -1 +1 @@
1
- import{o as e,s as t,t as n}from"./index-jhTtYCb9.js";var r=t();function i({module:t}){let{boot:i}=e(),a=(i?.commands||[]).filter(e=>e.module===t);return a.length?(0,r.jsxs)(`div`,{className:`cli-hint`,children:[(0,r.jsx)(`span`,{className:`cli-hint-label`,children:`CLI 等价(同构命令,加 --json 得机器可读输出):`}),a.map(e=>(0,r.jsx)(n,{className:`cli-cmd`,text:e.command,title:`点击复制:${e.usage}`,children:e.command},e.id))]}):null}export{i as t};
1
+ import{o as e,s as t,t as n}from"./index-Dv9g9jmR.js";var r=t();function i({module:t}){let{boot:i}=e(),a=(i?.commands||[]).filter(e=>e.module===t);return a.length?(0,r.jsxs)(`div`,{className:`cli-hint`,children:[(0,r.jsx)(`span`,{className:`cli-hint-label`,children:`CLI 等价(同构命令,加 --json 得机器可读输出):`}),a.map(e=>(0,r.jsx)(n,{className:`cli-cmd`,text:e.command,title:`点击复制:${e.usage}`,children:e.command},e.id))]}):null}export{i as t};
@@ -0,0 +1 @@
1
+ :root{--ink:#14161a;--paper:#fff;--soft:#f5f6f7;--soft-2:#ebedf0;--mid:#8b9096;--radius:12px;--radius-sm:8px;--shadow:0 1px 2px #14161a0f, 0 6px 16px #14161a0a}*{box-sizing:border-box}body{color:var(--ink);-webkit-font-smoothing:antialiased;background:#fbfbfc;margin:0;font-family:system-ui,Segoe UI,Microsoft YaHei,sans-serif;font-size:13.5px;line-height:1.55}header{background:var(--paper);box-shadow:0 1px 0 var(--soft-2);z-index:5;align-items:center;gap:20px;padding:12px 20px;display:flex;position:sticky;top:0}.brand{letter-spacing:.4px;align-items:center;gap:7px;font-weight:800;display:inline-flex}.brand img{border-radius:5px;width:20px;height:20px;display:block}.brand .sub{color:var(--mid);margin-left:8px;font-size:12px;font-weight:400}nav{background:var(--soft);border-radius:999px;gap:2px;padding:3px;display:inline-flex}.tab{font:inherit;color:var(--mid);cursor:pointer;background:0 0;border:0;border-radius:999px;padding:5px 16px;transition:background .15s,color .15s}.tab:hover{color:var(--ink)}.tab.active{background:var(--paper);color:var(--ink);box-shadow:var(--shadow);font-weight:600}.meta{color:var(--mid);margin-left:auto;font-family:ui-monospace,Consolas,monospace;font-size:11.5px}main{max-width:1240px;margin:0 auto;padding:18px 20px 28px}.panel{display:none}.panel.active{display:block}.toolbar{flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:10px;display:flex}.toolbar label{color:var(--mid);font-size:12px}.sep{background:var(--soft-2);width:1px;height:20px;margin:0 4px}.grow{max-width:340px}input,select{font:inherit;color:var(--ink);background:var(--paper);border:1px solid var(--soft-2);border-radius:var(--radius-sm);padding:6px 10px;transition:border-color .15s,box-shadow .15s}input::placeholder{color:#b3b8bd}input:focus,select:focus{border-color:var(--ink);outline:none;box-shadow:0 0 0 3px #14161a12}.btn{font:inherit;cursor:pointer;border-radius:var(--radius-sm);background:var(--ink);color:var(--paper);border:0;padding:6px 12px;transition:opacity .15s,background .15s,color .15s}.btn:hover{opacity:.86}.btn.ghost{background:var(--soft);color:var(--ink)}.btn.ghost:hover{background:var(--soft-2);opacity:1}.btn.small{border-radius:7px;padding:3px 9px;font-size:12px}.btn:disabled{opacity:.4;cursor:default}.btn.danger{color:#fff;background:#b3261e}.toast-stack{z-index:60;pointer-events:none;flex-direction:column;align-items:center;gap:8px;display:flex;position:fixed;bottom:28px;left:50%;transform:translate(-50%)}.toast{background:var(--ink);color:var(--paper);white-space:pre-wrap;word-break:break-all;border-radius:10px;max-width:72vw;padding:9px 16px;font-size:12.5px;box-shadow:0 8px 24px #14161a40}.dlg{-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:50;background:#fbfbfcdb;justify-content:center;align-items:flex-start;padding:96px 16px;display:flex;position:fixed;inset:0}.dlg-box{background:var(--paper);border-radius:var(--radius);width:min(460px,94vw);padding:16px 18px;box-shadow:0 12px 40px #14161a29}.dlg-title{margin-bottom:6px;font-weight:700}.dlg-msg{color:var(--ink);white-space:pre-wrap;word-break:break-all;margin-bottom:6px}.dlg-input{width:100%;margin:8px 0 4px;font-family:ui-monospace,Consolas,monospace;font-size:12.5px}.dlg-acts{justify-content:flex-end;gap:8px;margin-top:12px;display:flex}.card{background:var(--paper);border-radius:var(--radius);box-shadow:var(--shadow);margin-bottom:12px;padding:10px 12px}.card.hidden{display:none}.colhead{align-items:baseline;gap:8px;margin:2px 2px 8px;display:flex}h3{margin:0;font-size:13px;font-weight:700}.cols{align-items:flex-start;gap:14px;display:flex}.col{flex:1;min-width:0}.list{padding:4px}.row{border-radius:10px;flex-wrap:wrap;align-items:center;gap:8px 10px;padding:8px 10px;transition:background .12s;display:flex}.row:hover{background:var(--soft)}.row+.row{margin-top:2px}.row .tid{color:var(--mid);text-align:right;flex-shrink:0;min-width:30px;font-family:ui-monospace,Consolas,monospace;font-size:11.5px}.row .topic{background:var(--soft-2);white-space:nowrap;border-radius:5px;flex-shrink:0;padding:1px 6px;font-size:12px;font-weight:600}.row .text{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;overflow:hidden}.row .time{color:var(--mid);white-space:nowrap;flex-shrink:0;font-size:11.5px}.row .note{color:var(--mid);word-break:break-word;flex-basis:100%;padding-left:40px;font-size:11.5px}.row-inline{flex-wrap:wrap;align-items:center;gap:8px;display:flex}.row .name{text-overflow:ellipsis;white-space:nowrap;min-width:0;font-weight:600;overflow:hidden}.row .desc{color:var(--mid);text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;overflow:hidden}.row .acts{flex-shrink:0;align-items:center;gap:6px;margin-left:auto;display:flex}.plats{flex-wrap:wrap;gap:4px;display:flex}.pill{font:inherit;cursor:pointer;background:var(--soft);color:var(--mid);border:0;border-radius:999px;padding:5px 8px;font-size:11px;line-height:1;transition:background .12s,color .12s}.pill:hover{background:var(--soft-2);color:var(--ink)}.pill.on{background:var(--ink);color:var(--paper);font-weight:600}.pill.on.lnk{background:var(--paper);color:var(--ink);border:1.5px dashed var(--ink);padding:4px 6.5px}.tag{background:var(--soft);color:var(--mid);white-space:nowrap;border-radius:999px;padding:2px 8px;font-size:11px}.tag.strong{background:var(--ink);color:var(--paper)}table{border-collapse:collapse;width:100%}th,td{text-align:left;vertical-align:top;padding:9px 10px}th{color:var(--mid);font-size:11.5px;font-weight:600}tbody tr:hover{background:var(--soft)}tbody tr+tr td{box-shadow:inset 0 1px 0 var(--soft)}.mono,td.path{word-break:break-all;font-family:ui-monospace,Consolas,monospace;font-size:12px}td.ops{white-space:nowrap}td.ops .btn{margin:0 3px 3px 0}.muted{color:var(--mid)}.bad{font-weight:700}.copyable{cursor:copy;border-bottom:1px dashed #0000;transition:border-color .12s,color .12s}.copyable:hover{border-bottom-color:var(--mid)}.copyable:active{color:var(--ink)}dd .adapter-dir{margin-right:14px;display:inline-block}.settings{grid-template-columns:120px 1fr;align-items:center;gap:10px 16px;display:grid}.settings dt{color:var(--mid);font-size:12px}.settings dd{margin:0}.row-inline{gap:8px;margin-top:8px;display:flex}.row-inline input{flex:1}.cli-hint{color:var(--mid);flex-wrap:wrap;align-items:baseline;gap:4px 8px;padding:6px 4px 2px;font-size:11.5px;display:flex}.cli-hint-label{flex-basis:100%}.cli-cmd{background:var(--soft);white-space:nowrap;border-radius:5px;padding:1px 6px}.modal{-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:20;background:#fbfbfcdb;justify-content:center;align-items:flex-start;padding:48px 16px;display:flex;position:fixed;inset:0}.modal.hidden{display:none}.modal-box{background:var(--paper);border-radius:var(--radius);flex-direction:column;width:min(880px,96vw);max-height:84vh;display:flex;overflow:hidden;box-shadow:0 12px 40px #14161a29}.modal-title{box-shadow:0 1px 0 var(--soft);justify-content:space-between;align-items:center;padding:12px 14px;font-weight:700;display:flex}.modal-body{padding:14px;overflow:auto}pre{white-space:pre-wrap;word-break:break-all;margin:0;font-family:ui-monospace,Consolas,monospace;font-size:12px;line-height:1.6}.d-add{background:var(--soft-2);font-weight:600}.d-del{color:var(--mid);text-decoration:line-through}.conflict-file{background:var(--soft);border-radius:10px;margin-bottom:10px;overflow:hidden}.conflict-file .cf-head{justify-content:space-between;align-items:center;padding:8px 12px;font-family:ui-monospace,Consolas,monospace;font-size:12px;display:flex}.conflict-file pre{background:var(--paper);padding:10px 12px}footer{color:var(--mid);text-align:center;padding:14px 20px 24px;font-size:11.5px}footer code{background:var(--soft);border-radius:6px;padding:1px 6px;font-family:ui-monospace,Consolas,monospace}