@pmate/cli 0.20.0 → 0.20.2
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.d.ts +21 -2
- package/dist/index.js +444 -77
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -121,12 +121,31 @@ type SummaryCommandArgs = {
|
|
|
121
121
|
};
|
|
122
122
|
type QuizCommandArgs = {
|
|
123
123
|
type: Command.Quiz;
|
|
124
|
-
action: "
|
|
124
|
+
action: "create-draft";
|
|
125
|
+
paperId: string;
|
|
126
|
+
apiBaseUrl?: string;
|
|
127
|
+
linkBaseUrl?: string;
|
|
128
|
+
} | {
|
|
129
|
+
type: Command.Quiz;
|
|
130
|
+
action: "update-meta";
|
|
131
|
+
paperId: string;
|
|
125
132
|
filePath: string;
|
|
133
|
+
apiBaseUrl?: string;
|
|
134
|
+
linkBaseUrl?: string;
|
|
135
|
+
} | {
|
|
136
|
+
type: Command.Quiz;
|
|
137
|
+
action: "append-step";
|
|
126
138
|
paperId: string;
|
|
139
|
+
filePath: string;
|
|
140
|
+
apiBaseUrl?: string;
|
|
141
|
+
linkBaseUrl?: string;
|
|
142
|
+
} | {
|
|
143
|
+
type: Command.Quiz;
|
|
144
|
+
action: "reorder";
|
|
145
|
+
paperId: string;
|
|
146
|
+
stepIds: string[];
|
|
127
147
|
apiBaseUrl?: string;
|
|
128
148
|
linkBaseUrl?: string;
|
|
129
|
-
activate: boolean;
|
|
130
149
|
} | {
|
|
131
150
|
type: Command.Quiz;
|
|
132
151
|
action: "activate";
|
package/dist/index.js
CHANGED
|
@@ -96,7 +96,7 @@ function assertValidAppRef(appRef) {
|
|
|
96
96
|
function saveLoginSession(session, requestedApp = DEFAULT_APP_ID) {
|
|
97
97
|
const store = loadExistingSessionStoreOrEmpty();
|
|
98
98
|
const app = assertValidAppRef(requestedApp);
|
|
99
|
-
const sessionApp = session.session?.app?.trim();
|
|
99
|
+
const sessionApp = session.session?.identity?.app?.trim();
|
|
100
100
|
if (!sessionApp) {
|
|
101
101
|
throw new Error("Missing app in login session payload.");
|
|
102
102
|
}
|
|
@@ -13202,7 +13202,8 @@ var LoginCommandHandler = class {
|
|
|
13202
13202
|
);
|
|
13203
13203
|
}
|
|
13204
13204
|
const resp = await response.json();
|
|
13205
|
-
|
|
13205
|
+
const returnedApp = resp?.data?.session?.identity?.app?.trim();
|
|
13206
|
+
if (!returnedApp || returnedApp !== appId) {
|
|
13206
13207
|
throw new Error("Invalid exchange response: app-scoped session mismatch.");
|
|
13207
13208
|
}
|
|
13208
13209
|
return resp.data;
|
|
@@ -13214,9 +13215,16 @@ var LoginCommandHandler = class {
|
|
|
13214
13215
|
resolveToken = resolve;
|
|
13215
13216
|
rejectToken = reject;
|
|
13216
13217
|
});
|
|
13218
|
+
const openSockets = /* @__PURE__ */ new Set();
|
|
13217
13219
|
const server = (0, import_node_http.createServer)((request, response) => {
|
|
13218
13220
|
this.handleCallbackRequest(request, response, resolveToken, rejectToken);
|
|
13219
13221
|
});
|
|
13222
|
+
server.on("connection", (socket) => {
|
|
13223
|
+
openSockets.add(socket);
|
|
13224
|
+
socket.on("close", () => {
|
|
13225
|
+
openSockets.delete(socket);
|
|
13226
|
+
});
|
|
13227
|
+
});
|
|
13220
13228
|
await new Promise((resolve, reject) => {
|
|
13221
13229
|
server.once("error", reject);
|
|
13222
13230
|
server.listen(0, "127.0.0.1", () => resolve());
|
|
@@ -13236,9 +13244,15 @@ var LoginCommandHandler = class {
|
|
|
13236
13244
|
}, LOGIN_TIMEOUT_MS);
|
|
13237
13245
|
const close = async () => {
|
|
13238
13246
|
clearTimeout(timeout);
|
|
13239
|
-
|
|
13247
|
+
const closePromise = new Promise((resolve) => {
|
|
13240
13248
|
server.close(() => resolve());
|
|
13241
13249
|
});
|
|
13250
|
+
server.closeIdleConnections?.();
|
|
13251
|
+
server.closeAllConnections?.();
|
|
13252
|
+
for (const socket of openSockets) {
|
|
13253
|
+
socket.destroy();
|
|
13254
|
+
}
|
|
13255
|
+
await closePromise;
|
|
13242
13256
|
};
|
|
13243
13257
|
return {
|
|
13244
13258
|
redirectUrl,
|
|
@@ -13257,38 +13271,122 @@ var LoginCommandHandler = class {
|
|
|
13257
13271
|
if (!token) {
|
|
13258
13272
|
response.statusCode = 400;
|
|
13259
13273
|
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
13260
|
-
response.end(
|
|
13274
|
+
response.end(
|
|
13275
|
+
this.renderHtml({
|
|
13276
|
+
state: "error",
|
|
13277
|
+
title: "Login failed",
|
|
13278
|
+
message: "Missing sessionId in redirect URL.",
|
|
13279
|
+
hint: "Please retry from your terminal with `pmate login`."
|
|
13280
|
+
})
|
|
13281
|
+
);
|
|
13261
13282
|
rejectToken(new Error("Login callback did not include sessionId."));
|
|
13262
13283
|
return;
|
|
13263
13284
|
}
|
|
13264
13285
|
response.statusCode = 200;
|
|
13265
13286
|
response.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
13287
|
+
response.setHeader("Connection", "close");
|
|
13266
13288
|
response.end(
|
|
13267
13289
|
this.renderHtml(
|
|
13268
|
-
|
|
13269
|
-
|
|
13270
|
-
|
|
13290
|
+
{
|
|
13291
|
+
state: "success",
|
|
13292
|
+
title: "Login complete",
|
|
13293
|
+
message: "You can close this tab and return to the terminal.",
|
|
13294
|
+
hint: "This window is only used to hand the session back to PMate CLI."
|
|
13295
|
+
}
|
|
13296
|
+
),
|
|
13297
|
+
() => resolveToken(token)
|
|
13271
13298
|
);
|
|
13272
|
-
resolveToken(token);
|
|
13273
13299
|
}
|
|
13274
|
-
renderHtml(
|
|
13300
|
+
renderHtml(input) {
|
|
13301
|
+
const badgeBg = input.state === "success" ? "#ecfdf3" : "#fff1f2";
|
|
13302
|
+
const badgeText = input.state === "success" ? "#027a48" : "#be123c";
|
|
13303
|
+
const dotColor = input.state === "success" ? "#10b981" : "#f43f5e";
|
|
13304
|
+
const stateText = input.state === "success" ? "Ready" : "Action required";
|
|
13305
|
+
const hint = input.hint?.trim();
|
|
13275
13306
|
return `<!doctype html>
|
|
13276
13307
|
<html lang="en">
|
|
13277
13308
|
<head>
|
|
13278
13309
|
<meta charset="utf-8" />
|
|
13279
13310
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
13280
|
-
<title>${title}</title>
|
|
13311
|
+
<title>${input.title}</title>
|
|
13281
13312
|
<style>
|
|
13282
|
-
|
|
13283
|
-
|
|
13284
|
-
|
|
13285
|
-
|
|
13313
|
+
:root {
|
|
13314
|
+
color-scheme: light;
|
|
13315
|
+
}
|
|
13316
|
+
* {
|
|
13317
|
+
box-sizing: border-box;
|
|
13318
|
+
}
|
|
13319
|
+
body {
|
|
13320
|
+
margin: 0;
|
|
13321
|
+
min-height: 100vh;
|
|
13322
|
+
font-family: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
|
13323
|
+
color: #0f172a;
|
|
13324
|
+
background:
|
|
13325
|
+
radial-gradient(circle at 18% 18%, #e0f2fe 0, transparent 36%),
|
|
13326
|
+
radial-gradient(circle at 82% 14%, #e0e7ff 0, transparent 34%),
|
|
13327
|
+
linear-gradient(180deg, #f8fafc 0%, #eef2ff 100%);
|
|
13328
|
+
display: grid;
|
|
13329
|
+
place-items: center;
|
|
13330
|
+
padding: 24px;
|
|
13331
|
+
}
|
|
13332
|
+
main {
|
|
13333
|
+
width: min(560px, 100%);
|
|
13334
|
+
border-radius: 28px;
|
|
13335
|
+
border: 1px solid rgba(15, 23, 42, 0.08);
|
|
13336
|
+
background: rgba(255, 255, 255, 0.9);
|
|
13337
|
+
box-shadow:
|
|
13338
|
+
0 22px 56px rgba(15, 23, 42, 0.14),
|
|
13339
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.75);
|
|
13340
|
+
backdrop-filter: blur(8px);
|
|
13341
|
+
padding: 28px;
|
|
13342
|
+
}
|
|
13343
|
+
.badge {
|
|
13344
|
+
display: inline-flex;
|
|
13345
|
+
align-items: center;
|
|
13346
|
+
gap: 8px;
|
|
13347
|
+
border-radius: 999px;
|
|
13348
|
+
padding: 8px 12px;
|
|
13349
|
+
font-size: 14px;
|
|
13350
|
+
font-weight: 600;
|
|
13351
|
+
background: ${badgeBg};
|
|
13352
|
+
color: ${badgeText};
|
|
13353
|
+
}
|
|
13354
|
+
.dot {
|
|
13355
|
+
width: 10px;
|
|
13356
|
+
height: 10px;
|
|
13357
|
+
border-radius: 999px;
|
|
13358
|
+
background: ${dotColor};
|
|
13359
|
+
}
|
|
13360
|
+
h1 {
|
|
13361
|
+
margin: 16px 0 8px;
|
|
13362
|
+
font-size: 32px;
|
|
13363
|
+
line-height: 1.18;
|
|
13364
|
+
letter-spacing: -0.03em;
|
|
13365
|
+
}
|
|
13366
|
+
p {
|
|
13367
|
+
margin: 0;
|
|
13368
|
+
font-size: 16px;
|
|
13369
|
+
line-height: 1.6;
|
|
13370
|
+
color: #334155;
|
|
13371
|
+
}
|
|
13372
|
+
.hint {
|
|
13373
|
+
margin-top: 16px;
|
|
13374
|
+
border-radius: 14px;
|
|
13375
|
+
background: rgba(148, 163, 184, 0.14);
|
|
13376
|
+
padding: 12px 14px;
|
|
13377
|
+
font-size: 14px;
|
|
13378
|
+
}
|
|
13286
13379
|
</style>
|
|
13287
13380
|
</head>
|
|
13288
13381
|
<body>
|
|
13289
13382
|
<main>
|
|
13290
|
-
<
|
|
13291
|
-
|
|
13383
|
+
<div class="badge">
|
|
13384
|
+
<span class="dot"></span>
|
|
13385
|
+
<span>${stateText}</span>
|
|
13386
|
+
</div>
|
|
13387
|
+
<h1>${input.title}</h1>
|
|
13388
|
+
<p>${input.message}</p>
|
|
13389
|
+
${hint ? `<p class="hint">${hint}</p>` : ""}
|
|
13292
13390
|
</main>
|
|
13293
13391
|
</body>
|
|
13294
13392
|
</html>`;
|
|
@@ -17951,22 +18049,22 @@ init_sessionStore();
|
|
|
17951
18049
|
var INTRO_STEP_COUNT = 2;
|
|
17952
18050
|
var QUIZ_APP_ID = "quiz";
|
|
17953
18051
|
var DEFAULT_MIN_LENGTHS = Object.freeze({
|
|
17954
|
-
|
|
18052
|
+
teachingArticle: 36,
|
|
17955
18053
|
explanation: 60
|
|
17956
18054
|
});
|
|
17957
18055
|
var INTRO_MIN_LENGTHS = Object.freeze({
|
|
17958
|
-
|
|
17959
|
-
|
|
18056
|
+
teachingArticle: 90,
|
|
18057
|
+
teachingTip: 36,
|
|
17960
18058
|
explanation: 90
|
|
17961
18059
|
});
|
|
17962
18060
|
var FIELD_RULES = Object.freeze({
|
|
17963
|
-
|
|
17964
|
-
label: "
|
|
18061
|
+
teachingArticle: Object.freeze({
|
|
18062
|
+
label: "teachingArticle\uFF08\u6559\u5B66\u77ED\u6587\uFF09",
|
|
17965
18063
|
defaultHint: "\u77E5\u8BC6\u8BB2\u89E3\u81F3\u5C11\u8981\u5148\u628A\u9898\u76EE\u524D\u63D0\u8BF4\u6E05\u695A\uFF0C\u518D\u8BA9\u7528\u6237\u53BB\u9009\u7B54\u6848\u3002",
|
|
17966
18064
|
introHint: "\u5F00\u573A\u9898\u81F3\u5C11\u8981\u8BB2\u6E05\u5B83\u662F\u4EC0\u4E48\u3001\u89E3\u51B3\u4EC0\u4E48\u95EE\u9898\uFF0C\u4EE5\u53CA\u8BFB\u8005\u63A5\u4E0B\u6765\u8BE5\u5E26\u7740\u4EC0\u4E48\u7406\u89E3\u8DEF\u5F84\u7EE7\u7EED\u5F80\u4E0B\u770B\u3002"
|
|
17967
18065
|
}),
|
|
17968
|
-
|
|
17969
|
-
label: "
|
|
18066
|
+
teachingTip: Object.freeze({
|
|
18067
|
+
label: "teachingTip\uFF08\u8865\u5145\u8BF4\u660E\uFF09",
|
|
17970
18068
|
introHint: "\u5F00\u573A\u9898\u8981\u8865\u5145\u4E3A\u4EC0\u4E48\u5BB9\u6613\u8BEF\u89E3\uFF0C\u6216\u8005\u7B2C\u4E00\u6B21\u8BFB\u8FD9\u5757\u5185\u5BB9\u65F6\u5E94\u8BE5\u5148\u770B\u54EA\u91CC\u3002"
|
|
17971
18069
|
}),
|
|
17972
18070
|
explanation: Object.freeze({
|
|
@@ -18006,9 +18104,9 @@ function validateQuizPaperPayload(payload) {
|
|
|
18006
18104
|
assertMinLength(
|
|
18007
18105
|
step,
|
|
18008
18106
|
index,
|
|
18009
|
-
"
|
|
18010
|
-
DEFAULT_MIN_LENGTHS.
|
|
18011
|
-
FIELD_RULES.
|
|
18107
|
+
"teachingArticle",
|
|
18108
|
+
DEFAULT_MIN_LENGTHS.teachingArticle,
|
|
18109
|
+
FIELD_RULES.teachingArticle.defaultHint
|
|
18012
18110
|
);
|
|
18013
18111
|
assertMinLength(
|
|
18014
18112
|
step,
|
|
@@ -18023,16 +18121,16 @@ function validateQuizPaperPayload(payload) {
|
|
|
18023
18121
|
assertMinLength(
|
|
18024
18122
|
step,
|
|
18025
18123
|
index,
|
|
18026
|
-
"
|
|
18027
|
-
INTRO_MIN_LENGTHS.
|
|
18028
|
-
FIELD_RULES.
|
|
18124
|
+
"teachingArticle",
|
|
18125
|
+
INTRO_MIN_LENGTHS.teachingArticle,
|
|
18126
|
+
FIELD_RULES.teachingArticle.introHint
|
|
18029
18127
|
);
|
|
18030
18128
|
assertMinLength(
|
|
18031
18129
|
step,
|
|
18032
18130
|
index,
|
|
18033
|
-
"
|
|
18034
|
-
INTRO_MIN_LENGTHS.
|
|
18035
|
-
FIELD_RULES.
|
|
18131
|
+
"teachingTip",
|
|
18132
|
+
INTRO_MIN_LENGTHS.teachingTip,
|
|
18133
|
+
FIELD_RULES.teachingTip.introHint
|
|
18036
18134
|
);
|
|
18037
18135
|
assertMinLength(
|
|
18038
18136
|
step,
|
|
@@ -18180,6 +18278,131 @@ async function activateQuizPaper({
|
|
|
18180
18278
|
data: activated
|
|
18181
18279
|
};
|
|
18182
18280
|
}
|
|
18281
|
+
async function createQuizDraft({
|
|
18282
|
+
fetchImpl = fetch,
|
|
18283
|
+
apiBaseUrl,
|
|
18284
|
+
linkBaseUrl,
|
|
18285
|
+
paperId,
|
|
18286
|
+
token
|
|
18287
|
+
}) {
|
|
18288
|
+
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
18289
|
+
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
18290
|
+
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
18291
|
+
const data = await requestJson(
|
|
18292
|
+
fetchImpl,
|
|
18293
|
+
`${trimmedApiBaseUrl}/api/quiz/papers`,
|
|
18294
|
+
{
|
|
18295
|
+
method: "POST",
|
|
18296
|
+
headers: {
|
|
18297
|
+
Authorization: `Bearer ${token}`,
|
|
18298
|
+
"Content-Type": "application/json"
|
|
18299
|
+
},
|
|
18300
|
+
body: JSON.stringify({ paperId })
|
|
18301
|
+
},
|
|
18302
|
+
"\u521B\u5EFA\u8349\u7A3F"
|
|
18303
|
+
);
|
|
18304
|
+
return {
|
|
18305
|
+
apiBaseUrl: trimmedApiBaseUrl,
|
|
18306
|
+
paperId,
|
|
18307
|
+
previewLink,
|
|
18308
|
+
data
|
|
18309
|
+
};
|
|
18310
|
+
}
|
|
18311
|
+
async function updateQuizPaperMetadata({
|
|
18312
|
+
fetchImpl = fetch,
|
|
18313
|
+
apiBaseUrl,
|
|
18314
|
+
linkBaseUrl,
|
|
18315
|
+
paperId,
|
|
18316
|
+
metadata,
|
|
18317
|
+
token
|
|
18318
|
+
}) {
|
|
18319
|
+
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
18320
|
+
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
18321
|
+
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
18322
|
+
const data = await requestJson(
|
|
18323
|
+
fetchImpl,
|
|
18324
|
+
`${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}`,
|
|
18325
|
+
{
|
|
18326
|
+
method: "PATCH",
|
|
18327
|
+
headers: {
|
|
18328
|
+
Authorization: `Bearer ${token}`,
|
|
18329
|
+
"Content-Type": "application/json"
|
|
18330
|
+
},
|
|
18331
|
+
body: JSON.stringify(metadata)
|
|
18332
|
+
},
|
|
18333
|
+
"\u66F4\u65B0\u8BD5\u5377\u5143\u4FE1\u606F"
|
|
18334
|
+
);
|
|
18335
|
+
return {
|
|
18336
|
+
apiBaseUrl: trimmedApiBaseUrl,
|
|
18337
|
+
paperId,
|
|
18338
|
+
previewLink,
|
|
18339
|
+
data
|
|
18340
|
+
};
|
|
18341
|
+
}
|
|
18342
|
+
async function appendQuizPaperStep({
|
|
18343
|
+
fetchImpl = fetch,
|
|
18344
|
+
apiBaseUrl,
|
|
18345
|
+
linkBaseUrl,
|
|
18346
|
+
paperId,
|
|
18347
|
+
step,
|
|
18348
|
+
token
|
|
18349
|
+
}) {
|
|
18350
|
+
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
18351
|
+
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
18352
|
+
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
18353
|
+
const data = await requestJson(
|
|
18354
|
+
fetchImpl,
|
|
18355
|
+
`${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps`,
|
|
18356
|
+
{
|
|
18357
|
+
method: "POST",
|
|
18358
|
+
headers: {
|
|
18359
|
+
Authorization: `Bearer ${token}`,
|
|
18360
|
+
"Content-Type": "application/json"
|
|
18361
|
+
},
|
|
18362
|
+
body: JSON.stringify(step)
|
|
18363
|
+
},
|
|
18364
|
+
`\u8FFD\u52A0\u9898\u76EE\uFF08${String(step?.stepId ?? "unknown-step")}\uFF09`
|
|
18365
|
+
);
|
|
18366
|
+
return {
|
|
18367
|
+
apiBaseUrl: trimmedApiBaseUrl,
|
|
18368
|
+
paperId,
|
|
18369
|
+
previewLink,
|
|
18370
|
+
data
|
|
18371
|
+
};
|
|
18372
|
+
}
|
|
18373
|
+
async function reorderQuizPaperSteps({
|
|
18374
|
+
fetchImpl = fetch,
|
|
18375
|
+
apiBaseUrl,
|
|
18376
|
+
linkBaseUrl,
|
|
18377
|
+
paperId,
|
|
18378
|
+
stepIds,
|
|
18379
|
+
token
|
|
18380
|
+
}) {
|
|
18381
|
+
const trimmedApiBaseUrl = apiBaseUrl.replace(/\/+$/, "");
|
|
18382
|
+
const trimmedLinkBaseUrl = linkBaseUrl.replace(/\/+$/, "");
|
|
18383
|
+
const previewLink = `${trimmedLinkBaseUrl}/?paper=${encodeURIComponent(paperId)}`;
|
|
18384
|
+
const data = await requestJson(
|
|
18385
|
+
fetchImpl,
|
|
18386
|
+
`${trimmedApiBaseUrl}/api/quiz/papers/${encodeURIComponent(paperId)}/steps/reorder`,
|
|
18387
|
+
{
|
|
18388
|
+
method: "POST",
|
|
18389
|
+
headers: {
|
|
18390
|
+
Authorization: `Bearer ${token}`,
|
|
18391
|
+
"Content-Type": "application/json"
|
|
18392
|
+
},
|
|
18393
|
+
body: JSON.stringify({
|
|
18394
|
+
stepIds
|
|
18395
|
+
})
|
|
18396
|
+
},
|
|
18397
|
+
"\u91CD\u6392\u9898\u76EE\u987A\u5E8F"
|
|
18398
|
+
);
|
|
18399
|
+
return {
|
|
18400
|
+
apiBaseUrl: trimmedApiBaseUrl,
|
|
18401
|
+
paperId,
|
|
18402
|
+
previewLink,
|
|
18403
|
+
data
|
|
18404
|
+
};
|
|
18405
|
+
}
|
|
18183
18406
|
async function viewQuizPaper({
|
|
18184
18407
|
fetchImpl = fetch,
|
|
18185
18408
|
apiBaseUrl,
|
|
@@ -18242,26 +18465,76 @@ var QuizCommandHandler = class {
|
|
|
18242
18465
|
const apiBaseUrl = args.apiBaseUrl || DEFAULT_QUIZ_API_BASE_URL;
|
|
18243
18466
|
const linkBaseUrl = args.linkBaseUrl || DEFAULT_QUIZ_LINK_BASE_URL;
|
|
18244
18467
|
if (args.action === "activate") {
|
|
18245
|
-
const
|
|
18468
|
+
const result = await activateQuizPaper({
|
|
18469
|
+
apiBaseUrl,
|
|
18470
|
+
linkBaseUrl,
|
|
18471
|
+
paperId: args.paperId,
|
|
18472
|
+
token: session.token
|
|
18473
|
+
});
|
|
18474
|
+
ui.success("Quiz \u5DF2\u6FC0\u6D3B\u53D1\u5E03", result.link);
|
|
18475
|
+
return;
|
|
18476
|
+
}
|
|
18477
|
+
if (args.action === "create-draft") {
|
|
18478
|
+
const result = await createQuizDraft({
|
|
18479
|
+
apiBaseUrl,
|
|
18480
|
+
linkBaseUrl,
|
|
18481
|
+
paperId: args.paperId,
|
|
18482
|
+
token: session.token
|
|
18483
|
+
});
|
|
18484
|
+
ui.success("Quiz \u8349\u7A3F\u5DF2\u521B\u5EFA", result.previewLink);
|
|
18485
|
+
ui.info("\u72B6\u6001", "draft");
|
|
18486
|
+
return;
|
|
18487
|
+
}
|
|
18488
|
+
if (args.action === "update-meta") {
|
|
18489
|
+
const resolvedFilePath = import_node_path14.default.resolve(process.cwd(), args.filePath);
|
|
18490
|
+
const metadata = JSON.parse((0, import_node_fs9.readFileSync)(resolvedFilePath, "utf8"));
|
|
18491
|
+
const result = await updateQuizPaperMetadata({
|
|
18246
18492
|
apiBaseUrl,
|
|
18247
18493
|
linkBaseUrl,
|
|
18248
18494
|
paperId: args.paperId,
|
|
18495
|
+
metadata,
|
|
18249
18496
|
token: session.token
|
|
18250
18497
|
});
|
|
18251
|
-
ui.success("Quiz \
|
|
18498
|
+
ui.success("Quiz \u5143\u4FE1\u606F\u5DF2\u66F4\u65B0", result.previewLink);
|
|
18499
|
+
return;
|
|
18500
|
+
}
|
|
18501
|
+
if (args.action === "append-step") {
|
|
18502
|
+
const resolvedFilePath = import_node_path14.default.resolve(process.cwd(), args.filePath);
|
|
18503
|
+
const step = JSON.parse((0, import_node_fs9.readFileSync)(resolvedFilePath, "utf8"));
|
|
18504
|
+
const result = await appendQuizPaperStep({
|
|
18505
|
+
apiBaseUrl,
|
|
18506
|
+
linkBaseUrl,
|
|
18507
|
+
paperId: args.paperId,
|
|
18508
|
+
step,
|
|
18509
|
+
token: session.token
|
|
18510
|
+
});
|
|
18511
|
+
ui.success("Quiz \u9898\u76EE\u5DF2\u8FFD\u52A0", result.previewLink);
|
|
18512
|
+
ui.info("stepId", String(step.stepId));
|
|
18513
|
+
return;
|
|
18514
|
+
}
|
|
18515
|
+
if (args.action === "reorder") {
|
|
18516
|
+
const result = await reorderQuizPaperSteps({
|
|
18517
|
+
apiBaseUrl,
|
|
18518
|
+
linkBaseUrl,
|
|
18519
|
+
paperId: args.paperId,
|
|
18520
|
+
stepIds: args.stepIds,
|
|
18521
|
+
token: session.token
|
|
18522
|
+
});
|
|
18523
|
+
ui.success("Quiz \u9898\u76EE\u987A\u5E8F\u5DF2\u66F4\u65B0", result.previewLink);
|
|
18524
|
+
ui.info("\u6570\u91CF", String(args.stepIds.length));
|
|
18252
18525
|
return;
|
|
18253
18526
|
}
|
|
18254
18527
|
if (args.action === "view") {
|
|
18255
|
-
const
|
|
18528
|
+
const result = await viewQuizPaper({
|
|
18256
18529
|
apiBaseUrl,
|
|
18257
18530
|
linkBaseUrl,
|
|
18258
18531
|
paperId: args.paperId,
|
|
18259
18532
|
token: session.token
|
|
18260
18533
|
});
|
|
18261
|
-
ui.success("Quiz \u8BD5\u5377\u5DF2\u627E\u5230",
|
|
18262
|
-
ui.info("\u72B6\u6001",
|
|
18263
|
-
if (typeof
|
|
18264
|
-
ui.info("\u9898\u76EE\u6570", String(
|
|
18534
|
+
ui.success("Quiz \u8BD5\u5377\u5DF2\u627E\u5230", result.previewLink);
|
|
18535
|
+
ui.info("\u72B6\u6001", result.paperStatus);
|
|
18536
|
+
if (typeof result.stepCount === "number") {
|
|
18537
|
+
ui.info("\u9898\u76EE\u6570", String(result.stepCount));
|
|
18265
18538
|
}
|
|
18266
18539
|
return;
|
|
18267
18540
|
}
|
|
@@ -18276,13 +18549,13 @@ var QuizCommandHandler = class {
|
|
|
18276
18549
|
if (targetIndex < 0) {
|
|
18277
18550
|
throw new Error(`\u672A\u627E\u5230 stepId=${args.stepId}\uFF0C\u65E0\u6CD5\u66F4\u65B0\u8BE5\u9898\u76EE\u3002`);
|
|
18278
18551
|
}
|
|
18279
|
-
const
|
|
18280
|
-
const nextStep = JSON.parse((0, import_node_fs9.readFileSync)(
|
|
18552
|
+
const resolvedFilePath = import_node_path14.default.resolve(process.cwd(), args.filePath);
|
|
18553
|
+
const nextStep = JSON.parse((0, import_node_fs9.readFileSync)(resolvedFilePath, "utf8"));
|
|
18281
18554
|
nextStep.stepId = args.stepId;
|
|
18282
18555
|
const nextSteps = [...basePaper.steps];
|
|
18283
18556
|
nextSteps[targetIndex] = nextStep;
|
|
18284
18557
|
const nextPaperId = args.newPaperId || `${args.paperId}-rev-${this.timestampTag()}`;
|
|
18285
|
-
const
|
|
18558
|
+
const result = await publishQuizPaper({
|
|
18286
18559
|
apiBaseUrl,
|
|
18287
18560
|
linkBaseUrl,
|
|
18288
18561
|
paperId: nextPaperId,
|
|
@@ -18296,37 +18569,20 @@ var QuizCommandHandler = class {
|
|
|
18296
18569
|
token: session.token,
|
|
18297
18570
|
activate: args.activate
|
|
18298
18571
|
});
|
|
18299
|
-
if (
|
|
18300
|
-
ui.success("Quiz \u5355\u9898\u4FEE\u8BA2\u7A3F\u5DF2\u521B\u5EFA",
|
|
18572
|
+
if (result.status === "draft") {
|
|
18573
|
+
ui.success("Quiz \u5355\u9898\u4FEE\u8BA2\u7A3F\u5DF2\u521B\u5EFA", result.previewLink);
|
|
18301
18574
|
ui.info("\u6765\u6E90\u8BD5\u5377", args.paperId);
|
|
18302
18575
|
ui.info("\u4FEE\u8BA2\u9898\u76EE", args.stepId);
|
|
18303
18576
|
ui.info("\u65B0\u8BD5\u5377", nextPaperId);
|
|
18304
18577
|
ui.info("\u4E0B\u4E00\u6B65", `pmate quiz activate --paper-id ${nextPaperId}`);
|
|
18305
18578
|
return;
|
|
18306
18579
|
}
|
|
18307
|
-
ui.success("Quiz \u5355\u9898\u4FEE\u8BA2\u7A3F\u5DF2\u53D1\u5E03",
|
|
18580
|
+
ui.success("Quiz \u5355\u9898\u4FEE\u8BA2\u7A3F\u5DF2\u53D1\u5E03", result.link);
|
|
18308
18581
|
ui.info("\u6765\u6E90\u8BD5\u5377", args.paperId);
|
|
18309
18582
|
ui.info("\u4FEE\u8BA2\u9898\u76EE", args.stepId);
|
|
18310
18583
|
ui.info("\u65B0\u8BD5\u5377", nextPaperId);
|
|
18311
18584
|
return;
|
|
18312
18585
|
}
|
|
18313
|
-
const resolvedFilePath = import_node_path14.default.resolve(process.cwd(), args.filePath);
|
|
18314
|
-
const payload = JSON.parse((0, import_node_fs9.readFileSync)(resolvedFilePath, "utf8"));
|
|
18315
|
-
const result = await publishQuizPaper({
|
|
18316
|
-
apiBaseUrl,
|
|
18317
|
-
linkBaseUrl,
|
|
18318
|
-
paperId: args.paperId,
|
|
18319
|
-
payload,
|
|
18320
|
-
token: session.token,
|
|
18321
|
-
activate: args.activate
|
|
18322
|
-
});
|
|
18323
|
-
if (result.status === "draft") {
|
|
18324
|
-
ui.success("Quiz \u8349\u7A3F\u5DF2\u521B\u5EFA", result.previewLink);
|
|
18325
|
-
ui.info("\u72B6\u6001", "draft");
|
|
18326
|
-
ui.info("\u4E0B\u4E00\u6B65", `pmate quiz activate --paper-id ${args.paperId}`);
|
|
18327
|
-
return;
|
|
18328
|
-
}
|
|
18329
|
-
ui.success("Quiz \u5DF2\u53D1\u5E03", result.link);
|
|
18330
18586
|
}
|
|
18331
18587
|
timestampTag() {
|
|
18332
18588
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -21977,7 +22233,10 @@ var HELP_TEXT = [
|
|
|
21977
22233
|
` ${import_chalk3.default.cyan("summary")} Summarize a GitHub PR with AI`,
|
|
21978
22234
|
` ${import_chalk3.default.gray(" --pr <id> [--cwd <dir>]")}`,
|
|
21979
22235
|
` ${import_chalk3.default.cyan("quiz")} Manage quiz papers on quiz-api`,
|
|
21980
|
-
` ${import_chalk3.default.gray("
|
|
22236
|
+
` ${import_chalk3.default.gray(" create-draft --paper-id <id>")}`,
|
|
22237
|
+
` ${import_chalk3.default.gray(" update-meta --paper-id <id> --file <metadata.json>")}`,
|
|
22238
|
+
` ${import_chalk3.default.gray(" append-step --paper-id <id> --file <step.json>")}`,
|
|
22239
|
+
` ${import_chalk3.default.gray(" reorder --paper-id <id> --step-ids <id1,id2,...>")}`,
|
|
21981
22240
|
` ${import_chalk3.default.gray(" activate --paper-id <id>")}`,
|
|
21982
22241
|
` ${import_chalk3.default.gray(" view --paper-id <id>")}`,
|
|
21983
22242
|
` ${import_chalk3.default.gray(" edit-step --paper-id <id> --step-id <step-id> --file <step.json> [--new-paper-id <id>] [--activate]")}`,
|
|
@@ -22577,50 +22836,158 @@ function parseQuizArgs(tokens) {
|
|
|
22577
22836
|
const rest = [...tokens];
|
|
22578
22837
|
const action = rest.shift();
|
|
22579
22838
|
if (!action) {
|
|
22580
|
-
throw new Error("Missing quiz action. Usage: quiz
|
|
22839
|
+
throw new Error("Missing quiz action. Usage: quiz create-draft|update-meta|append-step|reorder|activate|view|edit-step");
|
|
22581
22840
|
}
|
|
22582
|
-
if (action === "
|
|
22583
|
-
let filePath;
|
|
22841
|
+
if (action === "create-draft") {
|
|
22584
22842
|
let paperId;
|
|
22585
22843
|
let apiBaseUrl;
|
|
22586
22844
|
let linkBaseUrl;
|
|
22587
|
-
let activate = false;
|
|
22588
22845
|
while (rest.length > 0) {
|
|
22589
22846
|
const token = rest.shift();
|
|
22590
22847
|
switch (token) {
|
|
22848
|
+
case "--paper-id":
|
|
22849
|
+
paperId = requireValue8(rest, token);
|
|
22850
|
+
break;
|
|
22851
|
+
case "--base-url":
|
|
22852
|
+
apiBaseUrl = requireValue8(rest, token);
|
|
22853
|
+
break;
|
|
22854
|
+
case "--link-base":
|
|
22855
|
+
linkBaseUrl = requireValue8(rest, token);
|
|
22856
|
+
break;
|
|
22857
|
+
default:
|
|
22858
|
+
throw new Error(`Unknown quiz create-draft option: ${token}`);
|
|
22859
|
+
}
|
|
22860
|
+
}
|
|
22861
|
+
if (!paperId) {
|
|
22862
|
+
throw new Error("Missing --paper-id. Usage: quiz create-draft --paper-id <id>.");
|
|
22863
|
+
}
|
|
22864
|
+
return {
|
|
22865
|
+
type: "quiz" /* Quiz */,
|
|
22866
|
+
action: "create-draft",
|
|
22867
|
+
paperId,
|
|
22868
|
+
apiBaseUrl,
|
|
22869
|
+
linkBaseUrl
|
|
22870
|
+
};
|
|
22871
|
+
}
|
|
22872
|
+
if (action === "update-meta") {
|
|
22873
|
+
let paperId;
|
|
22874
|
+
let filePath;
|
|
22875
|
+
let apiBaseUrl;
|
|
22876
|
+
let linkBaseUrl;
|
|
22877
|
+
while (rest.length > 0) {
|
|
22878
|
+
const token = rest.shift();
|
|
22879
|
+
switch (token) {
|
|
22880
|
+
case "--paper-id":
|
|
22881
|
+
paperId = requireValue8(rest, token);
|
|
22882
|
+
break;
|
|
22591
22883
|
case "--file":
|
|
22592
22884
|
filePath = requireValue8(rest, token);
|
|
22593
22885
|
break;
|
|
22886
|
+
case "--base-url":
|
|
22887
|
+
apiBaseUrl = requireValue8(rest, token);
|
|
22888
|
+
break;
|
|
22889
|
+
case "--link-base":
|
|
22890
|
+
linkBaseUrl = requireValue8(rest, token);
|
|
22891
|
+
break;
|
|
22892
|
+
default:
|
|
22893
|
+
throw new Error(`Unknown quiz update-meta option: ${token}`);
|
|
22894
|
+
}
|
|
22895
|
+
}
|
|
22896
|
+
if (!paperId) {
|
|
22897
|
+
throw new Error("Missing --paper-id. Usage: quiz update-meta --paper-id <id> --file <metadata.json>.");
|
|
22898
|
+
}
|
|
22899
|
+
if (!filePath) {
|
|
22900
|
+
throw new Error("Missing --file. Usage: quiz update-meta --paper-id <id> --file <metadata.json>.");
|
|
22901
|
+
}
|
|
22902
|
+
return {
|
|
22903
|
+
type: "quiz" /* Quiz */,
|
|
22904
|
+
action: "update-meta",
|
|
22905
|
+
paperId,
|
|
22906
|
+
filePath,
|
|
22907
|
+
apiBaseUrl,
|
|
22908
|
+
linkBaseUrl
|
|
22909
|
+
};
|
|
22910
|
+
}
|
|
22911
|
+
if (action === "append-step") {
|
|
22912
|
+
let paperId;
|
|
22913
|
+
let filePath;
|
|
22914
|
+
let apiBaseUrl;
|
|
22915
|
+
let linkBaseUrl;
|
|
22916
|
+
while (rest.length > 0) {
|
|
22917
|
+
const token = rest.shift();
|
|
22918
|
+
switch (token) {
|
|
22594
22919
|
case "--paper-id":
|
|
22595
22920
|
paperId = requireValue8(rest, token);
|
|
22596
22921
|
break;
|
|
22922
|
+
case "--file":
|
|
22923
|
+
filePath = requireValue8(rest, token);
|
|
22924
|
+
break;
|
|
22597
22925
|
case "--base-url":
|
|
22598
22926
|
apiBaseUrl = requireValue8(rest, token);
|
|
22599
22927
|
break;
|
|
22600
22928
|
case "--link-base":
|
|
22601
22929
|
linkBaseUrl = requireValue8(rest, token);
|
|
22602
22930
|
break;
|
|
22603
|
-
case "--activate":
|
|
22604
|
-
activate = true;
|
|
22605
|
-
break;
|
|
22606
22931
|
default:
|
|
22607
|
-
throw new Error(`Unknown quiz
|
|
22932
|
+
throw new Error(`Unknown quiz append-step option: ${token}`);
|
|
22608
22933
|
}
|
|
22609
22934
|
}
|
|
22935
|
+
if (!paperId) {
|
|
22936
|
+
throw new Error("Missing --paper-id. Usage: quiz append-step --paper-id <id> --file <step.json>.");
|
|
22937
|
+
}
|
|
22610
22938
|
if (!filePath) {
|
|
22611
|
-
throw new Error("Missing --file. Usage: quiz
|
|
22939
|
+
throw new Error("Missing --file. Usage: quiz append-step --paper-id <id> --file <step.json>.");
|
|
22940
|
+
}
|
|
22941
|
+
return {
|
|
22942
|
+
type: "quiz" /* Quiz */,
|
|
22943
|
+
action: "append-step",
|
|
22944
|
+
paperId,
|
|
22945
|
+
filePath,
|
|
22946
|
+
apiBaseUrl,
|
|
22947
|
+
linkBaseUrl
|
|
22948
|
+
};
|
|
22949
|
+
}
|
|
22950
|
+
if (action === "reorder") {
|
|
22951
|
+
let paperId;
|
|
22952
|
+
let stepIdsRaw;
|
|
22953
|
+
let apiBaseUrl;
|
|
22954
|
+
let linkBaseUrl;
|
|
22955
|
+
while (rest.length > 0) {
|
|
22956
|
+
const token = rest.shift();
|
|
22957
|
+
switch (token) {
|
|
22958
|
+
case "--paper-id":
|
|
22959
|
+
paperId = requireValue8(rest, token);
|
|
22960
|
+
break;
|
|
22961
|
+
case "--step-ids":
|
|
22962
|
+
stepIdsRaw = requireValue8(rest, token);
|
|
22963
|
+
break;
|
|
22964
|
+
case "--base-url":
|
|
22965
|
+
apiBaseUrl = requireValue8(rest, token);
|
|
22966
|
+
break;
|
|
22967
|
+
case "--link-base":
|
|
22968
|
+
linkBaseUrl = requireValue8(rest, token);
|
|
22969
|
+
break;
|
|
22970
|
+
default:
|
|
22971
|
+
throw new Error(`Unknown quiz reorder option: ${token}`);
|
|
22972
|
+
}
|
|
22612
22973
|
}
|
|
22613
22974
|
if (!paperId) {
|
|
22614
|
-
throw new Error("Missing --paper-id. Usage: quiz
|
|
22975
|
+
throw new Error("Missing --paper-id. Usage: quiz reorder --paper-id <id> --step-ids <id1,id2,...>.");
|
|
22976
|
+
}
|
|
22977
|
+
if (!stepIdsRaw) {
|
|
22978
|
+
throw new Error("Missing --step-ids. Usage: quiz reorder --paper-id <id> --step-ids <id1,id2,...>.");
|
|
22979
|
+
}
|
|
22980
|
+
const stepIds = stepIdsRaw.split(",").map((item) => item.trim()).filter(Boolean);
|
|
22981
|
+
if (stepIds.length === 0) {
|
|
22982
|
+
throw new Error("Invalid --step-ids. At least one step id is required.");
|
|
22615
22983
|
}
|
|
22616
22984
|
return {
|
|
22617
22985
|
type: "quiz" /* Quiz */,
|
|
22618
|
-
action: "
|
|
22619
|
-
filePath,
|
|
22986
|
+
action: "reorder",
|
|
22620
22987
|
paperId,
|
|
22988
|
+
stepIds,
|
|
22621
22989
|
apiBaseUrl,
|
|
22622
|
-
linkBaseUrl
|
|
22623
|
-
activate
|
|
22990
|
+
linkBaseUrl
|
|
22624
22991
|
};
|
|
22625
22992
|
}
|
|
22626
22993
|
if (action === "activate") {
|