@wport/cli 0.9.3 → 0.10.1
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/CHANGELOG.md +68 -0
- package/README.md +21 -1
- package/dist/index.js +390 -110
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -387,7 +387,7 @@ function registerJobsSearch(parent) {
|
|
|
387
387
|
baseUrl: ctx.baseUrl,
|
|
388
388
|
locale: ctx.locale,
|
|
389
389
|
timeoutMs: ctx.timeoutMs,
|
|
390
|
-
userAgent: (0, import_core2.buildUserAgent)("wport-cli", "0.
|
|
390
|
+
userAgent: (0, import_core2.buildUserAgent)("wport-cli", "0.10.1"),
|
|
391
391
|
source: CLI_SOURCE
|
|
392
392
|
});
|
|
393
393
|
const { data, error, response } = await client.GET("/api/jobs/search", {
|
|
@@ -632,7 +632,7 @@ function registerJobsView(parent) {
|
|
|
632
632
|
baseUrl: ctx.baseUrl,
|
|
633
633
|
locale: ctx.locale,
|
|
634
634
|
timeoutMs: ctx.timeoutMs,
|
|
635
|
-
userAgent: (0, import_core3.buildUserAgent)("wport-cli", "0.
|
|
635
|
+
userAgent: (0, import_core3.buildUserAgent)("wport-cli", "0.10.1"),
|
|
636
636
|
source: CLI_SOURCE
|
|
637
637
|
});
|
|
638
638
|
if (flags.batch) {
|
|
@@ -1073,7 +1073,7 @@ async function oauthPost(opts, path, body) {
|
|
|
1073
1073
|
method: "POST",
|
|
1074
1074
|
headers: {
|
|
1075
1075
|
"Accept-Language": opts.locale,
|
|
1076
|
-
"User-Agent": (0, import_core5.buildUserAgent)("wport-cli", "0.
|
|
1076
|
+
"User-Agent": (0, import_core5.buildUserAgent)("wport-cli", "0.10.1"),
|
|
1077
1077
|
"X-Source": CLI_SOURCE,
|
|
1078
1078
|
Accept: "application/json",
|
|
1079
1079
|
"Content-Type": "application/json"
|
|
@@ -1156,7 +1156,7 @@ function registerDoctorCommand(program2) {
|
|
|
1156
1156
|
}
|
|
1157
1157
|
async function runDoctor(ctx) {
|
|
1158
1158
|
const line = (s = "") => process.stdout.write(s + "\n");
|
|
1159
|
-
line(`wport-cli ${"0.
|
|
1159
|
+
line(`wport-cli ${"0.10.1"}`);
|
|
1160
1160
|
line(` bundled schema fingerprint: ${"839e8a891dfb"}`);
|
|
1161
1161
|
line("");
|
|
1162
1162
|
line("Resolved configuration:");
|
|
@@ -1216,7 +1216,7 @@ async function probeServer(ctx, line) {
|
|
|
1216
1216
|
baseUrl: ctx.baseUrl,
|
|
1217
1217
|
locale: ctx.locale,
|
|
1218
1218
|
timeoutMs: ctx.timeoutMs,
|
|
1219
|
-
userAgent: (0, import_core7.buildUserAgent)("wport-cli", "0.
|
|
1219
|
+
userAgent: (0, import_core7.buildUserAgent)("wport-cli", "0.10.1"),
|
|
1220
1220
|
source: CLI_SOURCE
|
|
1221
1221
|
});
|
|
1222
1222
|
const { response } = await client.GET("/api/jobs/search", { params: { query: { pageSize: 1 } } });
|
|
@@ -1246,11 +1246,61 @@ async function probeAuthServer(ctx, line) {
|
|
|
1246
1246
|
var import_core8 = require("@wport/core");
|
|
1247
1247
|
var transport = __toESM(require("@wport/core"));
|
|
1248
1248
|
function withUserAgent(opts) {
|
|
1249
|
-
return { ...opts, userAgent: (0, import_core8.buildUserAgent)("wport-cli", "0.
|
|
1249
|
+
return { ...opts, userAgent: (0, import_core8.buildUserAgent)("wport-cli", "0.10.1"), source: CLI_SOURCE };
|
|
1250
|
+
}
|
|
1251
|
+
function extractErrorCodeBody(body) {
|
|
1252
|
+
if (!body || typeof body !== "object") return void 0;
|
|
1253
|
+
const b = body;
|
|
1254
|
+
const code = b.error_code;
|
|
1255
|
+
if (code !== "block_max_exceeded" && code !== "unsupported_video_provider" && code !== "block_item_forbidden" && code !== "profile_revision_conflict" && code !== "profile_revision_required") {
|
|
1256
|
+
return void 0;
|
|
1257
|
+
}
|
|
1258
|
+
return {
|
|
1259
|
+
error_code: code,
|
|
1260
|
+
block: typeof b.block === "string" ? b.block : void 0,
|
|
1261
|
+
limit: typeof b.limit === "number" ? b.limit : void 0,
|
|
1262
|
+
current_revision: typeof b.current_revision === "string" ? b.current_revision : void 0
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
function decorateByErrorCode(base, err, info) {
|
|
1266
|
+
switch (info.error_code) {
|
|
1267
|
+
case "block_max_exceeded":
|
|
1268
|
+
return new import_core8.WportHttpError(
|
|
1269
|
+
`${base} \u2014 Block "${info.block ?? "unknown"}" exceeds its item limit` + (info.limit !== void 0 ? ` (max ${info.limit})` : "") + ". Run `wport enterprise company view --output json` to see the current items before replacing.",
|
|
1270
|
+
err.status,
|
|
1271
|
+
err.body
|
|
1272
|
+
);
|
|
1273
|
+
case "unsupported_video_provider":
|
|
1274
|
+
return new import_core8.WportHttpError(
|
|
1275
|
+
`${base} \u2014 Unsupported video URL. Accepted forms: https://www.youtube.com/watch?v=<id>, https://youtu.be/<id>, https://vimeo.com/<id>, https://player.vimeo.com/video/<id>.`,
|
|
1276
|
+
err.status,
|
|
1277
|
+
err.body
|
|
1278
|
+
);
|
|
1279
|
+
case "block_item_forbidden":
|
|
1280
|
+
return new import_core8.WportHttpError(
|
|
1281
|
+
`${base} \u2014 This enc_id (block "${info.block ?? "unknown"}") does not belong to your company or no longer exists. Run \`wport enterprise company view\` to get the latest enc_id list.`,
|
|
1282
|
+
err.status,
|
|
1283
|
+
err.body
|
|
1284
|
+
);
|
|
1285
|
+
case "profile_revision_conflict":
|
|
1286
|
+
return new import_core8.WportHttpError(
|
|
1287
|
+
`${base} \u2014 Block "${info.block ?? "unknown"}" changed since you last read it` + (info.current_revision ? ` (current revision: ${info.current_revision})` : "") + ". This CLI will not auto-retry: re-run `wport enterprise company view` to see the latest state, then confirm again.",
|
|
1288
|
+
err.status,
|
|
1289
|
+
err.body
|
|
1290
|
+
);
|
|
1291
|
+
case "profile_revision_required":
|
|
1292
|
+
return new import_core8.WportHttpError(
|
|
1293
|
+
`${base} \u2014 This request needs an If-Match revision (block "${info.block ?? "unknown"}") and none was recognized. This usually means the CLI is out of date \u2014 upgrade it, or re-run \`wport enterprise company view\` to fetch a fresh revision before retrying.`,
|
|
1294
|
+
err.status,
|
|
1295
|
+
err.body
|
|
1296
|
+
);
|
|
1297
|
+
}
|
|
1250
1298
|
}
|
|
1251
1299
|
function decorateEnterpriseError(err) {
|
|
1252
1300
|
if (!(err instanceof import_core8.WportHttpError)) return err;
|
|
1253
1301
|
const base = err.message;
|
|
1302
|
+
const errorCodeInfo = extractErrorCodeBody(err.body);
|
|
1303
|
+
if (errorCodeInfo) return decorateByErrorCode(base, err, errorCodeInfo);
|
|
1254
1304
|
if (err.status === 401) {
|
|
1255
1305
|
return new import_core8.WportHttpError(
|
|
1256
1306
|
`${base} \u2014 If your key has expired, rotate it in place: \`wport enterprise keys rotate <enc_id>\` (an expired key is still accepted for rotate). If it was revoked or is incorrect, obtain a valid key and run \`wport enterprise login\`.`,
|
|
@@ -1311,6 +1361,9 @@ function enterprisePost2(opts, path, body, extra) {
|
|
|
1311
1361
|
function enterprisePatch2(opts, path, body, extra) {
|
|
1312
1362
|
return wrap(transport.enterprisePatch(withUserAgent(opts), path, body, extra));
|
|
1313
1363
|
}
|
|
1364
|
+
function enterprisePut2(opts, path, body, extra) {
|
|
1365
|
+
return wrap(transport.enterprisePut(withUserAgent(opts), path, body, extra));
|
|
1366
|
+
}
|
|
1314
1367
|
function enterpriseDelete2(opts, path, extra) {
|
|
1315
1368
|
return wrap(transport.enterpriseDelete(withUserAgent(opts), path, extra));
|
|
1316
1369
|
}
|
|
@@ -1408,10 +1461,16 @@ async function runUsage(ctx, apiKey) {
|
|
|
1408
1461
|
const rate = usage.rate_limit ?? {};
|
|
1409
1462
|
const lines = [
|
|
1410
1463
|
`period: ${usage.period ?? "\u2014"}`,
|
|
1411
|
-
`monthly quota: ${num(quota.used)} / ${num(quota.limit)} used (${num(quota.remaining)} remaining)`,
|
|
1464
|
+
`monthly quota: ${num(quota.used)} / ${num(quota.limit)} calls used (${num(quota.remaining)} remaining)`,
|
|
1412
1465
|
`rate limit: ${num(rate.limit)} requests / ${num(rate.window_seconds)}s per key`
|
|
1413
1466
|
];
|
|
1414
1467
|
process.stdout.write(lines.join("\n") + "\n");
|
|
1468
|
+
process.stdout.write(
|
|
1469
|
+
dim(
|
|
1470
|
+
"Monthly quota meters every authenticated API call; whoami/usage and key rotate are exempt.",
|
|
1471
|
+
ctx.color
|
|
1472
|
+
) + "\n"
|
|
1473
|
+
);
|
|
1415
1474
|
process.stdout.write(
|
|
1416
1475
|
dim("Live per-window rate-limit headroom is reported via response headers on write requests.", ctx.color) + "\n"
|
|
1417
1476
|
);
|
|
@@ -1921,6 +1980,15 @@ function renderDetailLines2(company) {
|
|
|
1921
1980
|
}
|
|
1922
1981
|
return lines;
|
|
1923
1982
|
}
|
|
1983
|
+
var BLOCK_SUMMARY_FIELDS = ["pain_points", "awards", "milestones", "qa_items", "video_links"];
|
|
1984
|
+
function renderBlockSummaryLines(company) {
|
|
1985
|
+
const width = Math.max(...BLOCK_SUMMARY_FIELDS.map((f) => f.length)) + 3;
|
|
1986
|
+
return BLOCK_SUMMARY_FIELDS.map((field) => {
|
|
1987
|
+
const value = company[field];
|
|
1988
|
+
const count = Array.isArray(value) ? value.length : 0;
|
|
1989
|
+
return `${(field + ":").padEnd(width)}${count}`;
|
|
1990
|
+
});
|
|
1991
|
+
}
|
|
1924
1992
|
async function runCompanyView(ctx, apiKey, flags) {
|
|
1925
1993
|
const { body } = await enterpriseGet2(
|
|
1926
1994
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
@@ -1935,7 +2003,8 @@ async function runCompanyView(ctx, apiKey, flags) {
|
|
|
1935
2003
|
printJson(company);
|
|
1936
2004
|
return;
|
|
1937
2005
|
}
|
|
1938
|
-
|
|
2006
|
+
const lines = [...renderDetailLines2(company), "", ...renderBlockSummaryLines(company)];
|
|
2007
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
1939
2008
|
}
|
|
1940
2009
|
function registerEnterpriseCompanyView(parent) {
|
|
1941
2010
|
parent.command("view").description("View your company information").option("--fields <list>", "output selected fields as JSON (comma-separated dotted paths)").action(async (flags, command) => {
|
|
@@ -1950,6 +2019,52 @@ function registerEnterpriseCompanyView(parent) {
|
|
|
1950
2019
|
var import_node_crypto5 = require("crypto");
|
|
1951
2020
|
var import_core19 = require("@wport/core");
|
|
1952
2021
|
|
|
2022
|
+
// src/commands/enterprise/company/block-replace-shared.ts
|
|
2023
|
+
function assertValidSubmittedItems(value, label) {
|
|
2024
|
+
if (!Array.isArray(value)) {
|
|
2025
|
+
throw new InvalidArgumentError(
|
|
2026
|
+
`"${label}" must be a JSON array, got ${value === null ? "null" : typeof value}`
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
2029
|
+
value.forEach((item, index) => {
|
|
2030
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
2031
|
+
throw new InvalidArgumentError(
|
|
2032
|
+
`"${label}[${index}]" must be a JSON object, got ` + (item === null ? "null" : Array.isArray(item) ? "an array" : typeof item)
|
|
2033
|
+
);
|
|
2034
|
+
}
|
|
2035
|
+
});
|
|
2036
|
+
return value;
|
|
2037
|
+
}
|
|
2038
|
+
function previewDeletions(current, submitted, summarize) {
|
|
2039
|
+
const submittedIds = new Set(
|
|
2040
|
+
submitted.filter((i) => typeof i.enc_id === "string").map((i) => i.enc_id)
|
|
2041
|
+
);
|
|
2042
|
+
return current.filter((item) => !submittedIds.has(item.enc_id)).map((item) => ({ enc_id: item.enc_id, summary: summarize(item) }));
|
|
2043
|
+
}
|
|
2044
|
+
function enforceDeletionConfirmation(label, deletions, confirm, color) {
|
|
2045
|
+
if (deletions.length === 0) return;
|
|
2046
|
+
printWarn(
|
|
2047
|
+
`This replace will delete ${deletions.length} existing "${label}" item(s): ` + deletions.map((d) => `${d.enc_id} (${d.summary || "untitled"})`).join("; "),
|
|
2048
|
+
color
|
|
2049
|
+
);
|
|
2050
|
+
if (!confirm) {
|
|
2051
|
+
throw new InvalidArgumentError(
|
|
2052
|
+
`Refusing to replace "${label}" without --confirm: ${deletions.length} existing item(s) would be deleted (see the warning above for the enc_id list). Re-run with --confirm to proceed.`
|
|
2053
|
+
);
|
|
2054
|
+
}
|
|
2055
|
+
}
|
|
2056
|
+
function summarizeItemsDiff(before, after) {
|
|
2057
|
+
const beforeIds = new Set(before.map((i) => i.enc_id));
|
|
2058
|
+
const afterIds = new Set(after.map((i) => i.enc_id));
|
|
2059
|
+
const added = after.filter((i) => !beforeIds.has(i.enc_id)).map((i) => i.enc_id);
|
|
2060
|
+
const removed = before.filter((i) => !afterIds.has(i.enc_id)).map((i) => i.enc_id);
|
|
2061
|
+
const parts = [];
|
|
2062
|
+
if (added.length > 0) parts.push(`added since your read: ${added.join(", ")}`);
|
|
2063
|
+
if (removed.length > 0) parts.push(`removed since your read: ${removed.join(", ")}`);
|
|
2064
|
+
if (parts.length === 0) parts.push("item content or order changed (enc_id set unchanged)");
|
|
2065
|
+
return parts.join("; ");
|
|
2066
|
+
}
|
|
2067
|
+
|
|
1953
2068
|
// src/commands/enterprise/company/types.ts
|
|
1954
2069
|
var BASIC_FIELDS = [
|
|
1955
2070
|
"name",
|
|
@@ -1961,24 +2076,25 @@ var BASIC_FIELDS = [
|
|
|
1961
2076
|
"capital_show_status",
|
|
1962
2077
|
"website",
|
|
1963
2078
|
"area_code",
|
|
1964
|
-
"address"
|
|
2079
|
+
"address",
|
|
2080
|
+
"representative_name",
|
|
2081
|
+
"establishment_date",
|
|
2082
|
+
"directors",
|
|
2083
|
+
"is_representative_visible",
|
|
2084
|
+
"is_establishment_date_visible",
|
|
2085
|
+
"is_directors_visible"
|
|
1965
2086
|
];
|
|
1966
|
-
var DESCRIPTION_FIELDS = ["description", "products_services", "latest_news"];
|
|
2087
|
+
var DESCRIPTION_FIELDS = ["description", "products_services", "latest_news", "video_links"];
|
|
1967
2088
|
var FORBIDDEN_FIELDS = [
|
|
1968
2089
|
"uniform_number",
|
|
2090
|
+
"is_uniform_number_visible",
|
|
1969
2091
|
"banner_url",
|
|
1970
2092
|
"photo_1",
|
|
1971
2093
|
"photo_2",
|
|
1972
2094
|
"photo_3",
|
|
1973
2095
|
"video_1",
|
|
1974
2096
|
"video_2",
|
|
1975
|
-
"video_3"
|
|
1976
|
-
"foundation_date",
|
|
1977
|
-
"representative",
|
|
1978
|
-
"directors",
|
|
1979
|
-
"milestones",
|
|
1980
|
-
"awards",
|
|
1981
|
-
"qa"
|
|
2097
|
+
"video_3"
|
|
1982
2098
|
];
|
|
1983
2099
|
|
|
1984
2100
|
// src/commands/enterprise/company/update.ts
|
|
@@ -2046,12 +2162,25 @@ async function buildCompanyUpdatePayloads(input, ctx, apiKey) {
|
|
|
2046
2162
|
}
|
|
2047
2163
|
let descriptions = null;
|
|
2048
2164
|
if (inputHasDescriptionField) {
|
|
2049
|
-
|
|
2165
|
+
const partial = {};
|
|
2050
2166
|
for (const field of DESCRIPTION_FIELDS) {
|
|
2051
|
-
if (field in input)
|
|
2167
|
+
if (field in input) partial[field] = input[field];
|
|
2052
2168
|
}
|
|
2169
|
+
descriptions = partial;
|
|
2053
2170
|
}
|
|
2054
|
-
|
|
2171
|
+
let videoLinksRevision;
|
|
2172
|
+
let currentVideoLinks;
|
|
2173
|
+
if ("video_links" in input) {
|
|
2174
|
+
currentVideoLinks = current.video_links ?? [];
|
|
2175
|
+
videoLinksRevision = current.block_revisions?.video_links;
|
|
2176
|
+
if (!videoLinksRevision) {
|
|
2177
|
+
throw new CliError(
|
|
2178
|
+
"Backend contract appears broken: GET /company response is missing block_revisions.video_links",
|
|
2179
|
+
ExitCode.ServerOrNetworkError
|
|
2180
|
+
);
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
return { basic, descriptions, videoLinksRevision, currentVideoLinks };
|
|
2055
2184
|
}
|
|
2056
2185
|
function isDescriptionsPartialFailureBody(body) {
|
|
2057
2186
|
return !!body && typeof body === "object" && Array.isArray(body.updated_sections) && typeof body.failed_section === "string";
|
|
@@ -2076,12 +2205,21 @@ function resolveUpdateIdempotencyKeys(needsBasic, needsDescriptions, flags) {
|
|
|
2076
2205
|
descriptionsKey: needsDescriptions ? flags.descriptionsIdempotencyKey ?? flags.idempotencyKey ?? (0, import_node_crypto5.randomUUID)() : void 0
|
|
2077
2206
|
};
|
|
2078
2207
|
}
|
|
2079
|
-
async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options = {}) {
|
|
2208
|
+
async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options = {}, confirm = false) {
|
|
2080
2209
|
const input = readJsonObject(source, options);
|
|
2081
2210
|
const needsBasic = BASIC_FIELDS.some((f) => f in input);
|
|
2082
2211
|
const needsDescriptions = DESCRIPTION_FIELDS.some((f) => f in input);
|
|
2212
|
+
const needsVideoLinks = "video_links" in input;
|
|
2213
|
+
if (needsVideoLinks) {
|
|
2214
|
+
assertValidSubmittedItems(input.video_links, "video_links");
|
|
2215
|
+
}
|
|
2083
2216
|
const { basicKey, descriptionsKey } = resolveUpdateIdempotencyKeys(needsBasic, needsDescriptions, idempotencyFlags);
|
|
2084
2217
|
const payloads = await buildCompanyUpdatePayloads(input, ctx, apiKey);
|
|
2218
|
+
if (needsVideoLinks) {
|
|
2219
|
+
const submitted = payloads.descriptions?.video_links ?? [];
|
|
2220
|
+
const deletions = previewDeletions(payloads.currentVideoLinks ?? [], submitted, (item) => String(item.url ?? ""));
|
|
2221
|
+
enforceDeletionConfirmation("video_links", deletions, confirm, ctx.color ?? false);
|
|
2222
|
+
}
|
|
2085
2223
|
const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
|
|
2086
2224
|
let basicResultCompany;
|
|
2087
2225
|
if (needsBasic) {
|
|
@@ -2099,11 +2237,43 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
|
|
|
2099
2237
|
requestOpts,
|
|
2100
2238
|
"/company/descriptions",
|
|
2101
2239
|
payloads.descriptions,
|
|
2102
|
-
{
|
|
2240
|
+
{
|
|
2241
|
+
idempotencyKey: descriptionsKey,
|
|
2242
|
+
// 只有輸入帶 video_links 時才附 If-Match——後端只在這種情況要求它(spec §3.2.2);
|
|
2243
|
+
// 沒帶 video_links 時絕不能傳這個 key(用條件式 spread,不是傳 `undefined`)。
|
|
2244
|
+
...needsVideoLinks ? { ifMatch: payloads.videoLinksRevision } : {}
|
|
2245
|
+
}
|
|
2103
2246
|
);
|
|
2104
2247
|
const result = (0, import_core19.unwrapDataResponse)(body);
|
|
2105
2248
|
printCompanyResult(result.company, ctx.format);
|
|
2106
2249
|
} catch (err) {
|
|
2250
|
+
if (needsVideoLinks && err instanceof ServerClientHttpError && err.status === 409) {
|
|
2251
|
+
const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2252
|
+
const freshCurrent = (0, import_core19.unwrapDataResponse)(freshBody);
|
|
2253
|
+
const freshVideoLinks = freshCurrent.video_links ?? [];
|
|
2254
|
+
const diff = summarizeItemsDiff(payloads.currentVideoLinks ?? [], freshVideoLinks);
|
|
2255
|
+
const partialBody = isDescriptionsPartialFailureBody(err.body) ? err.body : void 0;
|
|
2256
|
+
printWarn(`Server state for "video_links" changed since your read: ${diff}.`, ctx.color ?? false);
|
|
2257
|
+
const descriptionsError = {
|
|
2258
|
+
updated_sections: partialBody?.updated_sections ?? [],
|
|
2259
|
+
failed_section: partialBody?.failed_section ?? "video_links",
|
|
2260
|
+
video_links_diff: diff
|
|
2261
|
+
};
|
|
2262
|
+
if (ctx.format === "json") {
|
|
2263
|
+
printJson(
|
|
2264
|
+
needsBasic ? { basic_updated: true, basic_company: basicResultCompany, descriptions_error: descriptionsError } : { descriptions_error: descriptionsError }
|
|
2265
|
+
);
|
|
2266
|
+
} else {
|
|
2267
|
+
if (needsBasic) process.stdout.write("Basic company info was updated successfully.\n");
|
|
2268
|
+
process.stdout.write(
|
|
2269
|
+
`Updated sections before failure: ${descriptionsError.updated_sections.join(", ")}; failed section: ${descriptionsError.failed_section}
|
|
2270
|
+
`
|
|
2271
|
+
);
|
|
2272
|
+
}
|
|
2273
|
+
throw new InvalidArgumentError(
|
|
2274
|
+
`Refusing to auto-retry "video_links" update after a stale revision conflict (409). ${diff}. Re-run \`wport enterprise company view\` and retry \`company update --confirm\` against the current state.`
|
|
2275
|
+
);
|
|
2276
|
+
}
|
|
2107
2277
|
if (!needsBasic) {
|
|
2108
2278
|
throw err;
|
|
2109
2279
|
}
|
|
@@ -2134,10 +2304,13 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
|
|
|
2134
2304
|
}
|
|
2135
2305
|
function registerEnterpriseCompanyUpdate(parent) {
|
|
2136
2306
|
parent.command("update").description(
|
|
2137
|
-
"Update your company basic info and/or descriptions from a JSON file (uniform_number is read-only and cannot be changed via this command)"
|
|
2307
|
+
"Update your company basic info and/or descriptions from a JSON file (uniform_number is read-only and cannot be changed via this command). is_representative_visible / is_establishment_date_visible / is_directors_visible default to 0 (hidden) when not set. video_links (in descriptions) uses optimistic locking (If-Match, handled automatically from your latest `company view`); removing any existing video requires --confirm."
|
|
2138
2308
|
).requiredOption("--file <path>", 'path to a partial JSON company body, or "-" for stdin').option("--idempotency-key <key>", "single-section update only: reuse across retries (default: a fresh UUID)").option("--basic-idempotency-key <key>", "two-section update: idempotency key for PATCH /company/basic").option(
|
|
2139
2309
|
"--descriptions-idempotency-key <key>",
|
|
2140
2310
|
"two-section update: idempotency key for PATCH /company/descriptions"
|
|
2311
|
+
).option(
|
|
2312
|
+
"--confirm",
|
|
2313
|
+
"confirm deletion of existing video_links items not present in the input (required when video_links is provided and would remove any existing item)"
|
|
2141
2314
|
).action(async (flags, command) => {
|
|
2142
2315
|
const ctx = resolveContext(command);
|
|
2143
2316
|
const globals = command.optsWithGlobals();
|
|
@@ -2151,7 +2324,8 @@ function registerEnterpriseCompanyUpdate(parent) {
|
|
|
2151
2324
|
basicIdempotencyKey: flags.basicIdempotencyKey,
|
|
2152
2325
|
descriptionsIdempotencyKey: flags.descriptionsIdempotencyKey
|
|
2153
2326
|
},
|
|
2154
|
-
{ timeoutMs: ctx.timeoutMs }
|
|
2327
|
+
{ timeoutMs: ctx.timeoutMs },
|
|
2328
|
+
flags.confirm === true
|
|
2155
2329
|
);
|
|
2156
2330
|
});
|
|
2157
2331
|
}
|
|
@@ -2247,16 +2421,122 @@ function registerEnterpriseCompanyLogo(parent) {
|
|
|
2247
2421
|
});
|
|
2248
2422
|
}
|
|
2249
2423
|
|
|
2424
|
+
// src/commands/enterprise/company/replace.ts
|
|
2425
|
+
var import_node_crypto7 = require("crypto");
|
|
2426
|
+
var import_core21 = require("@wport/core");
|
|
2427
|
+
var REPLACE_SECTIONS = ["pain-points", "awards", "milestones", "qa-items"];
|
|
2428
|
+
var SECTION_CONFIG = {
|
|
2429
|
+
"pain-points": {
|
|
2430
|
+
path: "/company/pain-points",
|
|
2431
|
+
dataKey: "pain_points",
|
|
2432
|
+
summarize: (i) => String(i.title ?? "")
|
|
2433
|
+
},
|
|
2434
|
+
awards: {
|
|
2435
|
+
path: "/company/awards",
|
|
2436
|
+
dataKey: "awards",
|
|
2437
|
+
summarize: (i) => String(i.name ?? "")
|
|
2438
|
+
},
|
|
2439
|
+
milestones: {
|
|
2440
|
+
path: "/company/milestones",
|
|
2441
|
+
dataKey: "milestones",
|
|
2442
|
+
summarize: (i) => String(i.title ?? "")
|
|
2443
|
+
},
|
|
2444
|
+
"qa-items": {
|
|
2445
|
+
path: "/company/qa-items",
|
|
2446
|
+
dataKey: "qa_items",
|
|
2447
|
+
summarize: (i) => String(i.question ?? "")
|
|
2448
|
+
}
|
|
2449
|
+
};
|
|
2450
|
+
function isReplaceSection(v) {
|
|
2451
|
+
return REPLACE_SECTIONS.includes(v);
|
|
2452
|
+
}
|
|
2453
|
+
function printReplaceResult(result, config, format, color) {
|
|
2454
|
+
if (format === "json") {
|
|
2455
|
+
printJson(result);
|
|
2456
|
+
return;
|
|
2457
|
+
}
|
|
2458
|
+
printTable(
|
|
2459
|
+
result.items ?? [],
|
|
2460
|
+
[
|
|
2461
|
+
{ header: "enc_id", value: (r) => String(r.enc_id ?? "") },
|
|
2462
|
+
{ header: "summary", value: (r) => config.summarize(r) }
|
|
2463
|
+
],
|
|
2464
|
+
color
|
|
2465
|
+
);
|
|
2466
|
+
process.stdout.write(`revision: ${result.revision ?? ""}
|
|
2467
|
+
`);
|
|
2468
|
+
}
|
|
2469
|
+
async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempotencyKey, options = {}) {
|
|
2470
|
+
if (!isReplaceSection(section)) {
|
|
2471
|
+
throw new InvalidArgumentError(`Invalid section "${section}". Allowed: ${REPLACE_SECTIONS.join(", ")}`);
|
|
2472
|
+
}
|
|
2473
|
+
const config = SECTION_CONFIG[section];
|
|
2474
|
+
const input = readJsonObject(source, options);
|
|
2475
|
+
if (!Array.isArray(input.items)) {
|
|
2476
|
+
throw new InvalidArgumentError('Input must be a JSON object of the form { "items": [...] }');
|
|
2477
|
+
}
|
|
2478
|
+
const items = assertValidSubmittedItems(input.items, "items");
|
|
2479
|
+
const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
|
|
2480
|
+
const { body: getBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2481
|
+
const current = (0, import_core21.unwrapDataResponse)(getBody);
|
|
2482
|
+
const currentItems = current[config.dataKey] ?? [];
|
|
2483
|
+
const revision = current.block_revisions?.[config.dataKey];
|
|
2484
|
+
if (!revision) {
|
|
2485
|
+
throw new CliError(
|
|
2486
|
+
`Backend contract appears broken: GET /company response is missing block_revisions.${config.dataKey}`,
|
|
2487
|
+
ExitCode.ServerOrNetworkError
|
|
2488
|
+
);
|
|
2489
|
+
}
|
|
2490
|
+
const deletions = previewDeletions(currentItems, items, config.summarize);
|
|
2491
|
+
enforceDeletionConfirmation(section, deletions, confirm, ctx.color);
|
|
2492
|
+
try {
|
|
2493
|
+
const { body } = await enterprisePut2(requestOpts, config.path, { items }, { idempotencyKey, ifMatch: revision });
|
|
2494
|
+
const result = (0, import_core21.unwrapDataResponse)(body);
|
|
2495
|
+
printReplaceResult(result, config, ctx.format, ctx.color);
|
|
2496
|
+
} catch (err) {
|
|
2497
|
+
if (err instanceof import_core21.WportHttpError && err.status === 409) {
|
|
2498
|
+
const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2499
|
+
const freshCurrent = (0, import_core21.unwrapDataResponse)(freshBody);
|
|
2500
|
+
const freshItems = freshCurrent[config.dataKey] ?? [];
|
|
2501
|
+
const diff = summarizeItemsDiff(currentItems, freshItems);
|
|
2502
|
+
printWarn(`Server state for "${section}" changed since your read: ${diff}.`, ctx.color);
|
|
2503
|
+
throw new InvalidArgumentError(
|
|
2504
|
+
`Refusing to auto-retry "${section}" replace after a stale revision conflict (409). ${diff}. Re-run \`wport enterprise company view\` and retry \`company replace --confirm\` against the current state.`
|
|
2505
|
+
);
|
|
2506
|
+
}
|
|
2507
|
+
throw err;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
function registerEnterpriseCompanyReplace(parent) {
|
|
2511
|
+
parent.command("replace <section>").description(
|
|
2512
|
+
`Replace an entire company profile block from a JSON file. <section> is one of: ${REPLACE_SECTIONS.join("|")}. This is a full replacement, not an add/update: any existing item not listed in the input is deleted.`
|
|
2513
|
+
).requiredOption("--file <path>", 'path to a JSON body { "items": [...] }, or "-" for stdin').option("--confirm", "confirm deletion of existing items that are not present in the input").option("--idempotency-key <key>", "reuse across retries (default: a fresh UUID)").action(async (section, flags, command) => {
|
|
2514
|
+
const ctx = resolveContext(command);
|
|
2515
|
+
const globals = command.optsWithGlobals();
|
|
2516
|
+
const { key } = resolveApiKey(globals.apiKey);
|
|
2517
|
+
await runCompanyReplace(
|
|
2518
|
+
ctx,
|
|
2519
|
+
key,
|
|
2520
|
+
section,
|
|
2521
|
+
flags.file,
|
|
2522
|
+
flags.confirm === true,
|
|
2523
|
+
flags.idempotencyKey ?? (0, import_node_crypto7.randomUUID)(),
|
|
2524
|
+
{ timeoutMs: ctx.timeoutMs }
|
|
2525
|
+
);
|
|
2526
|
+
});
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2250
2529
|
// src/commands/enterprise/company/index.ts
|
|
2251
2530
|
function registerEnterpriseCompanyCommand(parent) {
|
|
2252
2531
|
const company = parent.command("company").description("View and manage your company information");
|
|
2253
2532
|
registerEnterpriseCompanyView(company);
|
|
2254
2533
|
registerEnterpriseCompanyUpdate(company);
|
|
2255
2534
|
registerEnterpriseCompanyLogo(company);
|
|
2535
|
+
registerEnterpriseCompanyReplace(company);
|
|
2256
2536
|
}
|
|
2257
2537
|
|
|
2258
2538
|
// src/commands/enterprise/talents/list.ts
|
|
2259
|
-
var
|
|
2539
|
+
var import_core22 = require("@wport/core");
|
|
2260
2540
|
var DEFAULT_PAGE_SIZE = 20;
|
|
2261
2541
|
var MINIMAL_LIST_FIELDS2 = ["enc_resume_id", "candidate_name", "applied_job_title", "applied_at"];
|
|
2262
2542
|
function formatDate4(value) {
|
|
@@ -2279,7 +2559,7 @@ async function runEnterpriseTalentsList(ctx, apiKey, flags) {
|
|
|
2279
2559
|
pageSize: flags.pageSize ?? DEFAULT_PAGE_SIZE
|
|
2280
2560
|
}
|
|
2281
2561
|
);
|
|
2282
|
-
const paged = (0,
|
|
2562
|
+
const paged = (0, import_core22.asPaginatedBody)(body);
|
|
2283
2563
|
const projection = flags.minimal ? MINIMAL_LIST_FIELDS2 : flags.fields ? parseFieldsList(flags.fields) : void 0;
|
|
2284
2564
|
if (projection || ctx.format === "json") {
|
|
2285
2565
|
printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
|
|
@@ -2312,7 +2592,7 @@ function registerEnterpriseTalentsList(parent) {
|
|
|
2312
2592
|
}
|
|
2313
2593
|
|
|
2314
2594
|
// src/commands/enterprise/talents/view.ts
|
|
2315
|
-
var
|
|
2595
|
+
var import_core23 = require("@wport/core");
|
|
2316
2596
|
async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
|
|
2317
2597
|
const trimmed = encResumeId.trim();
|
|
2318
2598
|
if (!trimmed) {
|
|
@@ -2322,7 +2602,7 @@ async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
|
|
|
2322
2602
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
2323
2603
|
`/talents/${encodeURIComponent(trimmed)}`
|
|
2324
2604
|
);
|
|
2325
|
-
const resume = (0,
|
|
2605
|
+
const resume = (0, import_core23.unwrapDataResponse)(body);
|
|
2326
2606
|
if (flags.fields) {
|
|
2327
2607
|
printJson(pickPaths(resume, parseFieldsList(flags.fields)));
|
|
2328
2608
|
return;
|
|
@@ -2339,8 +2619,8 @@ function registerEnterpriseTalentsView(parent) {
|
|
|
2339
2619
|
}
|
|
2340
2620
|
|
|
2341
2621
|
// src/commands/enterprise/talents/respond.ts
|
|
2342
|
-
var
|
|
2343
|
-
var
|
|
2622
|
+
var import_node_crypto8 = require("crypto");
|
|
2623
|
+
var import_core24 = require("@wport/core");
|
|
2344
2624
|
function resolveRespondBody(flags, options = {}) {
|
|
2345
2625
|
const hasBody = flags.body !== void 0;
|
|
2346
2626
|
const hasBodyFile = flags.bodyFile !== void 0;
|
|
@@ -2372,7 +2652,7 @@ async function runEnterpriseTalentsRespond(ctx, apiKey, encResumeId, flags, idem
|
|
|
2372
2652
|
payload,
|
|
2373
2653
|
{ idempotencyKey }
|
|
2374
2654
|
);
|
|
2375
|
-
const result = (0,
|
|
2655
|
+
const result = (0, import_core24.unwrapDataResponse)(respBody);
|
|
2376
2656
|
if (ctx.format === "json") {
|
|
2377
2657
|
printJson(result);
|
|
2378
2658
|
return;
|
|
@@ -2385,7 +2665,7 @@ function registerEnterpriseTalentsRespond(parent) {
|
|
|
2385
2665
|
const ctx = resolveContext(command);
|
|
2386
2666
|
const globals = command.optsWithGlobals();
|
|
2387
2667
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2388
|
-
await runEnterpriseTalentsRespond(ctx, key, encResumeId, flags, flags.idempotencyKey ?? (0,
|
|
2668
|
+
await runEnterpriseTalentsRespond(ctx, key, encResumeId, flags, flags.idempotencyKey ?? (0, import_node_crypto8.randomUUID)());
|
|
2389
2669
|
});
|
|
2390
2670
|
}
|
|
2391
2671
|
|
|
@@ -2400,8 +2680,8 @@ function registerEnterpriseTalentsCommand(parent) {
|
|
|
2400
2680
|
}
|
|
2401
2681
|
|
|
2402
2682
|
// src/commands/enterprise/campaigns/create.ts
|
|
2403
|
-
var
|
|
2404
|
-
var
|
|
2683
|
+
var import_node_crypto9 = require("crypto");
|
|
2684
|
+
var import_core25 = require("@wport/core");
|
|
2405
2685
|
async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
|
|
2406
2686
|
const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
|
|
2407
2687
|
const { body } = await enterprisePost2(
|
|
@@ -2410,7 +2690,7 @@ async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
|
|
|
2410
2690
|
campaignBody,
|
|
2411
2691
|
{ idempotencyKey }
|
|
2412
2692
|
);
|
|
2413
|
-
const created = (0,
|
|
2693
|
+
const created = (0, import_core25.unwrapDataResponse)(body);
|
|
2414
2694
|
if (ctx.format === "json") {
|
|
2415
2695
|
printJson(created);
|
|
2416
2696
|
return;
|
|
@@ -2423,12 +2703,12 @@ function registerEnterpriseCampaignsCreate(parent) {
|
|
|
2423
2703
|
const ctx = resolveContext(command);
|
|
2424
2704
|
const globals = command.optsWithGlobals();
|
|
2425
2705
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2426
|
-
await runCampaignCreate(ctx, key, flags.file, flags.idempotencyKey ?? (0,
|
|
2706
|
+
await runCampaignCreate(ctx, key, flags.file, flags.idempotencyKey ?? (0, import_node_crypto9.randomUUID)());
|
|
2427
2707
|
});
|
|
2428
2708
|
}
|
|
2429
2709
|
|
|
2430
2710
|
// src/commands/enterprise/campaigns/list.ts
|
|
2431
|
-
var
|
|
2711
|
+
var import_core26 = require("@wport/core");
|
|
2432
2712
|
var STATUS_MAP2 = { open: 1, closed: 0 };
|
|
2433
2713
|
var MINIMAL_LIST_FIELDS3 = ["enc_id", "name", "status", "job_count"];
|
|
2434
2714
|
function mapStatusFlag2(raw) {
|
|
@@ -2458,7 +2738,7 @@ async function runEnterpriseCampaignsList(ctx, apiKey, flags) {
|
|
|
2458
2738
|
status: mapStatusFlag2(flags.status)
|
|
2459
2739
|
}
|
|
2460
2740
|
);
|
|
2461
|
-
const paged = (0,
|
|
2741
|
+
const paged = (0, import_core26.asPaginatedBody)(body);
|
|
2462
2742
|
const projection = flags.minimal ? MINIMAL_LIST_FIELDS3 : flags.fields ? parseFieldsList(flags.fields) : void 0;
|
|
2463
2743
|
if (projection || ctx.format === "json") {
|
|
2464
2744
|
printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
|
|
@@ -2490,8 +2770,8 @@ function registerEnterpriseCampaignsList(parent) {
|
|
|
2490
2770
|
}
|
|
2491
2771
|
|
|
2492
2772
|
// src/commands/enterprise/campaigns/lifecycle.ts
|
|
2493
|
-
var
|
|
2494
|
-
var
|
|
2773
|
+
var import_node_crypto10 = require("crypto");
|
|
2774
|
+
var import_core27 = require("@wport/core");
|
|
2495
2775
|
async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey) {
|
|
2496
2776
|
const trimmed = requireEncId(encId);
|
|
2497
2777
|
const { body } = await enterprisePatch2(
|
|
@@ -2500,7 +2780,7 @@ async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey)
|
|
|
2500
2780
|
{},
|
|
2501
2781
|
{ idempotencyKey }
|
|
2502
2782
|
);
|
|
2503
|
-
const result = (0,
|
|
2783
|
+
const result = (0, import_core27.unwrapDataResponse)(body);
|
|
2504
2784
|
if (ctx.format === "json") {
|
|
2505
2785
|
printJson(result);
|
|
2506
2786
|
return;
|
|
@@ -2513,20 +2793,20 @@ function registerEnterpriseCampaignsPublish(parent) {
|
|
|
2513
2793
|
parent.command("publish <enc_id>").description("Publish (activate) a recruitment campaign").option("--idempotency-key <key>", "reuse across retries (default: a fresh UUID)").action(async (encId, flags, command) => {
|
|
2514
2794
|
const ctx = resolveContext(command);
|
|
2515
2795
|
const { key } = resolveApiKey(command.optsWithGlobals().apiKey);
|
|
2516
|
-
await runCampaignTransition(ctx, key, encId, "publish", flags.idempotencyKey ?? (0,
|
|
2796
|
+
await runCampaignTransition(ctx, key, encId, "publish", flags.idempotencyKey ?? (0, import_node_crypto10.randomUUID)());
|
|
2517
2797
|
});
|
|
2518
2798
|
}
|
|
2519
2799
|
function registerEnterpriseCampaignsUnpublish(parent) {
|
|
2520
2800
|
parent.command("unpublish <enc_id>").description("Unpublish (deactivate) a recruitment campaign").option("--idempotency-key <key>", "reuse across retries (default: a fresh UUID)").action(async (encId, flags, command) => {
|
|
2521
2801
|
const ctx = resolveContext(command);
|
|
2522
2802
|
const { key } = resolveApiKey(command.optsWithGlobals().apiKey);
|
|
2523
|
-
await runCampaignTransition(ctx, key, encId, "unpublish", flags.idempotencyKey ?? (0,
|
|
2803
|
+
await runCampaignTransition(ctx, key, encId, "unpublish", flags.idempotencyKey ?? (0, import_node_crypto10.randomUUID)());
|
|
2524
2804
|
});
|
|
2525
2805
|
}
|
|
2526
2806
|
|
|
2527
2807
|
// src/commands/enterprise/campaigns/update.ts
|
|
2528
|
-
var
|
|
2529
|
-
var
|
|
2808
|
+
var import_node_crypto11 = require("crypto");
|
|
2809
|
+
var import_core28 = require("@wport/core");
|
|
2530
2810
|
async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
|
|
2531
2811
|
const trimmed = requireEncId(encId);
|
|
2532
2812
|
const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
|
|
@@ -2536,7 +2816,7 @@ async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
|
|
|
2536
2816
|
campaignBody,
|
|
2537
2817
|
{ idempotencyKey }
|
|
2538
2818
|
);
|
|
2539
|
-
const updated = (0,
|
|
2819
|
+
const updated = (0, import_core28.unwrapDataResponse)(body);
|
|
2540
2820
|
if (ctx.format === "json") {
|
|
2541
2821
|
printJson(updated);
|
|
2542
2822
|
return;
|
|
@@ -2549,12 +2829,12 @@ function registerEnterpriseCampaignsUpdate(parent) {
|
|
|
2549
2829
|
const ctx = resolveContext(command);
|
|
2550
2830
|
const globals = command.optsWithGlobals();
|
|
2551
2831
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2552
|
-
await runCampaignUpdate(ctx, key, encId, flags.file, flags.idempotencyKey ?? (0,
|
|
2832
|
+
await runCampaignUpdate(ctx, key, encId, flags.file, flags.idempotencyKey ?? (0, import_node_crypto11.randomUUID)());
|
|
2553
2833
|
});
|
|
2554
2834
|
}
|
|
2555
2835
|
|
|
2556
2836
|
// src/commands/enterprise/campaigns/view.ts
|
|
2557
|
-
var
|
|
2837
|
+
var import_core29 = require("@wport/core");
|
|
2558
2838
|
async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
|
|
2559
2839
|
const trimmed = encId.trim();
|
|
2560
2840
|
if (!trimmed) {
|
|
@@ -2564,7 +2844,7 @@ async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
|
|
|
2564
2844
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
2565
2845
|
`/campaigns/${encodeURIComponent(trimmed)}`
|
|
2566
2846
|
);
|
|
2567
|
-
const campaign = (0,
|
|
2847
|
+
const campaign = (0, import_core29.unwrapDataResponse)(body);
|
|
2568
2848
|
if (flags.fields) {
|
|
2569
2849
|
printJson(pickPaths(campaign, parseFieldsList(flags.fields)));
|
|
2570
2850
|
return;
|
|
@@ -2709,10 +2989,10 @@ function registerLoginCommand(program2) {
|
|
|
2709
2989
|
}
|
|
2710
2990
|
|
|
2711
2991
|
// src/commands/auth/whoami.ts
|
|
2712
|
-
var
|
|
2992
|
+
var import_core31 = require("@wport/core");
|
|
2713
2993
|
|
|
2714
2994
|
// src/lib/personal-client.ts
|
|
2715
|
-
var
|
|
2995
|
+
var import_core30 = require("@wport/core");
|
|
2716
2996
|
var EXPIRY_SKEW_MS = 3e4;
|
|
2717
2997
|
var NOT_LOGGED_IN_MESSAGE = "Not logged in. Run `wport login`.";
|
|
2718
2998
|
async function ensureFreshCredentials(opts) {
|
|
@@ -2741,7 +3021,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
|
|
|
2741
3021
|
const headers = {
|
|
2742
3022
|
Authorization: `Bearer ${accessToken}`,
|
|
2743
3023
|
"Accept-Language": opts.locale,
|
|
2744
|
-
"User-Agent": (0,
|
|
3024
|
+
"User-Agent": (0, import_core30.buildUserAgent)("wport-cli", "0.10.1"),
|
|
2745
3025
|
"X-Source": CLI_SOURCE,
|
|
2746
3026
|
Accept: "application/json"
|
|
2747
3027
|
};
|
|
@@ -2752,7 +3032,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
|
|
|
2752
3032
|
headers,
|
|
2753
3033
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
2754
3034
|
});
|
|
2755
|
-
const res = await (0,
|
|
3035
|
+
const res = await (0, import_core30.fetchWithTimeout)(request, opts.timeoutMs);
|
|
2756
3036
|
const respBody = await res.json().catch(() => null);
|
|
2757
3037
|
return { status: res.status, body: respBody, headers: res.headers };
|
|
2758
3038
|
}
|
|
@@ -2784,13 +3064,13 @@ function personalDelete(opts, path, extra) {
|
|
|
2784
3064
|
}
|
|
2785
3065
|
function throwPersonalHttpError(status, body) {
|
|
2786
3066
|
if (status === 401) {
|
|
2787
|
-
const base = (0,
|
|
3067
|
+
const base = (0, import_core30.extractErrorMessage)(body) ?? `HTTP ${status}`;
|
|
2788
3068
|
throw new CliError(
|
|
2789
3069
|
`${base} \u2014 Your session may have expired or the request was rejected. Run \`wport login\` to sign in again.`,
|
|
2790
3070
|
ExitCode.ServerClientError
|
|
2791
3071
|
);
|
|
2792
3072
|
}
|
|
2793
|
-
(0,
|
|
3073
|
+
(0, import_core30.throwForHttpStatus)(status, body);
|
|
2794
3074
|
}
|
|
2795
3075
|
function warnIfRateLimitLow2(headers) {
|
|
2796
3076
|
const remaining = Number(headers.get("x-ratelimit-remaining"));
|
|
@@ -2801,7 +3081,7 @@ function warnIfRateLimitLow2(headers) {
|
|
|
2801
3081
|
}
|
|
2802
3082
|
|
|
2803
3083
|
// src/commands/auth/whoami.ts
|
|
2804
|
-
var
|
|
3084
|
+
var import_core32 = require("@wport/core");
|
|
2805
3085
|
var PLACEHOLDER = "\u2014";
|
|
2806
3086
|
function display(value) {
|
|
2807
3087
|
const clean = sanitizeForTerminal(value ?? "");
|
|
@@ -2809,8 +3089,8 @@ function display(value) {
|
|
|
2809
3089
|
}
|
|
2810
3090
|
async function performWhoami(ctx) {
|
|
2811
3091
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2812
|
-
const { body } = await personalGet(opts,
|
|
2813
|
-
const sessions = (0,
|
|
3092
|
+
const { body } = await personalGet(opts, import_core32.OAUTH_SESSIONS_BASE);
|
|
3093
|
+
const sessions = (0, import_core31.unwrapDataArray)(body);
|
|
2814
3094
|
const current = sessions.find((s) => s.is_current);
|
|
2815
3095
|
const localLoginAt = loadPersonalCredentials()?.session_created_at ?? null;
|
|
2816
3096
|
if (ctx.format === "json") {
|
|
@@ -2862,15 +3142,15 @@ function registerLogoutCommand(program2) {
|
|
|
2862
3142
|
}
|
|
2863
3143
|
|
|
2864
3144
|
// src/commands/sessions/list.ts
|
|
2865
|
-
var import_core32 = require("@wport/core");
|
|
2866
3145
|
var import_core33 = require("@wport/core");
|
|
3146
|
+
var import_core34 = require("@wport/core");
|
|
2867
3147
|
function formatDate5(value) {
|
|
2868
3148
|
return value ? String(value).slice(0, 10) : "";
|
|
2869
3149
|
}
|
|
2870
3150
|
async function runSessionsList(ctx) {
|
|
2871
3151
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2872
|
-
const { body } = await personalGet(opts,
|
|
2873
|
-
const sessions = (0,
|
|
3152
|
+
const { body } = await personalGet(opts, import_core34.OAUTH_SESSIONS_BASE);
|
|
3153
|
+
const sessions = (0, import_core33.unwrapDataArray)(body);
|
|
2874
3154
|
if (ctx.format === "json") {
|
|
2875
3155
|
printJson(sessions);
|
|
2876
3156
|
return;
|
|
@@ -2894,8 +3174,8 @@ function registerSessionsList(parent) {
|
|
|
2894
3174
|
}
|
|
2895
3175
|
|
|
2896
3176
|
// src/commands/sessions/revoke.ts
|
|
2897
|
-
var import_core34 = require("@wport/core");
|
|
2898
3177
|
var import_core35 = require("@wport/core");
|
|
3178
|
+
var import_core36 = require("@wport/core");
|
|
2899
3179
|
async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
2900
3180
|
const hasEncId = encId !== void 0;
|
|
2901
3181
|
if (hasEncId === allOthers) {
|
|
@@ -2903,8 +3183,8 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
|
2903
3183
|
}
|
|
2904
3184
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2905
3185
|
if (allOthers) {
|
|
2906
|
-
const { body } = await personalDelete(opts, `${
|
|
2907
|
-
const result = (0,
|
|
3186
|
+
const { body } = await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/others`);
|
|
3187
|
+
const result = (0, import_core36.unwrapDataResponse)(body);
|
|
2908
3188
|
if (ctx.format === "json") {
|
|
2909
3189
|
printJson(result);
|
|
2910
3190
|
return;
|
|
@@ -2915,7 +3195,7 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
|
2915
3195
|
}
|
|
2916
3196
|
const trimmed = encId.trim();
|
|
2917
3197
|
if (!trimmed) throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
|
|
2918
|
-
await personalDelete(opts, `${
|
|
3198
|
+
await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
|
|
2919
3199
|
if (ctx.format === "json") {
|
|
2920
3200
|
printJson({ enc_id: trimmed, revoked: true });
|
|
2921
3201
|
return;
|
|
@@ -2938,18 +3218,18 @@ function registerSessionsCommand(program2) {
|
|
|
2938
3218
|
}
|
|
2939
3219
|
|
|
2940
3220
|
// src/commands/personal/resumes/schema.ts
|
|
2941
|
-
var
|
|
3221
|
+
var import_core37 = require("@wport/core");
|
|
2942
3222
|
function registerPersonalResumesSchema(parent) {
|
|
2943
3223
|
parent.command("schema").description("Print the resume aggregate JSON Schema (offline, no login required)").option("--section <name>", "print only the given section (e.g. education, work_experience)").action((opts) => {
|
|
2944
|
-
printJson((0,
|
|
3224
|
+
printJson((0, import_core37.buildAggregateJsonSchema)(opts.section));
|
|
2945
3225
|
});
|
|
2946
3226
|
}
|
|
2947
3227
|
|
|
2948
3228
|
// src/commands/personal/resumes/validate.ts
|
|
2949
|
-
var
|
|
3229
|
+
var import_core38 = require("@wport/core");
|
|
2950
3230
|
function runResumesValidate(ctx, filePath) {
|
|
2951
3231
|
const input = readJsonInput(filePath, { timeoutMs: ctx.timeoutMs });
|
|
2952
|
-
const issues = (0,
|
|
3232
|
+
const issues = (0, import_core38.validateAggregate)(input);
|
|
2953
3233
|
if (issues.length === 0) {
|
|
2954
3234
|
if (ctx.format === "json") {
|
|
2955
3235
|
printJson({ valid: true });
|
|
@@ -2977,9 +3257,9 @@ function registerPersonalResumesValidate(parent) {
|
|
|
2977
3257
|
|
|
2978
3258
|
// src/commands/personal/resumes/template.ts
|
|
2979
3259
|
var import_node_fs8 = require("fs");
|
|
2980
|
-
var
|
|
3260
|
+
var import_core39 = require("@wport/core");
|
|
2981
3261
|
function runResumesTemplate(outPath) {
|
|
2982
|
-
const template = (0,
|
|
3262
|
+
const template = (0, import_core39.buildTemplate)();
|
|
2983
3263
|
if (outPath === void 0) {
|
|
2984
3264
|
printJson(template);
|
|
2985
3265
|
return;
|
|
@@ -3003,8 +3283,8 @@ function registerPersonalResumesTemplate(parent) {
|
|
|
3003
3283
|
}
|
|
3004
3284
|
|
|
3005
3285
|
// src/commands/personal/resumes/list.ts
|
|
3006
|
-
var import_core39 = require("@wport/core");
|
|
3007
3286
|
var import_core40 = require("@wport/core");
|
|
3287
|
+
var import_core41 = require("@wport/core");
|
|
3008
3288
|
var MINIMAL_LIST_FIELDS4 = ["enc_id", "name", "updated_at", "is_complete", "is_published"];
|
|
3009
3289
|
function formatDate6(value) {
|
|
3010
3290
|
return value ? String(value).slice(0, 10) : "";
|
|
@@ -3014,8 +3294,8 @@ function formatQuotaLine(quota) {
|
|
|
3014
3294
|
return `${quota.used}/${quota.max_resumes} used, ${status}.`;
|
|
3015
3295
|
}
|
|
3016
3296
|
async function fetchResumeList(opts) {
|
|
3017
|
-
const { body } = await personalGet(opts,
|
|
3018
|
-
return (0,
|
|
3297
|
+
const { body } = await personalGet(opts, import_core41.PERSONAL_RESUMES_BASE);
|
|
3298
|
+
return (0, import_core40.unwrapDataResponse)(body);
|
|
3019
3299
|
}
|
|
3020
3300
|
async function runResumesList(ctx, flags) {
|
|
3021
3301
|
if (flags.fields && flags.minimal) {
|
|
@@ -3048,20 +3328,20 @@ function registerPersonalResumesList(parent) {
|
|
|
3048
3328
|
}
|
|
3049
3329
|
|
|
3050
3330
|
// src/commands/personal/resumes/view.ts
|
|
3051
|
-
var import_core41 = require("@wport/core");
|
|
3052
3331
|
var import_core42 = require("@wport/core");
|
|
3053
3332
|
var import_core43 = require("@wport/core");
|
|
3333
|
+
var import_core44 = require("@wport/core");
|
|
3054
3334
|
async function fetchResumeAggregate(opts, encId) {
|
|
3055
3335
|
const trimmed = encId.trim();
|
|
3056
3336
|
if (!trimmed) {
|
|
3057
3337
|
throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
|
|
3058
3338
|
}
|
|
3059
|
-
const { body } = await personalGet(opts, `${
|
|
3060
|
-
return (0,
|
|
3339
|
+
const { body } = await personalGet(opts, `${import_core43.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
|
|
3340
|
+
return (0, import_core42.unwrapDataResponse)(body);
|
|
3061
3341
|
}
|
|
3062
3342
|
function summarizeSections(resume) {
|
|
3063
3343
|
const rows = [{ section: "name", summary: resume.name }];
|
|
3064
|
-
for (const def of
|
|
3344
|
+
for (const def of import_core44.SECTIONS) {
|
|
3065
3345
|
rows.push({ section: def.key, summary: summarizeSection(def, resume) });
|
|
3066
3346
|
}
|
|
3067
3347
|
return rows;
|
|
@@ -3139,15 +3419,15 @@ function registerPersonalResumesExport(parent) {
|
|
|
3139
3419
|
}
|
|
3140
3420
|
|
|
3141
3421
|
// src/commands/personal/resumes/create.ts
|
|
3142
|
-
var
|
|
3422
|
+
var import_core48 = require("@wport/core");
|
|
3143
3423
|
|
|
3144
3424
|
// src/lib/resume-orchestrator.ts
|
|
3145
|
-
var
|
|
3146
|
-
var import_core44 = require("@wport/core");
|
|
3425
|
+
var import_node_crypto12 = require("crypto");
|
|
3147
3426
|
var import_core45 = require("@wport/core");
|
|
3148
3427
|
var import_core46 = require("@wport/core");
|
|
3428
|
+
var import_core47 = require("@wport/core");
|
|
3149
3429
|
function freshIdempotencyKey() {
|
|
3150
|
-
return { idempotencyKey: (0,
|
|
3430
|
+
return { idempotencyKey: (0, import_node_crypto12.randomUUID)() };
|
|
3151
3431
|
}
|
|
3152
3432
|
function describeError(err) {
|
|
3153
3433
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -3160,8 +3440,8 @@ function extractErrorCode(body) {
|
|
|
3160
3440
|
}
|
|
3161
3441
|
async function createShell(opts) {
|
|
3162
3442
|
try {
|
|
3163
|
-
const { body } = await personalPost(opts,
|
|
3164
|
-
return (0,
|
|
3443
|
+
const { body } = await personalPost(opts, import_core46.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
|
|
3444
|
+
return (0, import_core45.unwrapDataResponse)(body).enc_id;
|
|
3165
3445
|
} catch (err) {
|
|
3166
3446
|
if (err instanceof ServerClientHttpError) {
|
|
3167
3447
|
const code = extractErrorCode(err.body);
|
|
@@ -3182,7 +3462,7 @@ async function createShell(opts) {
|
|
|
3182
3462
|
}
|
|
3183
3463
|
}
|
|
3184
3464
|
async function renameResume(opts, encId, name) {
|
|
3185
|
-
await personalPut(opts, `${
|
|
3465
|
+
await personalPut(opts, `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
|
|
3186
3466
|
}
|
|
3187
3467
|
function toWorkExperienceWriteItem(item) {
|
|
3188
3468
|
const { is_current, ...rest } = item;
|
|
@@ -3194,8 +3474,8 @@ function splitItemEncId(item) {
|
|
|
3194
3474
|
return [valid, rest];
|
|
3195
3475
|
}
|
|
3196
3476
|
async function writeSection(opts, encId, key, value, mode) {
|
|
3197
|
-
const plan =
|
|
3198
|
-
const base = `${
|
|
3477
|
+
const plan = import_core46.SECTION_WRITE_PLAN[key];
|
|
3478
|
+
const base = `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
|
|
3199
3479
|
switch (plan.kind) {
|
|
3200
3480
|
case "per-item-post": {
|
|
3201
3481
|
for (const item of value) {
|
|
@@ -3262,7 +3542,7 @@ async function createAggregate(opts, aggregate) {
|
|
|
3262
3542
|
if (aggregate.name !== void 0) {
|
|
3263
3543
|
reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
|
|
3264
3544
|
}
|
|
3265
|
-
for (const section of
|
|
3545
|
+
for (const section of import_core47.SECTIONS) {
|
|
3266
3546
|
const value = aggregate[section.key];
|
|
3267
3547
|
if (value === void 0) continue;
|
|
3268
3548
|
reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "create")));
|
|
@@ -3272,9 +3552,9 @@ async function createAggregate(opts, aggregate) {
|
|
|
3272
3552
|
async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
3273
3553
|
const reports = [];
|
|
3274
3554
|
if (onlySection !== void 0) {
|
|
3275
|
-
const section = (0,
|
|
3555
|
+
const section = (0, import_core47.getSection)(onlySection);
|
|
3276
3556
|
if (!section) {
|
|
3277
|
-
const allowed =
|
|
3557
|
+
const allowed = import_core47.SECTIONS.map((s) => s.key).join(", ");
|
|
3278
3558
|
throw new CliError(`Unknown section "${onlySection}". Allowed: ${allowed}`, ExitCode.InvalidArgument);
|
|
3279
3559
|
}
|
|
3280
3560
|
const value = aggregate[onlySection];
|
|
@@ -3287,7 +3567,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
|
3287
3567
|
if (aggregate.name !== void 0) {
|
|
3288
3568
|
reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
|
|
3289
3569
|
}
|
|
3290
|
-
for (const section of
|
|
3570
|
+
for (const section of import_core47.SECTIONS) {
|
|
3291
3571
|
const value = aggregate[section.key];
|
|
3292
3572
|
if (value === void 0) continue;
|
|
3293
3573
|
reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "update")));
|
|
@@ -3298,7 +3578,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
|
3298
3578
|
// src/commands/personal/resumes/create.ts
|
|
3299
3579
|
async function runResumesCreate(ctx, filePath) {
|
|
3300
3580
|
const input = readJsonObject(filePath, { timeoutMs: ctx.timeoutMs });
|
|
3301
|
-
const issues = (0,
|
|
3581
|
+
const issues = (0, import_core48.validateAggregate)(input);
|
|
3302
3582
|
if (issues.length > 0) {
|
|
3303
3583
|
if (ctx.format === "json") {
|
|
3304
3584
|
printJson({ valid: false, issues });
|
|
@@ -3390,9 +3670,9 @@ function registerPersonalResumesUpdate(parent) {
|
|
|
3390
3670
|
}
|
|
3391
3671
|
|
|
3392
3672
|
// src/commands/personal/resumes/copy.ts
|
|
3393
|
-
var
|
|
3394
|
-
var import_core48 = require("@wport/core");
|
|
3673
|
+
var import_node_crypto13 = require("crypto");
|
|
3395
3674
|
var import_core49 = require("@wport/core");
|
|
3675
|
+
var import_core50 = require("@wport/core");
|
|
3396
3676
|
function requireEncId3(encId) {
|
|
3397
3677
|
const trimmed = encId.trim();
|
|
3398
3678
|
if (!trimmed) {
|
|
@@ -3411,12 +3691,12 @@ function printCopyResult(ctx, sourceEncId, newEncId) {
|
|
|
3411
3691
|
async function runResumesCopy(ctx, encId, name) {
|
|
3412
3692
|
const trimmed = requireEncId3(encId);
|
|
3413
3693
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3414
|
-
const { body } = await personalPost(opts, `${
|
|
3415
|
-
const { enc_id: newEncId } = (0,
|
|
3694
|
+
const { body } = await personalPost(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/duplicate`, {}, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
|
|
3695
|
+
const { enc_id: newEncId } = (0, import_core49.unwrapDataResponse)(body);
|
|
3416
3696
|
printCopyResult(ctx, trimmed, newEncId);
|
|
3417
3697
|
if (name === void 0) return;
|
|
3418
3698
|
try {
|
|
3419
|
-
await personalPut(opts, `${
|
|
3699
|
+
await personalPut(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
|
|
3420
3700
|
} catch (err) {
|
|
3421
3701
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3422
3702
|
throw new CliError(
|
|
@@ -3432,9 +3712,9 @@ function registerPersonalResumesCopy(parent) {
|
|
|
3432
3712
|
}
|
|
3433
3713
|
|
|
3434
3714
|
// src/commands/personal/resumes/publish.ts
|
|
3435
|
-
var
|
|
3436
|
-
var import_core50 = require("@wport/core");
|
|
3715
|
+
var import_node_crypto14 = require("crypto");
|
|
3437
3716
|
var import_core51 = require("@wport/core");
|
|
3717
|
+
var import_core52 = require("@wport/core");
|
|
3438
3718
|
function requireEncId4(encId) {
|
|
3439
3719
|
const trimmed = encId.trim();
|
|
3440
3720
|
if (!trimmed) {
|
|
@@ -3448,11 +3728,11 @@ async function runResumesPublishTransition(ctx, encId, action) {
|
|
|
3448
3728
|
const targetStatus = action === "publish";
|
|
3449
3729
|
const { body } = await personalPatch(
|
|
3450
3730
|
opts,
|
|
3451
|
-
`${
|
|
3731
|
+
`${import_core52.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
|
|
3452
3732
|
{ target_status: targetStatus },
|
|
3453
|
-
{ idempotencyKey: (0,
|
|
3733
|
+
{ idempotencyKey: (0, import_node_crypto14.randomUUID)() }
|
|
3454
3734
|
);
|
|
3455
|
-
const result = (0,
|
|
3735
|
+
const result = (0, import_core51.unwrapDataResponse)(body);
|
|
3456
3736
|
if (ctx.format === "json") {
|
|
3457
3737
|
printJson({ enc_id: trimmed, is_published: result.is_published });
|
|
3458
3738
|
return;
|
|
@@ -3473,8 +3753,8 @@ function registerPersonalResumesUnpublish(parent) {
|
|
|
3473
3753
|
}
|
|
3474
3754
|
|
|
3475
3755
|
// src/commands/personal/resumes/delete.ts
|
|
3476
|
-
var
|
|
3477
|
-
var
|
|
3756
|
+
var import_node_crypto15 = require("crypto");
|
|
3757
|
+
var import_core53 = require("@wport/core");
|
|
3478
3758
|
function requireEncId5(encId) {
|
|
3479
3759
|
const trimmed = encId.trim();
|
|
3480
3760
|
if (!trimmed) {
|
|
@@ -3488,7 +3768,7 @@ async function runResumesDelete(ctx, encId, confirm) {
|
|
|
3488
3768
|
}
|
|
3489
3769
|
const trimmed = requireEncId5(encId);
|
|
3490
3770
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3491
|
-
await personalDelete(opts, `${
|
|
3771
|
+
await personalDelete(opts, `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
|
|
3492
3772
|
if (ctx.format === "json") {
|
|
3493
3773
|
printJson({ enc_id: trimmed, deleted: true });
|
|
3494
3774
|
return;
|
|
@@ -3520,9 +3800,9 @@ function registerPersonalResumesCommand(parent) {
|
|
|
3520
3800
|
}
|
|
3521
3801
|
|
|
3522
3802
|
// src/commands/personal/apply/index.ts
|
|
3523
|
-
var
|
|
3803
|
+
var import_node_crypto16 = require("crypto");
|
|
3524
3804
|
var import_node_fs11 = require("fs");
|
|
3525
|
-
var
|
|
3805
|
+
var import_core54 = require("@wport/core");
|
|
3526
3806
|
|
|
3527
3807
|
// src/commands/personal/apply/message-input.ts
|
|
3528
3808
|
var import_node_fs10 = require("fs");
|
|
@@ -3604,7 +3884,7 @@ async function runPersonalApply(ctx, args) {
|
|
|
3604
3884
|
const body = { enc_job_id: args.encJobId, enc_resume_id: args.encResumeId, application_message: args.message };
|
|
3605
3885
|
let result;
|
|
3606
3886
|
try {
|
|
3607
|
-
result = await personalPost(opts,
|
|
3887
|
+
result = await personalPost(opts, import_core54.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
|
|
3608
3888
|
} catch (err) {
|
|
3609
3889
|
rethrowApplyError(err);
|
|
3610
3890
|
}
|
|
@@ -3655,7 +3935,7 @@ async function runPersonalApplyBatch(ctx, args) {
|
|
|
3655
3935
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3656
3936
|
let result;
|
|
3657
3937
|
try {
|
|
3658
|
-
result = await personalPost(opts, `${
|
|
3938
|
+
result = await personalPost(opts, `${import_core54.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
|
|
3659
3939
|
} catch (err) {
|
|
3660
3940
|
rethrowApplyError(err);
|
|
3661
3941
|
}
|
|
@@ -3683,7 +3963,7 @@ function registerPersonalCommand(program2) {
|
|
|
3683
3963
|
|
|
3684
3964
|
// src/index.ts
|
|
3685
3965
|
var program = new import_commander.Command();
|
|
3686
|
-
program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.
|
|
3966
|
+
program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.10.1", "-v, --version", "output the CLI version").option("--lang <locale>", "Accept-Language locale: zh-TW | en-US | vi-VN | th-TH | id-ID").option("--api <url>", "override API base URL").option("--output <fmt>", "output format: table | json").option("--no-color", "disable color output").option("--timeout <ms>", "HTTP timeout in milliseconds", (v) => Number(v));
|
|
3687
3967
|
registerJobsCommand(program);
|
|
3688
3968
|
registerConfigCommand(program);
|
|
3689
3969
|
registerDoctorCommand(program);
|