@wport/cli 0.9.2 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +76 -0
- package/README.md +20 -0
- package/dist/index.js +383 -109
- 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.0"),
|
|
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.0"),
|
|
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.0"),
|
|
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.0"}`);
|
|
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.0"),
|
|
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.0"), 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
|
}
|
|
@@ -1921,6 +1974,15 @@ function renderDetailLines2(company) {
|
|
|
1921
1974
|
}
|
|
1922
1975
|
return lines;
|
|
1923
1976
|
}
|
|
1977
|
+
var BLOCK_SUMMARY_FIELDS = ["pain_points", "awards", "milestones", "qa_items", "video_links"];
|
|
1978
|
+
function renderBlockSummaryLines(company) {
|
|
1979
|
+
const width = Math.max(...BLOCK_SUMMARY_FIELDS.map((f) => f.length)) + 3;
|
|
1980
|
+
return BLOCK_SUMMARY_FIELDS.map((field) => {
|
|
1981
|
+
const value = company[field];
|
|
1982
|
+
const count = Array.isArray(value) ? value.length : 0;
|
|
1983
|
+
return `${(field + ":").padEnd(width)}${count}`;
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1924
1986
|
async function runCompanyView(ctx, apiKey, flags) {
|
|
1925
1987
|
const { body } = await enterpriseGet2(
|
|
1926
1988
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
@@ -1935,7 +1997,8 @@ async function runCompanyView(ctx, apiKey, flags) {
|
|
|
1935
1997
|
printJson(company);
|
|
1936
1998
|
return;
|
|
1937
1999
|
}
|
|
1938
|
-
|
|
2000
|
+
const lines = [...renderDetailLines2(company), "", ...renderBlockSummaryLines(company)];
|
|
2001
|
+
process.stdout.write(lines.join("\n") + "\n");
|
|
1939
2002
|
}
|
|
1940
2003
|
function registerEnterpriseCompanyView(parent) {
|
|
1941
2004
|
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 +2013,52 @@ function registerEnterpriseCompanyView(parent) {
|
|
|
1950
2013
|
var import_node_crypto5 = require("crypto");
|
|
1951
2014
|
var import_core19 = require("@wport/core");
|
|
1952
2015
|
|
|
2016
|
+
// src/commands/enterprise/company/block-replace-shared.ts
|
|
2017
|
+
function assertValidSubmittedItems(value, label) {
|
|
2018
|
+
if (!Array.isArray(value)) {
|
|
2019
|
+
throw new InvalidArgumentError(
|
|
2020
|
+
`"${label}" must be a JSON array, got ${value === null ? "null" : typeof value}`
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
value.forEach((item, index) => {
|
|
2024
|
+
if (item === null || typeof item !== "object" || Array.isArray(item)) {
|
|
2025
|
+
throw new InvalidArgumentError(
|
|
2026
|
+
`"${label}[${index}]" must be a JSON object, got ` + (item === null ? "null" : Array.isArray(item) ? "an array" : typeof item)
|
|
2027
|
+
);
|
|
2028
|
+
}
|
|
2029
|
+
});
|
|
2030
|
+
return value;
|
|
2031
|
+
}
|
|
2032
|
+
function previewDeletions(current, submitted, summarize) {
|
|
2033
|
+
const submittedIds = new Set(
|
|
2034
|
+
submitted.filter((i) => typeof i.enc_id === "string").map((i) => i.enc_id)
|
|
2035
|
+
);
|
|
2036
|
+
return current.filter((item) => !submittedIds.has(item.enc_id)).map((item) => ({ enc_id: item.enc_id, summary: summarize(item) }));
|
|
2037
|
+
}
|
|
2038
|
+
function enforceDeletionConfirmation(label, deletions, confirm, color) {
|
|
2039
|
+
if (deletions.length === 0) return;
|
|
2040
|
+
printWarn(
|
|
2041
|
+
`This replace will delete ${deletions.length} existing "${label}" item(s): ` + deletions.map((d) => `${d.enc_id} (${d.summary || "untitled"})`).join("; "),
|
|
2042
|
+
color
|
|
2043
|
+
);
|
|
2044
|
+
if (!confirm) {
|
|
2045
|
+
throw new InvalidArgumentError(
|
|
2046
|
+
`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.`
|
|
2047
|
+
);
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
function summarizeItemsDiff(before, after) {
|
|
2051
|
+
const beforeIds = new Set(before.map((i) => i.enc_id));
|
|
2052
|
+
const afterIds = new Set(after.map((i) => i.enc_id));
|
|
2053
|
+
const added = after.filter((i) => !beforeIds.has(i.enc_id)).map((i) => i.enc_id);
|
|
2054
|
+
const removed = before.filter((i) => !afterIds.has(i.enc_id)).map((i) => i.enc_id);
|
|
2055
|
+
const parts = [];
|
|
2056
|
+
if (added.length > 0) parts.push(`added since your read: ${added.join(", ")}`);
|
|
2057
|
+
if (removed.length > 0) parts.push(`removed since your read: ${removed.join(", ")}`);
|
|
2058
|
+
if (parts.length === 0) parts.push("item content or order changed (enc_id set unchanged)");
|
|
2059
|
+
return parts.join("; ");
|
|
2060
|
+
}
|
|
2061
|
+
|
|
1953
2062
|
// src/commands/enterprise/company/types.ts
|
|
1954
2063
|
var BASIC_FIELDS = [
|
|
1955
2064
|
"name",
|
|
@@ -1961,24 +2070,25 @@ var BASIC_FIELDS = [
|
|
|
1961
2070
|
"capital_show_status",
|
|
1962
2071
|
"website",
|
|
1963
2072
|
"area_code",
|
|
1964
|
-
"address"
|
|
2073
|
+
"address",
|
|
2074
|
+
"representative_name",
|
|
2075
|
+
"establishment_date",
|
|
2076
|
+
"directors",
|
|
2077
|
+
"is_representative_visible",
|
|
2078
|
+
"is_establishment_date_visible",
|
|
2079
|
+
"is_directors_visible"
|
|
1965
2080
|
];
|
|
1966
|
-
var DESCRIPTION_FIELDS = ["description", "products_services", "latest_news"];
|
|
2081
|
+
var DESCRIPTION_FIELDS = ["description", "products_services", "latest_news", "video_links"];
|
|
1967
2082
|
var FORBIDDEN_FIELDS = [
|
|
1968
2083
|
"uniform_number",
|
|
2084
|
+
"is_uniform_number_visible",
|
|
1969
2085
|
"banner_url",
|
|
1970
2086
|
"photo_1",
|
|
1971
2087
|
"photo_2",
|
|
1972
2088
|
"photo_3",
|
|
1973
2089
|
"video_1",
|
|
1974
2090
|
"video_2",
|
|
1975
|
-
"video_3"
|
|
1976
|
-
"foundation_date",
|
|
1977
|
-
"representative",
|
|
1978
|
-
"directors",
|
|
1979
|
-
"milestones",
|
|
1980
|
-
"awards",
|
|
1981
|
-
"qa"
|
|
2091
|
+
"video_3"
|
|
1982
2092
|
];
|
|
1983
2093
|
|
|
1984
2094
|
// src/commands/enterprise/company/update.ts
|
|
@@ -2046,12 +2156,25 @@ async function buildCompanyUpdatePayloads(input, ctx, apiKey) {
|
|
|
2046
2156
|
}
|
|
2047
2157
|
let descriptions = null;
|
|
2048
2158
|
if (inputHasDescriptionField) {
|
|
2049
|
-
|
|
2159
|
+
const partial = {};
|
|
2050
2160
|
for (const field of DESCRIPTION_FIELDS) {
|
|
2051
|
-
if (field in input)
|
|
2161
|
+
if (field in input) partial[field] = input[field];
|
|
2162
|
+
}
|
|
2163
|
+
descriptions = partial;
|
|
2164
|
+
}
|
|
2165
|
+
let videoLinksRevision;
|
|
2166
|
+
let currentVideoLinks;
|
|
2167
|
+
if ("video_links" in input) {
|
|
2168
|
+
currentVideoLinks = current.video_links ?? [];
|
|
2169
|
+
videoLinksRevision = current.block_revisions?.video_links;
|
|
2170
|
+
if (!videoLinksRevision) {
|
|
2171
|
+
throw new CliError(
|
|
2172
|
+
"Backend contract appears broken: GET /company response is missing block_revisions.video_links",
|
|
2173
|
+
ExitCode.ServerOrNetworkError
|
|
2174
|
+
);
|
|
2052
2175
|
}
|
|
2053
2176
|
}
|
|
2054
|
-
return { basic, descriptions };
|
|
2177
|
+
return { basic, descriptions, videoLinksRevision, currentVideoLinks };
|
|
2055
2178
|
}
|
|
2056
2179
|
function isDescriptionsPartialFailureBody(body) {
|
|
2057
2180
|
return !!body && typeof body === "object" && Array.isArray(body.updated_sections) && typeof body.failed_section === "string";
|
|
@@ -2076,12 +2199,21 @@ function resolveUpdateIdempotencyKeys(needsBasic, needsDescriptions, flags) {
|
|
|
2076
2199
|
descriptionsKey: needsDescriptions ? flags.descriptionsIdempotencyKey ?? flags.idempotencyKey ?? (0, import_node_crypto5.randomUUID)() : void 0
|
|
2077
2200
|
};
|
|
2078
2201
|
}
|
|
2079
|
-
async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options = {}) {
|
|
2202
|
+
async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options = {}, confirm = false) {
|
|
2080
2203
|
const input = readJsonObject(source, options);
|
|
2081
2204
|
const needsBasic = BASIC_FIELDS.some((f) => f in input);
|
|
2082
2205
|
const needsDescriptions = DESCRIPTION_FIELDS.some((f) => f in input);
|
|
2206
|
+
const needsVideoLinks = "video_links" in input;
|
|
2207
|
+
if (needsVideoLinks) {
|
|
2208
|
+
assertValidSubmittedItems(input.video_links, "video_links");
|
|
2209
|
+
}
|
|
2083
2210
|
const { basicKey, descriptionsKey } = resolveUpdateIdempotencyKeys(needsBasic, needsDescriptions, idempotencyFlags);
|
|
2084
2211
|
const payloads = await buildCompanyUpdatePayloads(input, ctx, apiKey);
|
|
2212
|
+
if (needsVideoLinks) {
|
|
2213
|
+
const submitted = payloads.descriptions?.video_links ?? [];
|
|
2214
|
+
const deletions = previewDeletions(payloads.currentVideoLinks ?? [], submitted, (item) => String(item.url ?? ""));
|
|
2215
|
+
enforceDeletionConfirmation("video_links", deletions, confirm, ctx.color ?? false);
|
|
2216
|
+
}
|
|
2085
2217
|
const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
|
|
2086
2218
|
let basicResultCompany;
|
|
2087
2219
|
if (needsBasic) {
|
|
@@ -2099,11 +2231,43 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
|
|
|
2099
2231
|
requestOpts,
|
|
2100
2232
|
"/company/descriptions",
|
|
2101
2233
|
payloads.descriptions,
|
|
2102
|
-
{
|
|
2234
|
+
{
|
|
2235
|
+
idempotencyKey: descriptionsKey,
|
|
2236
|
+
// 只有輸入帶 video_links 時才附 If-Match——後端只在這種情況要求它(spec §3.2.2);
|
|
2237
|
+
// 沒帶 video_links 時絕不能傳這個 key(用條件式 spread,不是傳 `undefined`)。
|
|
2238
|
+
...needsVideoLinks ? { ifMatch: payloads.videoLinksRevision } : {}
|
|
2239
|
+
}
|
|
2103
2240
|
);
|
|
2104
2241
|
const result = (0, import_core19.unwrapDataResponse)(body);
|
|
2105
2242
|
printCompanyResult(result.company, ctx.format);
|
|
2106
2243
|
} catch (err) {
|
|
2244
|
+
if (needsVideoLinks && err instanceof ServerClientHttpError && err.status === 409) {
|
|
2245
|
+
const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2246
|
+
const freshCurrent = (0, import_core19.unwrapDataResponse)(freshBody);
|
|
2247
|
+
const freshVideoLinks = freshCurrent.video_links ?? [];
|
|
2248
|
+
const diff = summarizeItemsDiff(payloads.currentVideoLinks ?? [], freshVideoLinks);
|
|
2249
|
+
const partialBody = isDescriptionsPartialFailureBody(err.body) ? err.body : void 0;
|
|
2250
|
+
printWarn(`Server state for "video_links" changed since your read: ${diff}.`, ctx.color ?? false);
|
|
2251
|
+
const descriptionsError = {
|
|
2252
|
+
updated_sections: partialBody?.updated_sections ?? [],
|
|
2253
|
+
failed_section: partialBody?.failed_section ?? "video_links",
|
|
2254
|
+
video_links_diff: diff
|
|
2255
|
+
};
|
|
2256
|
+
if (ctx.format === "json") {
|
|
2257
|
+
printJson(
|
|
2258
|
+
needsBasic ? { basic_updated: true, basic_company: basicResultCompany, descriptions_error: descriptionsError } : { descriptions_error: descriptionsError }
|
|
2259
|
+
);
|
|
2260
|
+
} else {
|
|
2261
|
+
if (needsBasic) process.stdout.write("Basic company info was updated successfully.\n");
|
|
2262
|
+
process.stdout.write(
|
|
2263
|
+
`Updated sections before failure: ${descriptionsError.updated_sections.join(", ")}; failed section: ${descriptionsError.failed_section}
|
|
2264
|
+
`
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
throw new InvalidArgumentError(
|
|
2268
|
+
`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.`
|
|
2269
|
+
);
|
|
2270
|
+
}
|
|
2107
2271
|
if (!needsBasic) {
|
|
2108
2272
|
throw err;
|
|
2109
2273
|
}
|
|
@@ -2134,10 +2298,13 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
|
|
|
2134
2298
|
}
|
|
2135
2299
|
function registerEnterpriseCompanyUpdate(parent) {
|
|
2136
2300
|
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)"
|
|
2301
|
+
"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
2302
|
).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
2303
|
"--descriptions-idempotency-key <key>",
|
|
2140
2304
|
"two-section update: idempotency key for PATCH /company/descriptions"
|
|
2305
|
+
).option(
|
|
2306
|
+
"--confirm",
|
|
2307
|
+
"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
2308
|
).action(async (flags, command) => {
|
|
2142
2309
|
const ctx = resolveContext(command);
|
|
2143
2310
|
const globals = command.optsWithGlobals();
|
|
@@ -2151,7 +2318,8 @@ function registerEnterpriseCompanyUpdate(parent) {
|
|
|
2151
2318
|
basicIdempotencyKey: flags.basicIdempotencyKey,
|
|
2152
2319
|
descriptionsIdempotencyKey: flags.descriptionsIdempotencyKey
|
|
2153
2320
|
},
|
|
2154
|
-
{ timeoutMs: ctx.timeoutMs }
|
|
2321
|
+
{ timeoutMs: ctx.timeoutMs },
|
|
2322
|
+
flags.confirm === true
|
|
2155
2323
|
);
|
|
2156
2324
|
});
|
|
2157
2325
|
}
|
|
@@ -2247,16 +2415,122 @@ function registerEnterpriseCompanyLogo(parent) {
|
|
|
2247
2415
|
});
|
|
2248
2416
|
}
|
|
2249
2417
|
|
|
2418
|
+
// src/commands/enterprise/company/replace.ts
|
|
2419
|
+
var import_node_crypto7 = require("crypto");
|
|
2420
|
+
var import_core21 = require("@wport/core");
|
|
2421
|
+
var REPLACE_SECTIONS = ["pain-points", "awards", "milestones", "qa-items"];
|
|
2422
|
+
var SECTION_CONFIG = {
|
|
2423
|
+
"pain-points": {
|
|
2424
|
+
path: "/company/pain-points",
|
|
2425
|
+
dataKey: "pain_points",
|
|
2426
|
+
summarize: (i) => String(i.title ?? "")
|
|
2427
|
+
},
|
|
2428
|
+
awards: {
|
|
2429
|
+
path: "/company/awards",
|
|
2430
|
+
dataKey: "awards",
|
|
2431
|
+
summarize: (i) => String(i.name ?? "")
|
|
2432
|
+
},
|
|
2433
|
+
milestones: {
|
|
2434
|
+
path: "/company/milestones",
|
|
2435
|
+
dataKey: "milestones",
|
|
2436
|
+
summarize: (i) => String(i.title ?? "")
|
|
2437
|
+
},
|
|
2438
|
+
"qa-items": {
|
|
2439
|
+
path: "/company/qa-items",
|
|
2440
|
+
dataKey: "qa_items",
|
|
2441
|
+
summarize: (i) => String(i.question ?? "")
|
|
2442
|
+
}
|
|
2443
|
+
};
|
|
2444
|
+
function isReplaceSection(v) {
|
|
2445
|
+
return REPLACE_SECTIONS.includes(v);
|
|
2446
|
+
}
|
|
2447
|
+
function printReplaceResult(result, config, format, color) {
|
|
2448
|
+
if (format === "json") {
|
|
2449
|
+
printJson(result);
|
|
2450
|
+
return;
|
|
2451
|
+
}
|
|
2452
|
+
printTable(
|
|
2453
|
+
result.items ?? [],
|
|
2454
|
+
[
|
|
2455
|
+
{ header: "enc_id", value: (r) => String(r.enc_id ?? "") },
|
|
2456
|
+
{ header: "summary", value: (r) => config.summarize(r) }
|
|
2457
|
+
],
|
|
2458
|
+
color
|
|
2459
|
+
);
|
|
2460
|
+
process.stdout.write(`revision: ${result.revision ?? ""}
|
|
2461
|
+
`);
|
|
2462
|
+
}
|
|
2463
|
+
async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempotencyKey, options = {}) {
|
|
2464
|
+
if (!isReplaceSection(section)) {
|
|
2465
|
+
throw new InvalidArgumentError(`Invalid section "${section}". Allowed: ${REPLACE_SECTIONS.join(", ")}`);
|
|
2466
|
+
}
|
|
2467
|
+
const config = SECTION_CONFIG[section];
|
|
2468
|
+
const input = readJsonObject(source, options);
|
|
2469
|
+
if (!Array.isArray(input.items)) {
|
|
2470
|
+
throw new InvalidArgumentError('Input must be a JSON object of the form { "items": [...] }');
|
|
2471
|
+
}
|
|
2472
|
+
const items = assertValidSubmittedItems(input.items, "items");
|
|
2473
|
+
const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
|
|
2474
|
+
const { body: getBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2475
|
+
const current = (0, import_core21.unwrapDataResponse)(getBody);
|
|
2476
|
+
const currentItems = current[config.dataKey] ?? [];
|
|
2477
|
+
const revision = current.block_revisions?.[config.dataKey];
|
|
2478
|
+
if (!revision) {
|
|
2479
|
+
throw new CliError(
|
|
2480
|
+
`Backend contract appears broken: GET /company response is missing block_revisions.${config.dataKey}`,
|
|
2481
|
+
ExitCode.ServerOrNetworkError
|
|
2482
|
+
);
|
|
2483
|
+
}
|
|
2484
|
+
const deletions = previewDeletions(currentItems, items, config.summarize);
|
|
2485
|
+
enforceDeletionConfirmation(section, deletions, confirm, ctx.color);
|
|
2486
|
+
try {
|
|
2487
|
+
const { body } = await enterprisePut2(requestOpts, config.path, { items }, { idempotencyKey, ifMatch: revision });
|
|
2488
|
+
const result = (0, import_core21.unwrapDataResponse)(body);
|
|
2489
|
+
printReplaceResult(result, config, ctx.format, ctx.color);
|
|
2490
|
+
} catch (err) {
|
|
2491
|
+
if (err instanceof import_core21.WportHttpError && err.status === 409) {
|
|
2492
|
+
const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
|
|
2493
|
+
const freshCurrent = (0, import_core21.unwrapDataResponse)(freshBody);
|
|
2494
|
+
const freshItems = freshCurrent[config.dataKey] ?? [];
|
|
2495
|
+
const diff = summarizeItemsDiff(currentItems, freshItems);
|
|
2496
|
+
printWarn(`Server state for "${section}" changed since your read: ${diff}.`, ctx.color);
|
|
2497
|
+
throw new InvalidArgumentError(
|
|
2498
|
+
`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.`
|
|
2499
|
+
);
|
|
2500
|
+
}
|
|
2501
|
+
throw err;
|
|
2502
|
+
}
|
|
2503
|
+
}
|
|
2504
|
+
function registerEnterpriseCompanyReplace(parent) {
|
|
2505
|
+
parent.command("replace <section>").description(
|
|
2506
|
+
`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.`
|
|
2507
|
+
).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) => {
|
|
2508
|
+
const ctx = resolveContext(command);
|
|
2509
|
+
const globals = command.optsWithGlobals();
|
|
2510
|
+
const { key } = resolveApiKey(globals.apiKey);
|
|
2511
|
+
await runCompanyReplace(
|
|
2512
|
+
ctx,
|
|
2513
|
+
key,
|
|
2514
|
+
section,
|
|
2515
|
+
flags.file,
|
|
2516
|
+
flags.confirm === true,
|
|
2517
|
+
flags.idempotencyKey ?? (0, import_node_crypto7.randomUUID)(),
|
|
2518
|
+
{ timeoutMs: ctx.timeoutMs }
|
|
2519
|
+
);
|
|
2520
|
+
});
|
|
2521
|
+
}
|
|
2522
|
+
|
|
2250
2523
|
// src/commands/enterprise/company/index.ts
|
|
2251
2524
|
function registerEnterpriseCompanyCommand(parent) {
|
|
2252
2525
|
const company = parent.command("company").description("View and manage your company information");
|
|
2253
2526
|
registerEnterpriseCompanyView(company);
|
|
2254
2527
|
registerEnterpriseCompanyUpdate(company);
|
|
2255
2528
|
registerEnterpriseCompanyLogo(company);
|
|
2529
|
+
registerEnterpriseCompanyReplace(company);
|
|
2256
2530
|
}
|
|
2257
2531
|
|
|
2258
2532
|
// src/commands/enterprise/talents/list.ts
|
|
2259
|
-
var
|
|
2533
|
+
var import_core22 = require("@wport/core");
|
|
2260
2534
|
var DEFAULT_PAGE_SIZE = 20;
|
|
2261
2535
|
var MINIMAL_LIST_FIELDS2 = ["enc_resume_id", "candidate_name", "applied_job_title", "applied_at"];
|
|
2262
2536
|
function formatDate4(value) {
|
|
@@ -2279,7 +2553,7 @@ async function runEnterpriseTalentsList(ctx, apiKey, flags) {
|
|
|
2279
2553
|
pageSize: flags.pageSize ?? DEFAULT_PAGE_SIZE
|
|
2280
2554
|
}
|
|
2281
2555
|
);
|
|
2282
|
-
const paged = (0,
|
|
2556
|
+
const paged = (0, import_core22.asPaginatedBody)(body);
|
|
2283
2557
|
const projection = flags.minimal ? MINIMAL_LIST_FIELDS2 : flags.fields ? parseFieldsList(flags.fields) : void 0;
|
|
2284
2558
|
if (projection || ctx.format === "json") {
|
|
2285
2559
|
printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
|
|
@@ -2312,7 +2586,7 @@ function registerEnterpriseTalentsList(parent) {
|
|
|
2312
2586
|
}
|
|
2313
2587
|
|
|
2314
2588
|
// src/commands/enterprise/talents/view.ts
|
|
2315
|
-
var
|
|
2589
|
+
var import_core23 = require("@wport/core");
|
|
2316
2590
|
async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
|
|
2317
2591
|
const trimmed = encResumeId.trim();
|
|
2318
2592
|
if (!trimmed) {
|
|
@@ -2322,7 +2596,7 @@ async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
|
|
|
2322
2596
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
2323
2597
|
`/talents/${encodeURIComponent(trimmed)}`
|
|
2324
2598
|
);
|
|
2325
|
-
const resume = (0,
|
|
2599
|
+
const resume = (0, import_core23.unwrapDataResponse)(body);
|
|
2326
2600
|
if (flags.fields) {
|
|
2327
2601
|
printJson(pickPaths(resume, parseFieldsList(flags.fields)));
|
|
2328
2602
|
return;
|
|
@@ -2339,8 +2613,8 @@ function registerEnterpriseTalentsView(parent) {
|
|
|
2339
2613
|
}
|
|
2340
2614
|
|
|
2341
2615
|
// src/commands/enterprise/talents/respond.ts
|
|
2342
|
-
var
|
|
2343
|
-
var
|
|
2616
|
+
var import_node_crypto8 = require("crypto");
|
|
2617
|
+
var import_core24 = require("@wport/core");
|
|
2344
2618
|
function resolveRespondBody(flags, options = {}) {
|
|
2345
2619
|
const hasBody = flags.body !== void 0;
|
|
2346
2620
|
const hasBodyFile = flags.bodyFile !== void 0;
|
|
@@ -2372,7 +2646,7 @@ async function runEnterpriseTalentsRespond(ctx, apiKey, encResumeId, flags, idem
|
|
|
2372
2646
|
payload,
|
|
2373
2647
|
{ idempotencyKey }
|
|
2374
2648
|
);
|
|
2375
|
-
const result = (0,
|
|
2649
|
+
const result = (0, import_core24.unwrapDataResponse)(respBody);
|
|
2376
2650
|
if (ctx.format === "json") {
|
|
2377
2651
|
printJson(result);
|
|
2378
2652
|
return;
|
|
@@ -2385,7 +2659,7 @@ function registerEnterpriseTalentsRespond(parent) {
|
|
|
2385
2659
|
const ctx = resolveContext(command);
|
|
2386
2660
|
const globals = command.optsWithGlobals();
|
|
2387
2661
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2388
|
-
await runEnterpriseTalentsRespond(ctx, key, encResumeId, flags, flags.idempotencyKey ?? (0,
|
|
2662
|
+
await runEnterpriseTalentsRespond(ctx, key, encResumeId, flags, flags.idempotencyKey ?? (0, import_node_crypto8.randomUUID)());
|
|
2389
2663
|
});
|
|
2390
2664
|
}
|
|
2391
2665
|
|
|
@@ -2400,8 +2674,8 @@ function registerEnterpriseTalentsCommand(parent) {
|
|
|
2400
2674
|
}
|
|
2401
2675
|
|
|
2402
2676
|
// src/commands/enterprise/campaigns/create.ts
|
|
2403
|
-
var
|
|
2404
|
-
var
|
|
2677
|
+
var import_node_crypto9 = require("crypto");
|
|
2678
|
+
var import_core25 = require("@wport/core");
|
|
2405
2679
|
async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
|
|
2406
2680
|
const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
|
|
2407
2681
|
const { body } = await enterprisePost2(
|
|
@@ -2410,7 +2684,7 @@ async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
|
|
|
2410
2684
|
campaignBody,
|
|
2411
2685
|
{ idempotencyKey }
|
|
2412
2686
|
);
|
|
2413
|
-
const created = (0,
|
|
2687
|
+
const created = (0, import_core25.unwrapDataResponse)(body);
|
|
2414
2688
|
if (ctx.format === "json") {
|
|
2415
2689
|
printJson(created);
|
|
2416
2690
|
return;
|
|
@@ -2423,12 +2697,12 @@ function registerEnterpriseCampaignsCreate(parent) {
|
|
|
2423
2697
|
const ctx = resolveContext(command);
|
|
2424
2698
|
const globals = command.optsWithGlobals();
|
|
2425
2699
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2426
|
-
await runCampaignCreate(ctx, key, flags.file, flags.idempotencyKey ?? (0,
|
|
2700
|
+
await runCampaignCreate(ctx, key, flags.file, flags.idempotencyKey ?? (0, import_node_crypto9.randomUUID)());
|
|
2427
2701
|
});
|
|
2428
2702
|
}
|
|
2429
2703
|
|
|
2430
2704
|
// src/commands/enterprise/campaigns/list.ts
|
|
2431
|
-
var
|
|
2705
|
+
var import_core26 = require("@wport/core");
|
|
2432
2706
|
var STATUS_MAP2 = { open: 1, closed: 0 };
|
|
2433
2707
|
var MINIMAL_LIST_FIELDS3 = ["enc_id", "name", "status", "job_count"];
|
|
2434
2708
|
function mapStatusFlag2(raw) {
|
|
@@ -2458,7 +2732,7 @@ async function runEnterpriseCampaignsList(ctx, apiKey, flags) {
|
|
|
2458
2732
|
status: mapStatusFlag2(flags.status)
|
|
2459
2733
|
}
|
|
2460
2734
|
);
|
|
2461
|
-
const paged = (0,
|
|
2735
|
+
const paged = (0, import_core26.asPaginatedBody)(body);
|
|
2462
2736
|
const projection = flags.minimal ? MINIMAL_LIST_FIELDS3 : flags.fields ? parseFieldsList(flags.fields) : void 0;
|
|
2463
2737
|
if (projection || ctx.format === "json") {
|
|
2464
2738
|
printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
|
|
@@ -2490,8 +2764,8 @@ function registerEnterpriseCampaignsList(parent) {
|
|
|
2490
2764
|
}
|
|
2491
2765
|
|
|
2492
2766
|
// src/commands/enterprise/campaigns/lifecycle.ts
|
|
2493
|
-
var
|
|
2494
|
-
var
|
|
2767
|
+
var import_node_crypto10 = require("crypto");
|
|
2768
|
+
var import_core27 = require("@wport/core");
|
|
2495
2769
|
async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey) {
|
|
2496
2770
|
const trimmed = requireEncId(encId);
|
|
2497
2771
|
const { body } = await enterprisePatch2(
|
|
@@ -2500,7 +2774,7 @@ async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey)
|
|
|
2500
2774
|
{},
|
|
2501
2775
|
{ idempotencyKey }
|
|
2502
2776
|
);
|
|
2503
|
-
const result = (0,
|
|
2777
|
+
const result = (0, import_core27.unwrapDataResponse)(body);
|
|
2504
2778
|
if (ctx.format === "json") {
|
|
2505
2779
|
printJson(result);
|
|
2506
2780
|
return;
|
|
@@ -2513,20 +2787,20 @@ function registerEnterpriseCampaignsPublish(parent) {
|
|
|
2513
2787
|
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
2788
|
const ctx = resolveContext(command);
|
|
2515
2789
|
const { key } = resolveApiKey(command.optsWithGlobals().apiKey);
|
|
2516
|
-
await runCampaignTransition(ctx, key, encId, "publish", flags.idempotencyKey ?? (0,
|
|
2790
|
+
await runCampaignTransition(ctx, key, encId, "publish", flags.idempotencyKey ?? (0, import_node_crypto10.randomUUID)());
|
|
2517
2791
|
});
|
|
2518
2792
|
}
|
|
2519
2793
|
function registerEnterpriseCampaignsUnpublish(parent) {
|
|
2520
2794
|
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
2795
|
const ctx = resolveContext(command);
|
|
2522
2796
|
const { key } = resolveApiKey(command.optsWithGlobals().apiKey);
|
|
2523
|
-
await runCampaignTransition(ctx, key, encId, "unpublish", flags.idempotencyKey ?? (0,
|
|
2797
|
+
await runCampaignTransition(ctx, key, encId, "unpublish", flags.idempotencyKey ?? (0, import_node_crypto10.randomUUID)());
|
|
2524
2798
|
});
|
|
2525
2799
|
}
|
|
2526
2800
|
|
|
2527
2801
|
// src/commands/enterprise/campaigns/update.ts
|
|
2528
|
-
var
|
|
2529
|
-
var
|
|
2802
|
+
var import_node_crypto11 = require("crypto");
|
|
2803
|
+
var import_core28 = require("@wport/core");
|
|
2530
2804
|
async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
|
|
2531
2805
|
const trimmed = requireEncId(encId);
|
|
2532
2806
|
const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
|
|
@@ -2536,7 +2810,7 @@ async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
|
|
|
2536
2810
|
campaignBody,
|
|
2537
2811
|
{ idempotencyKey }
|
|
2538
2812
|
);
|
|
2539
|
-
const updated = (0,
|
|
2813
|
+
const updated = (0, import_core28.unwrapDataResponse)(body);
|
|
2540
2814
|
if (ctx.format === "json") {
|
|
2541
2815
|
printJson(updated);
|
|
2542
2816
|
return;
|
|
@@ -2549,12 +2823,12 @@ function registerEnterpriseCampaignsUpdate(parent) {
|
|
|
2549
2823
|
const ctx = resolveContext(command);
|
|
2550
2824
|
const globals = command.optsWithGlobals();
|
|
2551
2825
|
const { key } = resolveApiKey(globals.apiKey);
|
|
2552
|
-
await runCampaignUpdate(ctx, key, encId, flags.file, flags.idempotencyKey ?? (0,
|
|
2826
|
+
await runCampaignUpdate(ctx, key, encId, flags.file, flags.idempotencyKey ?? (0, import_node_crypto11.randomUUID)());
|
|
2553
2827
|
});
|
|
2554
2828
|
}
|
|
2555
2829
|
|
|
2556
2830
|
// src/commands/enterprise/campaigns/view.ts
|
|
2557
|
-
var
|
|
2831
|
+
var import_core29 = require("@wport/core");
|
|
2558
2832
|
async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
|
|
2559
2833
|
const trimmed = encId.trim();
|
|
2560
2834
|
if (!trimmed) {
|
|
@@ -2564,7 +2838,7 @@ async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
|
|
|
2564
2838
|
{ baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
|
|
2565
2839
|
`/campaigns/${encodeURIComponent(trimmed)}`
|
|
2566
2840
|
);
|
|
2567
|
-
const campaign = (0,
|
|
2841
|
+
const campaign = (0, import_core29.unwrapDataResponse)(body);
|
|
2568
2842
|
if (flags.fields) {
|
|
2569
2843
|
printJson(pickPaths(campaign, parseFieldsList(flags.fields)));
|
|
2570
2844
|
return;
|
|
@@ -2709,10 +2983,10 @@ function registerLoginCommand(program2) {
|
|
|
2709
2983
|
}
|
|
2710
2984
|
|
|
2711
2985
|
// src/commands/auth/whoami.ts
|
|
2712
|
-
var
|
|
2986
|
+
var import_core31 = require("@wport/core");
|
|
2713
2987
|
|
|
2714
2988
|
// src/lib/personal-client.ts
|
|
2715
|
-
var
|
|
2989
|
+
var import_core30 = require("@wport/core");
|
|
2716
2990
|
var EXPIRY_SKEW_MS = 3e4;
|
|
2717
2991
|
var NOT_LOGGED_IN_MESSAGE = "Not logged in. Run `wport login`.";
|
|
2718
2992
|
async function ensureFreshCredentials(opts) {
|
|
@@ -2741,7 +3015,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
|
|
|
2741
3015
|
const headers = {
|
|
2742
3016
|
Authorization: `Bearer ${accessToken}`,
|
|
2743
3017
|
"Accept-Language": opts.locale,
|
|
2744
|
-
"User-Agent": (0,
|
|
3018
|
+
"User-Agent": (0, import_core30.buildUserAgent)("wport-cli", "0.10.0"),
|
|
2745
3019
|
"X-Source": CLI_SOURCE,
|
|
2746
3020
|
Accept: "application/json"
|
|
2747
3021
|
};
|
|
@@ -2752,7 +3026,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
|
|
|
2752
3026
|
headers,
|
|
2753
3027
|
body: body !== void 0 ? JSON.stringify(body) : void 0
|
|
2754
3028
|
});
|
|
2755
|
-
const res = await (0,
|
|
3029
|
+
const res = await (0, import_core30.fetchWithTimeout)(request, opts.timeoutMs);
|
|
2756
3030
|
const respBody = await res.json().catch(() => null);
|
|
2757
3031
|
return { status: res.status, body: respBody, headers: res.headers };
|
|
2758
3032
|
}
|
|
@@ -2784,13 +3058,13 @@ function personalDelete(opts, path, extra) {
|
|
|
2784
3058
|
}
|
|
2785
3059
|
function throwPersonalHttpError(status, body) {
|
|
2786
3060
|
if (status === 401) {
|
|
2787
|
-
const base = (0,
|
|
3061
|
+
const base = (0, import_core30.extractErrorMessage)(body) ?? `HTTP ${status}`;
|
|
2788
3062
|
throw new CliError(
|
|
2789
3063
|
`${base} \u2014 Your session may have expired or the request was rejected. Run \`wport login\` to sign in again.`,
|
|
2790
3064
|
ExitCode.ServerClientError
|
|
2791
3065
|
);
|
|
2792
3066
|
}
|
|
2793
|
-
(0,
|
|
3067
|
+
(0, import_core30.throwForHttpStatus)(status, body);
|
|
2794
3068
|
}
|
|
2795
3069
|
function warnIfRateLimitLow2(headers) {
|
|
2796
3070
|
const remaining = Number(headers.get("x-ratelimit-remaining"));
|
|
@@ -2801,7 +3075,7 @@ function warnIfRateLimitLow2(headers) {
|
|
|
2801
3075
|
}
|
|
2802
3076
|
|
|
2803
3077
|
// src/commands/auth/whoami.ts
|
|
2804
|
-
var
|
|
3078
|
+
var import_core32 = require("@wport/core");
|
|
2805
3079
|
var PLACEHOLDER = "\u2014";
|
|
2806
3080
|
function display(value) {
|
|
2807
3081
|
const clean = sanitizeForTerminal(value ?? "");
|
|
@@ -2809,8 +3083,8 @@ function display(value) {
|
|
|
2809
3083
|
}
|
|
2810
3084
|
async function performWhoami(ctx) {
|
|
2811
3085
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2812
|
-
const { body } = await personalGet(opts,
|
|
2813
|
-
const sessions = (0,
|
|
3086
|
+
const { body } = await personalGet(opts, import_core32.OAUTH_SESSIONS_BASE);
|
|
3087
|
+
const sessions = (0, import_core31.unwrapDataArray)(body);
|
|
2814
3088
|
const current = sessions.find((s) => s.is_current);
|
|
2815
3089
|
const localLoginAt = loadPersonalCredentials()?.session_created_at ?? null;
|
|
2816
3090
|
if (ctx.format === "json") {
|
|
@@ -2862,15 +3136,15 @@ function registerLogoutCommand(program2) {
|
|
|
2862
3136
|
}
|
|
2863
3137
|
|
|
2864
3138
|
// src/commands/sessions/list.ts
|
|
2865
|
-
var import_core32 = require("@wport/core");
|
|
2866
3139
|
var import_core33 = require("@wport/core");
|
|
3140
|
+
var import_core34 = require("@wport/core");
|
|
2867
3141
|
function formatDate5(value) {
|
|
2868
3142
|
return value ? String(value).slice(0, 10) : "";
|
|
2869
3143
|
}
|
|
2870
3144
|
async function runSessionsList(ctx) {
|
|
2871
3145
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2872
|
-
const { body } = await personalGet(opts,
|
|
2873
|
-
const sessions = (0,
|
|
3146
|
+
const { body } = await personalGet(opts, import_core34.OAUTH_SESSIONS_BASE);
|
|
3147
|
+
const sessions = (0, import_core33.unwrapDataArray)(body);
|
|
2874
3148
|
if (ctx.format === "json") {
|
|
2875
3149
|
printJson(sessions);
|
|
2876
3150
|
return;
|
|
@@ -2894,8 +3168,8 @@ function registerSessionsList(parent) {
|
|
|
2894
3168
|
}
|
|
2895
3169
|
|
|
2896
3170
|
// src/commands/sessions/revoke.ts
|
|
2897
|
-
var import_core34 = require("@wport/core");
|
|
2898
3171
|
var import_core35 = require("@wport/core");
|
|
3172
|
+
var import_core36 = require("@wport/core");
|
|
2899
3173
|
async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
2900
3174
|
const hasEncId = encId !== void 0;
|
|
2901
3175
|
if (hasEncId === allOthers) {
|
|
@@ -2903,8 +3177,8 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
|
2903
3177
|
}
|
|
2904
3178
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
2905
3179
|
if (allOthers) {
|
|
2906
|
-
const { body } = await personalDelete(opts, `${
|
|
2907
|
-
const result = (0,
|
|
3180
|
+
const { body } = await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/others`);
|
|
3181
|
+
const result = (0, import_core36.unwrapDataResponse)(body);
|
|
2908
3182
|
if (ctx.format === "json") {
|
|
2909
3183
|
printJson(result);
|
|
2910
3184
|
return;
|
|
@@ -2915,7 +3189,7 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
|
|
|
2915
3189
|
}
|
|
2916
3190
|
const trimmed = encId.trim();
|
|
2917
3191
|
if (!trimmed) throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
|
|
2918
|
-
await personalDelete(opts, `${
|
|
3192
|
+
await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
|
|
2919
3193
|
if (ctx.format === "json") {
|
|
2920
3194
|
printJson({ enc_id: trimmed, revoked: true });
|
|
2921
3195
|
return;
|
|
@@ -2938,18 +3212,18 @@ function registerSessionsCommand(program2) {
|
|
|
2938
3212
|
}
|
|
2939
3213
|
|
|
2940
3214
|
// src/commands/personal/resumes/schema.ts
|
|
2941
|
-
var
|
|
3215
|
+
var import_core37 = require("@wport/core");
|
|
2942
3216
|
function registerPersonalResumesSchema(parent) {
|
|
2943
3217
|
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,
|
|
3218
|
+
printJson((0, import_core37.buildAggregateJsonSchema)(opts.section));
|
|
2945
3219
|
});
|
|
2946
3220
|
}
|
|
2947
3221
|
|
|
2948
3222
|
// src/commands/personal/resumes/validate.ts
|
|
2949
|
-
var
|
|
3223
|
+
var import_core38 = require("@wport/core");
|
|
2950
3224
|
function runResumesValidate(ctx, filePath) {
|
|
2951
3225
|
const input = readJsonInput(filePath, { timeoutMs: ctx.timeoutMs });
|
|
2952
|
-
const issues = (0,
|
|
3226
|
+
const issues = (0, import_core38.validateAggregate)(input);
|
|
2953
3227
|
if (issues.length === 0) {
|
|
2954
3228
|
if (ctx.format === "json") {
|
|
2955
3229
|
printJson({ valid: true });
|
|
@@ -2977,9 +3251,9 @@ function registerPersonalResumesValidate(parent) {
|
|
|
2977
3251
|
|
|
2978
3252
|
// src/commands/personal/resumes/template.ts
|
|
2979
3253
|
var import_node_fs8 = require("fs");
|
|
2980
|
-
var
|
|
3254
|
+
var import_core39 = require("@wport/core");
|
|
2981
3255
|
function runResumesTemplate(outPath) {
|
|
2982
|
-
const template = (0,
|
|
3256
|
+
const template = (0, import_core39.buildTemplate)();
|
|
2983
3257
|
if (outPath === void 0) {
|
|
2984
3258
|
printJson(template);
|
|
2985
3259
|
return;
|
|
@@ -3003,8 +3277,8 @@ function registerPersonalResumesTemplate(parent) {
|
|
|
3003
3277
|
}
|
|
3004
3278
|
|
|
3005
3279
|
// src/commands/personal/resumes/list.ts
|
|
3006
|
-
var import_core39 = require("@wport/core");
|
|
3007
3280
|
var import_core40 = require("@wport/core");
|
|
3281
|
+
var import_core41 = require("@wport/core");
|
|
3008
3282
|
var MINIMAL_LIST_FIELDS4 = ["enc_id", "name", "updated_at", "is_complete", "is_published"];
|
|
3009
3283
|
function formatDate6(value) {
|
|
3010
3284
|
return value ? String(value).slice(0, 10) : "";
|
|
@@ -3014,8 +3288,8 @@ function formatQuotaLine(quota) {
|
|
|
3014
3288
|
return `${quota.used}/${quota.max_resumes} used, ${status}.`;
|
|
3015
3289
|
}
|
|
3016
3290
|
async function fetchResumeList(opts) {
|
|
3017
|
-
const { body } = await personalGet(opts,
|
|
3018
|
-
return (0,
|
|
3291
|
+
const { body } = await personalGet(opts, import_core41.PERSONAL_RESUMES_BASE);
|
|
3292
|
+
return (0, import_core40.unwrapDataResponse)(body);
|
|
3019
3293
|
}
|
|
3020
3294
|
async function runResumesList(ctx, flags) {
|
|
3021
3295
|
if (flags.fields && flags.minimal) {
|
|
@@ -3048,20 +3322,20 @@ function registerPersonalResumesList(parent) {
|
|
|
3048
3322
|
}
|
|
3049
3323
|
|
|
3050
3324
|
// src/commands/personal/resumes/view.ts
|
|
3051
|
-
var import_core41 = require("@wport/core");
|
|
3052
3325
|
var import_core42 = require("@wport/core");
|
|
3053
3326
|
var import_core43 = require("@wport/core");
|
|
3327
|
+
var import_core44 = require("@wport/core");
|
|
3054
3328
|
async function fetchResumeAggregate(opts, encId) {
|
|
3055
3329
|
const trimmed = encId.trim();
|
|
3056
3330
|
if (!trimmed) {
|
|
3057
3331
|
throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
|
|
3058
3332
|
}
|
|
3059
|
-
const { body } = await personalGet(opts, `${
|
|
3060
|
-
return (0,
|
|
3333
|
+
const { body } = await personalGet(opts, `${import_core43.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
|
|
3334
|
+
return (0, import_core42.unwrapDataResponse)(body);
|
|
3061
3335
|
}
|
|
3062
3336
|
function summarizeSections(resume) {
|
|
3063
3337
|
const rows = [{ section: "name", summary: resume.name }];
|
|
3064
|
-
for (const def of
|
|
3338
|
+
for (const def of import_core44.SECTIONS) {
|
|
3065
3339
|
rows.push({ section: def.key, summary: summarizeSection(def, resume) });
|
|
3066
3340
|
}
|
|
3067
3341
|
return rows;
|
|
@@ -3139,15 +3413,15 @@ function registerPersonalResumesExport(parent) {
|
|
|
3139
3413
|
}
|
|
3140
3414
|
|
|
3141
3415
|
// src/commands/personal/resumes/create.ts
|
|
3142
|
-
var
|
|
3416
|
+
var import_core48 = require("@wport/core");
|
|
3143
3417
|
|
|
3144
3418
|
// src/lib/resume-orchestrator.ts
|
|
3145
|
-
var
|
|
3146
|
-
var import_core44 = require("@wport/core");
|
|
3419
|
+
var import_node_crypto12 = require("crypto");
|
|
3147
3420
|
var import_core45 = require("@wport/core");
|
|
3148
3421
|
var import_core46 = require("@wport/core");
|
|
3422
|
+
var import_core47 = require("@wport/core");
|
|
3149
3423
|
function freshIdempotencyKey() {
|
|
3150
|
-
return { idempotencyKey: (0,
|
|
3424
|
+
return { idempotencyKey: (0, import_node_crypto12.randomUUID)() };
|
|
3151
3425
|
}
|
|
3152
3426
|
function describeError(err) {
|
|
3153
3427
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -3160,8 +3434,8 @@ function extractErrorCode(body) {
|
|
|
3160
3434
|
}
|
|
3161
3435
|
async function createShell(opts) {
|
|
3162
3436
|
try {
|
|
3163
|
-
const { body } = await personalPost(opts,
|
|
3164
|
-
return (0,
|
|
3437
|
+
const { body } = await personalPost(opts, import_core46.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
|
|
3438
|
+
return (0, import_core45.unwrapDataResponse)(body).enc_id;
|
|
3165
3439
|
} catch (err) {
|
|
3166
3440
|
if (err instanceof ServerClientHttpError) {
|
|
3167
3441
|
const code = extractErrorCode(err.body);
|
|
@@ -3182,7 +3456,7 @@ async function createShell(opts) {
|
|
|
3182
3456
|
}
|
|
3183
3457
|
}
|
|
3184
3458
|
async function renameResume(opts, encId, name) {
|
|
3185
|
-
await personalPut(opts, `${
|
|
3459
|
+
await personalPut(opts, `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
|
|
3186
3460
|
}
|
|
3187
3461
|
function toWorkExperienceWriteItem(item) {
|
|
3188
3462
|
const { is_current, ...rest } = item;
|
|
@@ -3194,8 +3468,8 @@ function splitItemEncId(item) {
|
|
|
3194
3468
|
return [valid, rest];
|
|
3195
3469
|
}
|
|
3196
3470
|
async function writeSection(opts, encId, key, value, mode) {
|
|
3197
|
-
const plan =
|
|
3198
|
-
const base = `${
|
|
3471
|
+
const plan = import_core46.SECTION_WRITE_PLAN[key];
|
|
3472
|
+
const base = `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
|
|
3199
3473
|
switch (plan.kind) {
|
|
3200
3474
|
case "per-item-post": {
|
|
3201
3475
|
for (const item of value) {
|
|
@@ -3262,7 +3536,7 @@ async function createAggregate(opts, aggregate) {
|
|
|
3262
3536
|
if (aggregate.name !== void 0) {
|
|
3263
3537
|
reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
|
|
3264
3538
|
}
|
|
3265
|
-
for (const section of
|
|
3539
|
+
for (const section of import_core47.SECTIONS) {
|
|
3266
3540
|
const value = aggregate[section.key];
|
|
3267
3541
|
if (value === void 0) continue;
|
|
3268
3542
|
reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "create")));
|
|
@@ -3272,9 +3546,9 @@ async function createAggregate(opts, aggregate) {
|
|
|
3272
3546
|
async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
3273
3547
|
const reports = [];
|
|
3274
3548
|
if (onlySection !== void 0) {
|
|
3275
|
-
const section = (0,
|
|
3549
|
+
const section = (0, import_core47.getSection)(onlySection);
|
|
3276
3550
|
if (!section) {
|
|
3277
|
-
const allowed =
|
|
3551
|
+
const allowed = import_core47.SECTIONS.map((s) => s.key).join(", ");
|
|
3278
3552
|
throw new CliError(`Unknown section "${onlySection}". Allowed: ${allowed}`, ExitCode.InvalidArgument);
|
|
3279
3553
|
}
|
|
3280
3554
|
const value = aggregate[onlySection];
|
|
@@ -3287,7 +3561,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
|
3287
3561
|
if (aggregate.name !== void 0) {
|
|
3288
3562
|
reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
|
|
3289
3563
|
}
|
|
3290
|
-
for (const section of
|
|
3564
|
+
for (const section of import_core47.SECTIONS) {
|
|
3291
3565
|
const value = aggregate[section.key];
|
|
3292
3566
|
if (value === void 0) continue;
|
|
3293
3567
|
reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "update")));
|
|
@@ -3298,7 +3572,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
|
|
|
3298
3572
|
// src/commands/personal/resumes/create.ts
|
|
3299
3573
|
async function runResumesCreate(ctx, filePath) {
|
|
3300
3574
|
const input = readJsonObject(filePath, { timeoutMs: ctx.timeoutMs });
|
|
3301
|
-
const issues = (0,
|
|
3575
|
+
const issues = (0, import_core48.validateAggregate)(input);
|
|
3302
3576
|
if (issues.length > 0) {
|
|
3303
3577
|
if (ctx.format === "json") {
|
|
3304
3578
|
printJson({ valid: false, issues });
|
|
@@ -3390,9 +3664,9 @@ function registerPersonalResumesUpdate(parent) {
|
|
|
3390
3664
|
}
|
|
3391
3665
|
|
|
3392
3666
|
// src/commands/personal/resumes/copy.ts
|
|
3393
|
-
var
|
|
3394
|
-
var import_core48 = require("@wport/core");
|
|
3667
|
+
var import_node_crypto13 = require("crypto");
|
|
3395
3668
|
var import_core49 = require("@wport/core");
|
|
3669
|
+
var import_core50 = require("@wport/core");
|
|
3396
3670
|
function requireEncId3(encId) {
|
|
3397
3671
|
const trimmed = encId.trim();
|
|
3398
3672
|
if (!trimmed) {
|
|
@@ -3411,12 +3685,12 @@ function printCopyResult(ctx, sourceEncId, newEncId) {
|
|
|
3411
3685
|
async function runResumesCopy(ctx, encId, name) {
|
|
3412
3686
|
const trimmed = requireEncId3(encId);
|
|
3413
3687
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3414
|
-
const { body } = await personalPost(opts, `${
|
|
3415
|
-
const { enc_id: newEncId } = (0,
|
|
3688
|
+
const { body } = await personalPost(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/duplicate`, {}, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
|
|
3689
|
+
const { enc_id: newEncId } = (0, import_core49.unwrapDataResponse)(body);
|
|
3416
3690
|
printCopyResult(ctx, trimmed, newEncId);
|
|
3417
3691
|
if (name === void 0) return;
|
|
3418
3692
|
try {
|
|
3419
|
-
await personalPut(opts, `${
|
|
3693
|
+
await personalPut(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
|
|
3420
3694
|
} catch (err) {
|
|
3421
3695
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3422
3696
|
throw new CliError(
|
|
@@ -3432,9 +3706,9 @@ function registerPersonalResumesCopy(parent) {
|
|
|
3432
3706
|
}
|
|
3433
3707
|
|
|
3434
3708
|
// src/commands/personal/resumes/publish.ts
|
|
3435
|
-
var
|
|
3436
|
-
var import_core50 = require("@wport/core");
|
|
3709
|
+
var import_node_crypto14 = require("crypto");
|
|
3437
3710
|
var import_core51 = require("@wport/core");
|
|
3711
|
+
var import_core52 = require("@wport/core");
|
|
3438
3712
|
function requireEncId4(encId) {
|
|
3439
3713
|
const trimmed = encId.trim();
|
|
3440
3714
|
if (!trimmed) {
|
|
@@ -3448,11 +3722,11 @@ async function runResumesPublishTransition(ctx, encId, action) {
|
|
|
3448
3722
|
const targetStatus = action === "publish";
|
|
3449
3723
|
const { body } = await personalPatch(
|
|
3450
3724
|
opts,
|
|
3451
|
-
`${
|
|
3725
|
+
`${import_core52.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
|
|
3452
3726
|
{ target_status: targetStatus },
|
|
3453
|
-
{ idempotencyKey: (0,
|
|
3727
|
+
{ idempotencyKey: (0, import_node_crypto14.randomUUID)() }
|
|
3454
3728
|
);
|
|
3455
|
-
const result = (0,
|
|
3729
|
+
const result = (0, import_core51.unwrapDataResponse)(body);
|
|
3456
3730
|
if (ctx.format === "json") {
|
|
3457
3731
|
printJson({ enc_id: trimmed, is_published: result.is_published });
|
|
3458
3732
|
return;
|
|
@@ -3473,8 +3747,8 @@ function registerPersonalResumesUnpublish(parent) {
|
|
|
3473
3747
|
}
|
|
3474
3748
|
|
|
3475
3749
|
// src/commands/personal/resumes/delete.ts
|
|
3476
|
-
var
|
|
3477
|
-
var
|
|
3750
|
+
var import_node_crypto15 = require("crypto");
|
|
3751
|
+
var import_core53 = require("@wport/core");
|
|
3478
3752
|
function requireEncId5(encId) {
|
|
3479
3753
|
const trimmed = encId.trim();
|
|
3480
3754
|
if (!trimmed) {
|
|
@@ -3488,7 +3762,7 @@ async function runResumesDelete(ctx, encId, confirm) {
|
|
|
3488
3762
|
}
|
|
3489
3763
|
const trimmed = requireEncId5(encId);
|
|
3490
3764
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3491
|
-
await personalDelete(opts, `${
|
|
3765
|
+
await personalDelete(opts, `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
|
|
3492
3766
|
if (ctx.format === "json") {
|
|
3493
3767
|
printJson({ enc_id: trimmed, deleted: true });
|
|
3494
3768
|
return;
|
|
@@ -3520,9 +3794,9 @@ function registerPersonalResumesCommand(parent) {
|
|
|
3520
3794
|
}
|
|
3521
3795
|
|
|
3522
3796
|
// src/commands/personal/apply/index.ts
|
|
3523
|
-
var
|
|
3797
|
+
var import_node_crypto16 = require("crypto");
|
|
3524
3798
|
var import_node_fs11 = require("fs");
|
|
3525
|
-
var
|
|
3799
|
+
var import_core54 = require("@wport/core");
|
|
3526
3800
|
|
|
3527
3801
|
// src/commands/personal/apply/message-input.ts
|
|
3528
3802
|
var import_node_fs10 = require("fs");
|
|
@@ -3604,7 +3878,7 @@ async function runPersonalApply(ctx, args) {
|
|
|
3604
3878
|
const body = { enc_job_id: args.encJobId, enc_resume_id: args.encResumeId, application_message: args.message };
|
|
3605
3879
|
let result;
|
|
3606
3880
|
try {
|
|
3607
|
-
result = await personalPost(opts,
|
|
3881
|
+
result = await personalPost(opts, import_core54.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
|
|
3608
3882
|
} catch (err) {
|
|
3609
3883
|
rethrowApplyError(err);
|
|
3610
3884
|
}
|
|
@@ -3655,7 +3929,7 @@ async function runPersonalApplyBatch(ctx, args) {
|
|
|
3655
3929
|
const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
|
|
3656
3930
|
let result;
|
|
3657
3931
|
try {
|
|
3658
|
-
result = await personalPost(opts, `${
|
|
3932
|
+
result = await personalPost(opts, `${import_core54.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
|
|
3659
3933
|
} catch (err) {
|
|
3660
3934
|
rethrowApplyError(err);
|
|
3661
3935
|
}
|
|
@@ -3683,7 +3957,7 @@ function registerPersonalCommand(program2) {
|
|
|
3683
3957
|
|
|
3684
3958
|
// src/index.ts
|
|
3685
3959
|
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.
|
|
3960
|
+
program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.10.0", "-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
3961
|
registerJobsCommand(program);
|
|
3688
3962
|
registerConfigCommand(program);
|
|
3689
3963
|
registerDoctorCommand(program);
|