@wport/cli 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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.10.1"),
390
+ userAgent: (0, import_core2.buildUserAgent)("wport-cli", "0.10.2"),
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.10.1"),
635
+ userAgent: (0, import_core3.buildUserAgent)("wport-cli", "0.10.2"),
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.10.1"),
1076
+ "User-Agent": (0, import_core5.buildUserAgent)("wport-cli", "0.10.2"),
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.10.1"}`);
1159
+ line(`wport-cli ${"0.10.2"}`);
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.10.1"),
1219
+ userAgent: (0, import_core7.buildUserAgent)("wport-cli", "0.10.2"),
1220
1220
  source: CLI_SOURCE
1221
1221
  });
1222
1222
  const { response } = await client.GET("/api/jobs/search", { params: { query: { pageSize: 1 } } });
@@ -1246,7 +1246,7 @@ 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.10.1"), source: CLI_SOURCE };
1249
+ return { ...opts, userAgent: (0, import_core8.buildUserAgent)("wport-cli", "0.10.2"), source: CLI_SOURCE };
1250
1250
  }
1251
1251
  function extractErrorCodeBody(body) {
1252
1252
  if (!body || typeof body !== "object") return void 0;
@@ -2017,9 +2017,15 @@ function registerEnterpriseCompanyView(parent) {
2017
2017
 
2018
2018
  // src/commands/enterprise/company/update.ts
2019
2019
  var import_node_crypto5 = require("crypto");
2020
- var import_core19 = require("@wport/core");
2020
+ var import_core20 = require("@wport/core");
2021
2021
 
2022
2022
  // src/commands/enterprise/company/block-replace-shared.ts
2023
+ var import_core19 = require("@wport/core");
2024
+ function getEnterpriseErrorCode(err) {
2025
+ if (!(err instanceof import_core19.WportHttpError) || !err.body || typeof err.body !== "object") return void 0;
2026
+ const code = err.body.error_code;
2027
+ return typeof code === "string" ? code : void 0;
2028
+ }
2023
2029
  function assertValidSubmittedItems(value, label) {
2024
2030
  if (!Array.isArray(value)) {
2025
2031
  throw new InvalidArgumentError(
@@ -2134,7 +2140,7 @@ async function buildCompanyUpdatePayloads(input, ctx, apiKey) {
2134
2140
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2135
2141
  "/company"
2136
2142
  );
2137
- const current = (0, import_core19.unwrapDataResponse)(body);
2143
+ const current = (0, import_core20.unwrapDataResponse)(body);
2138
2144
  const missingContractFields = CONTRACT_REQUIRED_GET_FIELDS.filter((f) => !(f in current));
2139
2145
  if (missingContractFields.length > 0) {
2140
2146
  throw new CliError(
@@ -2226,7 +2232,7 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
2226
2232
  const { body } = await enterprisePatch2(requestOpts, "/company/basic", payloads.basic, {
2227
2233
  idempotencyKey: basicKey
2228
2234
  });
2229
- basicResultCompany = (0, import_core19.unwrapDataResponse)(body);
2235
+ basicResultCompany = (0, import_core20.unwrapDataResponse)(body);
2230
2236
  }
2231
2237
  if (!needsDescriptions) {
2232
2238
  printCompanyResult(basicResultCompany, ctx.format);
@@ -2244,12 +2250,23 @@ async function runCompanyUpdate(ctx, apiKey, source, idempotencyFlags, options =
2244
2250
  ...needsVideoLinks ? { ifMatch: payloads.videoLinksRevision } : {}
2245
2251
  }
2246
2252
  );
2247
- const result = (0, import_core19.unwrapDataResponse)(body);
2253
+ const result = (0, import_core20.unwrapDataResponse)(body);
2248
2254
  printCompanyResult(result.company, ctx.format);
2249
2255
  } catch (err) {
2250
2256
  if (needsVideoLinks && err instanceof ServerClientHttpError && err.status === 409) {
2257
+ const errorCode = getEnterpriseErrorCode(err);
2258
+ if (errorCode === "idempotency_conflict") {
2259
+ throw new InvalidArgumentError(
2260
+ "This Idempotency-Key was already used for different request content; change the key (or omit --idempotency-key to let the CLI generate one)."
2261
+ );
2262
+ }
2263
+ if (errorCode !== "profile_revision_conflict") {
2264
+ throw new InvalidArgumentError(
2265
+ 'Request rejected with an unclassified 409 conflict while updating "video_links"; the CLI will not auto-retry.'
2266
+ );
2267
+ }
2251
2268
  const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
2252
- const freshCurrent = (0, import_core19.unwrapDataResponse)(freshBody);
2269
+ const freshCurrent = (0, import_core20.unwrapDataResponse)(freshBody);
2253
2270
  const freshVideoLinks = freshCurrent.video_links ?? [];
2254
2271
  const diff = summarizeItemsDiff(payloads.currentVideoLinks ?? [], freshVideoLinks);
2255
2272
  const partialBody = isDescriptionsPartialFailureBody(err.body) ? err.body : void 0;
@@ -2334,7 +2351,7 @@ function registerEnterpriseCompanyUpdate(parent) {
2334
2351
  var import_node_crypto6 = require("crypto");
2335
2352
  var import_node_fs7 = require("fs");
2336
2353
  var import_node_path3 = require("path");
2337
- var import_core20 = require("@wport/core");
2354
+ var import_core21 = require("@wport/core");
2338
2355
  var EXTENSION_TO_CONTENT_TYPE = {
2339
2356
  ".png": "image/png",
2340
2357
  ".jpg": "image/jpeg",
@@ -2392,13 +2409,13 @@ async function runCompanyLogoUpload(ctx, apiKey, path, idempotencyFlags) {
2392
2409
  { content_type: contentType, file_size: fileSize },
2393
2410
  { idempotencyKey: presignKey }
2394
2411
  );
2395
- const presign = (0, import_core20.unwrapDataResponse)(presignBody);
2412
+ const presign = (0, import_core21.unwrapDataResponse)(presignBody);
2396
2413
  const putRequest = new Request(presign.upload_url, {
2397
2414
  method: "PUT",
2398
2415
  headers: { "Content-Type": contentType },
2399
2416
  body: bytes
2400
2417
  });
2401
- const putResponse = await (0, import_core20.fetchWithTimeout)(putRequest, ctx.timeoutMs);
2418
+ const putResponse = await (0, import_core21.fetchWithTimeout)(putRequest, ctx.timeoutMs);
2402
2419
  if (!putResponse.ok) {
2403
2420
  throw new NetworkError(`Failed to upload file to S3: HTTP ${putResponse.status}`);
2404
2421
  }
@@ -2408,7 +2425,7 @@ async function runCompanyLogoUpload(ctx, apiKey, path, idempotencyFlags) {
2408
2425
  { s3_key: presign.s3_key },
2409
2426
  { idempotencyKey: confirmKey }
2410
2427
  );
2411
- const result = (0, import_core20.unwrapDataResponse)(confirmBody);
2428
+ const result = (0, import_core21.unwrapDataResponse)(confirmBody);
2412
2429
  printLogoResult(result, ctx.format);
2413
2430
  }
2414
2431
  function registerEnterpriseCompanyLogo(parent) {
@@ -2423,7 +2440,7 @@ function registerEnterpriseCompanyLogo(parent) {
2423
2440
 
2424
2441
  // src/commands/enterprise/company/replace.ts
2425
2442
  var import_node_crypto7 = require("crypto");
2426
- var import_core21 = require("@wport/core");
2443
+ var import_core22 = require("@wport/core");
2427
2444
  var REPLACE_SECTIONS = ["pain-points", "awards", "milestones", "qa-items"];
2428
2445
  var SECTION_CONFIG = {
2429
2446
  "pain-points": {
@@ -2478,7 +2495,7 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2478
2495
  const items = assertValidSubmittedItems(input.items, "items");
2479
2496
  const requestOpts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey };
2480
2497
  const { body: getBody } = await enterpriseGet2(requestOpts, "/company");
2481
- const current = (0, import_core21.unwrapDataResponse)(getBody);
2498
+ const current = (0, import_core22.unwrapDataResponse)(getBody);
2482
2499
  const currentItems = current[config.dataKey] ?? [];
2483
2500
  const revision = current.block_revisions?.[config.dataKey];
2484
2501
  if (!revision) {
@@ -2491,12 +2508,23 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2491
2508
  enforceDeletionConfirmation(section, deletions, confirm, ctx.color);
2492
2509
  try {
2493
2510
  const { body } = await enterprisePut2(requestOpts, config.path, { items }, { idempotencyKey, ifMatch: revision });
2494
- const result = (0, import_core21.unwrapDataResponse)(body);
2511
+ const result = (0, import_core22.unwrapDataResponse)(body);
2495
2512
  printReplaceResult(result, config, ctx.format, ctx.color);
2496
2513
  } catch (err) {
2497
- if (err instanceof import_core21.WportHttpError && err.status === 409) {
2514
+ if (err instanceof import_core22.WportHttpError && err.status === 409) {
2515
+ const errorCode = getEnterpriseErrorCode(err);
2516
+ if (errorCode === "idempotency_conflict") {
2517
+ throw new InvalidArgumentError(
2518
+ "This Idempotency-Key was already used for different request content; change the key (or omit --idempotency-key to let the CLI generate one)."
2519
+ );
2520
+ }
2521
+ if (errorCode !== "profile_revision_conflict") {
2522
+ throw new InvalidArgumentError(
2523
+ `Request rejected with an unclassified 409 conflict while replacing "${section}"; the CLI will not auto-retry.`
2524
+ );
2525
+ }
2498
2526
  const { body: freshBody } = await enterpriseGet2(requestOpts, "/company");
2499
- const freshCurrent = (0, import_core21.unwrapDataResponse)(freshBody);
2527
+ const freshCurrent = (0, import_core22.unwrapDataResponse)(freshBody);
2500
2528
  const freshItems = freshCurrent[config.dataKey] ?? [];
2501
2529
  const diff = summarizeItemsDiff(currentItems, freshItems);
2502
2530
  printWarn(`Server state for "${section}" changed since your read: ${diff}.`, ctx.color);
@@ -2509,7 +2537,7 @@ async function runCompanyReplace(ctx, apiKey, section, source, confirm, idempote
2509
2537
  }
2510
2538
  function registerEnterpriseCompanyReplace(parent) {
2511
2539
  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.`
2540
+ `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 hard-deleted. A \`company view --output json\` backup cannot be restored as-is after deletion: strip every \`enc_id\` first to recreate items with new IDs. Example: \`jq '{items: [.awards[] | del(.enc_id)]}' company-backup.json > awards-restore.json\`.`
2513
2541
  ).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
2542
  const ctx = resolveContext(command);
2515
2543
  const globals = command.optsWithGlobals();
@@ -2536,7 +2564,7 @@ function registerEnterpriseCompanyCommand(parent) {
2536
2564
  }
2537
2565
 
2538
2566
  // src/commands/enterprise/talents/list.ts
2539
- var import_core22 = require("@wport/core");
2567
+ var import_core23 = require("@wport/core");
2540
2568
  var DEFAULT_PAGE_SIZE = 20;
2541
2569
  var MINIMAL_LIST_FIELDS2 = ["enc_resume_id", "candidate_name", "applied_job_title", "applied_at"];
2542
2570
  function formatDate4(value) {
@@ -2559,7 +2587,7 @@ async function runEnterpriseTalentsList(ctx, apiKey, flags) {
2559
2587
  pageSize: flags.pageSize ?? DEFAULT_PAGE_SIZE
2560
2588
  }
2561
2589
  );
2562
- const paged = (0, import_core22.asPaginatedBody)(body);
2590
+ const paged = (0, import_core23.asPaginatedBody)(body);
2563
2591
  const projection = flags.minimal ? MINIMAL_LIST_FIELDS2 : flags.fields ? parseFieldsList(flags.fields) : void 0;
2564
2592
  if (projection || ctx.format === "json") {
2565
2593
  printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
@@ -2592,7 +2620,7 @@ function registerEnterpriseTalentsList(parent) {
2592
2620
  }
2593
2621
 
2594
2622
  // src/commands/enterprise/talents/view.ts
2595
- var import_core23 = require("@wport/core");
2623
+ var import_core24 = require("@wport/core");
2596
2624
  async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
2597
2625
  const trimmed = encResumeId.trim();
2598
2626
  if (!trimmed) {
@@ -2602,7 +2630,7 @@ async function runEnterpriseTalentsView(ctx, apiKey, encResumeId, flags) {
2602
2630
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2603
2631
  `/talents/${encodeURIComponent(trimmed)}`
2604
2632
  );
2605
- const resume = (0, import_core23.unwrapDataResponse)(body);
2633
+ const resume = (0, import_core24.unwrapDataResponse)(body);
2606
2634
  if (flags.fields) {
2607
2635
  printJson(pickPaths(resume, parseFieldsList(flags.fields)));
2608
2636
  return;
@@ -2620,7 +2648,7 @@ function registerEnterpriseTalentsView(parent) {
2620
2648
 
2621
2649
  // src/commands/enterprise/talents/respond.ts
2622
2650
  var import_node_crypto8 = require("crypto");
2623
- var import_core24 = require("@wport/core");
2651
+ var import_core25 = require("@wport/core");
2624
2652
  function resolveRespondBody(flags, options = {}) {
2625
2653
  const hasBody = flags.body !== void 0;
2626
2654
  const hasBodyFile = flags.bodyFile !== void 0;
@@ -2652,7 +2680,7 @@ async function runEnterpriseTalentsRespond(ctx, apiKey, encResumeId, flags, idem
2652
2680
  payload,
2653
2681
  { idempotencyKey }
2654
2682
  );
2655
- const result = (0, import_core24.unwrapDataResponse)(respBody);
2683
+ const result = (0, import_core25.unwrapDataResponse)(respBody);
2656
2684
  if (ctx.format === "json") {
2657
2685
  printJson(result);
2658
2686
  return;
@@ -2681,7 +2709,7 @@ function registerEnterpriseTalentsCommand(parent) {
2681
2709
 
2682
2710
  // src/commands/enterprise/campaigns/create.ts
2683
2711
  var import_node_crypto9 = require("crypto");
2684
- var import_core25 = require("@wport/core");
2712
+ var import_core26 = require("@wport/core");
2685
2713
  async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
2686
2714
  const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
2687
2715
  const { body } = await enterprisePost2(
@@ -2690,7 +2718,7 @@ async function runCampaignCreate(ctx, apiKey, source, idempotencyKey) {
2690
2718
  campaignBody,
2691
2719
  { idempotencyKey }
2692
2720
  );
2693
- const created = (0, import_core25.unwrapDataResponse)(body);
2721
+ const created = (0, import_core26.unwrapDataResponse)(body);
2694
2722
  if (ctx.format === "json") {
2695
2723
  printJson(created);
2696
2724
  return;
@@ -2708,7 +2736,7 @@ function registerEnterpriseCampaignsCreate(parent) {
2708
2736
  }
2709
2737
 
2710
2738
  // src/commands/enterprise/campaigns/list.ts
2711
- var import_core26 = require("@wport/core");
2739
+ var import_core27 = require("@wport/core");
2712
2740
  var STATUS_MAP2 = { open: 1, closed: 0 };
2713
2741
  var MINIMAL_LIST_FIELDS3 = ["enc_id", "name", "status", "job_count"];
2714
2742
  function mapStatusFlag2(raw) {
@@ -2738,7 +2766,7 @@ async function runEnterpriseCampaignsList(ctx, apiKey, flags) {
2738
2766
  status: mapStatusFlag2(flags.status)
2739
2767
  }
2740
2768
  );
2741
- const paged = (0, import_core26.asPaginatedBody)(body);
2769
+ const paged = (0, import_core27.asPaginatedBody)(body);
2742
2770
  const projection = flags.minimal ? MINIMAL_LIST_FIELDS3 : flags.fields ? parseFieldsList(flags.fields) : void 0;
2743
2771
  if (projection || ctx.format === "json") {
2744
2772
  printJson(projection ? { ...paged, data: paged.data.map((row) => pickPaths(row, projection)) } : paged);
@@ -2771,7 +2799,7 @@ function registerEnterpriseCampaignsList(parent) {
2771
2799
 
2772
2800
  // src/commands/enterprise/campaigns/lifecycle.ts
2773
2801
  var import_node_crypto10 = require("crypto");
2774
- var import_core27 = require("@wport/core");
2802
+ var import_core28 = require("@wport/core");
2775
2803
  async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey) {
2776
2804
  const trimmed = requireEncId(encId);
2777
2805
  const { body } = await enterprisePatch2(
@@ -2780,7 +2808,7 @@ async function runCampaignTransition(ctx, apiKey, encId, action, idempotencyKey)
2780
2808
  {},
2781
2809
  { idempotencyKey }
2782
2810
  );
2783
- const result = (0, import_core27.unwrapDataResponse)(body);
2811
+ const result = (0, import_core28.unwrapDataResponse)(body);
2784
2812
  if (ctx.format === "json") {
2785
2813
  printJson(result);
2786
2814
  return;
@@ -2806,7 +2834,7 @@ function registerEnterpriseCampaignsUnpublish(parent) {
2806
2834
 
2807
2835
  // src/commands/enterprise/campaigns/update.ts
2808
2836
  var import_node_crypto11 = require("crypto");
2809
- var import_core28 = require("@wport/core");
2837
+ var import_core29 = require("@wport/core");
2810
2838
  async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
2811
2839
  const trimmed = requireEncId(encId);
2812
2840
  const campaignBody = readJsonObject(source, { timeoutMs: ctx.timeoutMs });
@@ -2816,7 +2844,7 @@ async function runCampaignUpdate(ctx, apiKey, encId, source, idempotencyKey) {
2816
2844
  campaignBody,
2817
2845
  { idempotencyKey }
2818
2846
  );
2819
- const updated = (0, import_core28.unwrapDataResponse)(body);
2847
+ const updated = (0, import_core29.unwrapDataResponse)(body);
2820
2848
  if (ctx.format === "json") {
2821
2849
  printJson(updated);
2822
2850
  return;
@@ -2834,7 +2862,7 @@ function registerEnterpriseCampaignsUpdate(parent) {
2834
2862
  }
2835
2863
 
2836
2864
  // src/commands/enterprise/campaigns/view.ts
2837
- var import_core29 = require("@wport/core");
2865
+ var import_core30 = require("@wport/core");
2838
2866
  async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
2839
2867
  const trimmed = encId.trim();
2840
2868
  if (!trimmed) {
@@ -2844,7 +2872,7 @@ async function runEnterpriseCampaignsView(ctx, apiKey, encId, flags) {
2844
2872
  { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs, apiKey },
2845
2873
  `/campaigns/${encodeURIComponent(trimmed)}`
2846
2874
  );
2847
- const campaign = (0, import_core29.unwrapDataResponse)(body);
2875
+ const campaign = (0, import_core30.unwrapDataResponse)(body);
2848
2876
  if (flags.fields) {
2849
2877
  printJson(pickPaths(campaign, parseFieldsList(flags.fields)));
2850
2878
  return;
@@ -2989,10 +3017,10 @@ function registerLoginCommand(program2) {
2989
3017
  }
2990
3018
 
2991
3019
  // src/commands/auth/whoami.ts
2992
- var import_core31 = require("@wport/core");
3020
+ var import_core32 = require("@wport/core");
2993
3021
 
2994
3022
  // src/lib/personal-client.ts
2995
- var import_core30 = require("@wport/core");
3023
+ var import_core31 = require("@wport/core");
2996
3024
  var EXPIRY_SKEW_MS = 3e4;
2997
3025
  var NOT_LOGGED_IN_MESSAGE = "Not logged in. Run `wport login`.";
2998
3026
  async function ensureFreshCredentials(opts) {
@@ -3021,7 +3049,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
3021
3049
  const headers = {
3022
3050
  Authorization: `Bearer ${accessToken}`,
3023
3051
  "Accept-Language": opts.locale,
3024
- "User-Agent": (0, import_core30.buildUserAgent)("wport-cli", "0.10.1"),
3052
+ "User-Agent": (0, import_core31.buildUserAgent)("wport-cli", "0.10.2"),
3025
3053
  "X-Source": CLI_SOURCE,
3026
3054
  Accept: "application/json"
3027
3055
  };
@@ -3032,7 +3060,7 @@ async function attemptRequest(opts, method, path, accessToken, body, query, extr
3032
3060
  headers,
3033
3061
  body: body !== void 0 ? JSON.stringify(body) : void 0
3034
3062
  });
3035
- const res = await (0, import_core30.fetchWithTimeout)(request, opts.timeoutMs);
3063
+ const res = await (0, import_core31.fetchWithTimeout)(request, opts.timeoutMs);
3036
3064
  const respBody = await res.json().catch(() => null);
3037
3065
  return { status: res.status, body: respBody, headers: res.headers };
3038
3066
  }
@@ -3064,13 +3092,13 @@ function personalDelete(opts, path, extra) {
3064
3092
  }
3065
3093
  function throwPersonalHttpError(status, body) {
3066
3094
  if (status === 401) {
3067
- const base = (0, import_core30.extractErrorMessage)(body) ?? `HTTP ${status}`;
3095
+ const base = (0, import_core31.extractErrorMessage)(body) ?? `HTTP ${status}`;
3068
3096
  throw new CliError(
3069
3097
  `${base} \u2014 Your session may have expired or the request was rejected. Run \`wport login\` to sign in again.`,
3070
3098
  ExitCode.ServerClientError
3071
3099
  );
3072
3100
  }
3073
- (0, import_core30.throwForHttpStatus)(status, body);
3101
+ (0, import_core31.throwForHttpStatus)(status, body);
3074
3102
  }
3075
3103
  function warnIfRateLimitLow2(headers) {
3076
3104
  const remaining = Number(headers.get("x-ratelimit-remaining"));
@@ -3081,7 +3109,7 @@ function warnIfRateLimitLow2(headers) {
3081
3109
  }
3082
3110
 
3083
3111
  // src/commands/auth/whoami.ts
3084
- var import_core32 = require("@wport/core");
3112
+ var import_core33 = require("@wport/core");
3085
3113
  var PLACEHOLDER = "\u2014";
3086
3114
  function display(value) {
3087
3115
  const clean = sanitizeForTerminal(value ?? "");
@@ -3089,8 +3117,8 @@ function display(value) {
3089
3117
  }
3090
3118
  async function performWhoami(ctx) {
3091
3119
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3092
- const { body } = await personalGet(opts, import_core32.OAUTH_SESSIONS_BASE);
3093
- const sessions = (0, import_core31.unwrapDataArray)(body);
3120
+ const { body } = await personalGet(opts, import_core33.OAUTH_SESSIONS_BASE);
3121
+ const sessions = (0, import_core32.unwrapDataArray)(body);
3094
3122
  const current = sessions.find((s) => s.is_current);
3095
3123
  const localLoginAt = loadPersonalCredentials()?.session_created_at ?? null;
3096
3124
  if (ctx.format === "json") {
@@ -3142,15 +3170,15 @@ function registerLogoutCommand(program2) {
3142
3170
  }
3143
3171
 
3144
3172
  // src/commands/sessions/list.ts
3145
- var import_core33 = require("@wport/core");
3146
3173
  var import_core34 = require("@wport/core");
3174
+ var import_core35 = require("@wport/core");
3147
3175
  function formatDate5(value) {
3148
3176
  return value ? String(value).slice(0, 10) : "";
3149
3177
  }
3150
3178
  async function runSessionsList(ctx) {
3151
3179
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3152
- const { body } = await personalGet(opts, import_core34.OAUTH_SESSIONS_BASE);
3153
- const sessions = (0, import_core33.unwrapDataArray)(body);
3180
+ const { body } = await personalGet(opts, import_core35.OAUTH_SESSIONS_BASE);
3181
+ const sessions = (0, import_core34.unwrapDataArray)(body);
3154
3182
  if (ctx.format === "json") {
3155
3183
  printJson(sessions);
3156
3184
  return;
@@ -3174,8 +3202,8 @@ function registerSessionsList(parent) {
3174
3202
  }
3175
3203
 
3176
3204
  // src/commands/sessions/revoke.ts
3177
- var import_core35 = require("@wport/core");
3178
3205
  var import_core36 = require("@wport/core");
3206
+ var import_core37 = require("@wport/core");
3179
3207
  async function runSessionsRevoke(ctx, encId, allOthers) {
3180
3208
  const hasEncId = encId !== void 0;
3181
3209
  if (hasEncId === allOthers) {
@@ -3183,8 +3211,8 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
3183
3211
  }
3184
3212
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3185
3213
  if (allOthers) {
3186
- const { body } = await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/others`);
3187
- const result = (0, import_core36.unwrapDataResponse)(body);
3214
+ const { body } = await personalDelete(opts, `${import_core36.OAUTH_SESSIONS_BASE}/others`);
3215
+ const result = (0, import_core37.unwrapDataResponse)(body);
3188
3216
  if (ctx.format === "json") {
3189
3217
  printJson(result);
3190
3218
  return;
@@ -3195,7 +3223,7 @@ async function runSessionsRevoke(ctx, encId, allOthers) {
3195
3223
  }
3196
3224
  const trimmed = encId.trim();
3197
3225
  if (!trimmed) throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
3198
- await personalDelete(opts, `${import_core35.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
3226
+ await personalDelete(opts, `${import_core36.OAUTH_SESSIONS_BASE}/${encodeURIComponent(trimmed)}`);
3199
3227
  if (ctx.format === "json") {
3200
3228
  printJson({ enc_id: trimmed, revoked: true });
3201
3229
  return;
@@ -3218,18 +3246,18 @@ function registerSessionsCommand(program2) {
3218
3246
  }
3219
3247
 
3220
3248
  // src/commands/personal/resumes/schema.ts
3221
- var import_core37 = require("@wport/core");
3249
+ var import_core38 = require("@wport/core");
3222
3250
  function registerPersonalResumesSchema(parent) {
3223
3251
  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) => {
3224
- printJson((0, import_core37.buildAggregateJsonSchema)(opts.section));
3252
+ printJson((0, import_core38.buildAggregateJsonSchema)(opts.section));
3225
3253
  });
3226
3254
  }
3227
3255
 
3228
3256
  // src/commands/personal/resumes/validate.ts
3229
- var import_core38 = require("@wport/core");
3257
+ var import_core39 = require("@wport/core");
3230
3258
  function runResumesValidate(ctx, filePath) {
3231
3259
  const input = readJsonInput(filePath, { timeoutMs: ctx.timeoutMs });
3232
- const issues = (0, import_core38.validateAggregate)(input);
3260
+ const issues = (0, import_core39.validateAggregate)(input);
3233
3261
  if (issues.length === 0) {
3234
3262
  if (ctx.format === "json") {
3235
3263
  printJson({ valid: true });
@@ -3257,9 +3285,9 @@ function registerPersonalResumesValidate(parent) {
3257
3285
 
3258
3286
  // src/commands/personal/resumes/template.ts
3259
3287
  var import_node_fs8 = require("fs");
3260
- var import_core39 = require("@wport/core");
3288
+ var import_core40 = require("@wport/core");
3261
3289
  function runResumesTemplate(outPath) {
3262
- const template = (0, import_core39.buildTemplate)();
3290
+ const template = (0, import_core40.buildTemplate)();
3263
3291
  if (outPath === void 0) {
3264
3292
  printJson(template);
3265
3293
  return;
@@ -3283,8 +3311,8 @@ function registerPersonalResumesTemplate(parent) {
3283
3311
  }
3284
3312
 
3285
3313
  // src/commands/personal/resumes/list.ts
3286
- var import_core40 = require("@wport/core");
3287
3314
  var import_core41 = require("@wport/core");
3315
+ var import_core42 = require("@wport/core");
3288
3316
  var MINIMAL_LIST_FIELDS4 = ["enc_id", "name", "updated_at", "is_complete", "is_published"];
3289
3317
  function formatDate6(value) {
3290
3318
  return value ? String(value).slice(0, 10) : "";
@@ -3294,8 +3322,8 @@ function formatQuotaLine(quota) {
3294
3322
  return `${quota.used}/${quota.max_resumes} used, ${status}.`;
3295
3323
  }
3296
3324
  async function fetchResumeList(opts) {
3297
- const { body } = await personalGet(opts, import_core41.PERSONAL_RESUMES_BASE);
3298
- return (0, import_core40.unwrapDataResponse)(body);
3325
+ const { body } = await personalGet(opts, import_core42.PERSONAL_RESUMES_BASE);
3326
+ return (0, import_core41.unwrapDataResponse)(body);
3299
3327
  }
3300
3328
  async function runResumesList(ctx, flags) {
3301
3329
  if (flags.fields && flags.minimal) {
@@ -3328,20 +3356,20 @@ function registerPersonalResumesList(parent) {
3328
3356
  }
3329
3357
 
3330
3358
  // src/commands/personal/resumes/view.ts
3331
- var import_core42 = require("@wport/core");
3332
3359
  var import_core43 = require("@wport/core");
3333
3360
  var import_core44 = require("@wport/core");
3361
+ var import_core45 = require("@wport/core");
3334
3362
  async function fetchResumeAggregate(opts, encId) {
3335
3363
  const trimmed = encId.trim();
3336
3364
  if (!trimmed) {
3337
3365
  throw new CliError("enc_id must not be empty", ExitCode.InvalidArgument);
3338
3366
  }
3339
- const { body } = await personalGet(opts, `${import_core43.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
3340
- return (0, import_core42.unwrapDataResponse)(body);
3367
+ const { body } = await personalGet(opts, `${import_core44.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`);
3368
+ return (0, import_core43.unwrapDataResponse)(body);
3341
3369
  }
3342
3370
  function summarizeSections(resume) {
3343
3371
  const rows = [{ section: "name", summary: resume.name }];
3344
- for (const def of import_core44.SECTIONS) {
3372
+ for (const def of import_core45.SECTIONS) {
3345
3373
  rows.push({ section: def.key, summary: summarizeSection(def, resume) });
3346
3374
  }
3347
3375
  return rows;
@@ -3419,13 +3447,13 @@ function registerPersonalResumesExport(parent) {
3419
3447
  }
3420
3448
 
3421
3449
  // src/commands/personal/resumes/create.ts
3422
- var import_core48 = require("@wport/core");
3450
+ var import_core49 = require("@wport/core");
3423
3451
 
3424
3452
  // src/lib/resume-orchestrator.ts
3425
3453
  var import_node_crypto12 = require("crypto");
3426
- var import_core45 = require("@wport/core");
3427
3454
  var import_core46 = require("@wport/core");
3428
3455
  var import_core47 = require("@wport/core");
3456
+ var import_core48 = require("@wport/core");
3429
3457
  function freshIdempotencyKey() {
3430
3458
  return { idempotencyKey: (0, import_node_crypto12.randomUUID)() };
3431
3459
  }
@@ -3440,8 +3468,8 @@ function extractErrorCode(body) {
3440
3468
  }
3441
3469
  async function createShell(opts) {
3442
3470
  try {
3443
- const { body } = await personalPost(opts, import_core46.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
3444
- return (0, import_core45.unwrapDataResponse)(body).enc_id;
3471
+ const { body } = await personalPost(opts, import_core47.PERSONAL_RESUMES_BASE, {}, freshIdempotencyKey());
3472
+ return (0, import_core46.unwrapDataResponse)(body).enc_id;
3445
3473
  } catch (err) {
3446
3474
  if (err instanceof ServerClientHttpError) {
3447
3475
  const code = extractErrorCode(err.body);
@@ -3462,7 +3490,7 @@ async function createShell(opts) {
3462
3490
  }
3463
3491
  }
3464
3492
  async function renameResume(opts, encId, name) {
3465
- await personalPut(opts, `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
3493
+ await personalPut(opts, `${import_core47.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}/name`, { name }, freshIdempotencyKey());
3466
3494
  }
3467
3495
  function toWorkExperienceWriteItem(item) {
3468
3496
  const { is_current, ...rest } = item;
@@ -3474,8 +3502,8 @@ function splitItemEncId(item) {
3474
3502
  return [valid, rest];
3475
3503
  }
3476
3504
  async function writeSection(opts, encId, key, value, mode) {
3477
- const plan = import_core46.SECTION_WRITE_PLAN[key];
3478
- const base = `${import_core46.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
3505
+ const plan = import_core47.SECTION_WRITE_PLAN[key];
3506
+ const base = `${import_core47.PERSONAL_RESUMES_BASE}/${encodeURIComponent(encId)}`;
3479
3507
  switch (plan.kind) {
3480
3508
  case "per-item-post": {
3481
3509
  for (const item of value) {
@@ -3542,7 +3570,7 @@ async function createAggregate(opts, aggregate) {
3542
3570
  if (aggregate.name !== void 0) {
3543
3571
  reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
3544
3572
  }
3545
- for (const section of import_core47.SECTIONS) {
3573
+ for (const section of import_core48.SECTIONS) {
3546
3574
  const value = aggregate[section.key];
3547
3575
  if (value === void 0) continue;
3548
3576
  reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "create")));
@@ -3552,9 +3580,9 @@ async function createAggregate(opts, aggregate) {
3552
3580
  async function updateAggregate(opts, encId, aggregate, onlySection) {
3553
3581
  const reports = [];
3554
3582
  if (onlySection !== void 0) {
3555
- const section = (0, import_core47.getSection)(onlySection);
3583
+ const section = (0, import_core48.getSection)(onlySection);
3556
3584
  if (!section) {
3557
- const allowed = import_core47.SECTIONS.map((s) => s.key).join(", ");
3585
+ const allowed = import_core48.SECTIONS.map((s) => s.key).join(", ");
3558
3586
  throw new CliError(`Unknown section "${onlySection}". Allowed: ${allowed}`, ExitCode.InvalidArgument);
3559
3587
  }
3560
3588
  const value = aggregate[onlySection];
@@ -3567,7 +3595,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
3567
3595
  if (aggregate.name !== void 0) {
3568
3596
  reports.push(await attemptStep("name", () => renameResume(opts, encId, aggregate.name)));
3569
3597
  }
3570
- for (const section of import_core47.SECTIONS) {
3598
+ for (const section of import_core48.SECTIONS) {
3571
3599
  const value = aggregate[section.key];
3572
3600
  if (value === void 0) continue;
3573
3601
  reports.push(await attemptStep(section.key, () => writeSection(opts, encId, section.key, value, "update")));
@@ -3578,7 +3606,7 @@ async function updateAggregate(opts, encId, aggregate, onlySection) {
3578
3606
  // src/commands/personal/resumes/create.ts
3579
3607
  async function runResumesCreate(ctx, filePath) {
3580
3608
  const input = readJsonObject(filePath, { timeoutMs: ctx.timeoutMs });
3581
- const issues = (0, import_core48.validateAggregate)(input);
3609
+ const issues = (0, import_core49.validateAggregate)(input);
3582
3610
  if (issues.length > 0) {
3583
3611
  if (ctx.format === "json") {
3584
3612
  printJson({ valid: false, issues });
@@ -3671,8 +3699,8 @@ function registerPersonalResumesUpdate(parent) {
3671
3699
 
3672
3700
  // src/commands/personal/resumes/copy.ts
3673
3701
  var import_node_crypto13 = require("crypto");
3674
- var import_core49 = require("@wport/core");
3675
3702
  var import_core50 = require("@wport/core");
3703
+ var import_core51 = require("@wport/core");
3676
3704
  function requireEncId3(encId) {
3677
3705
  const trimmed = encId.trim();
3678
3706
  if (!trimmed) {
@@ -3691,12 +3719,12 @@ function printCopyResult(ctx, sourceEncId, newEncId) {
3691
3719
  async function runResumesCopy(ctx, encId, name) {
3692
3720
  const trimmed = requireEncId3(encId);
3693
3721
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
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);
3722
+ const { body } = await personalPost(opts, `${import_core51.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/duplicate`, {}, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3723
+ const { enc_id: newEncId } = (0, import_core50.unwrapDataResponse)(body);
3696
3724
  printCopyResult(ctx, trimmed, newEncId);
3697
3725
  if (name === void 0) return;
3698
3726
  try {
3699
- await personalPut(opts, `${import_core50.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3727
+ await personalPut(opts, `${import_core51.PERSONAL_RESUMES_BASE}/${encodeURIComponent(newEncId)}/name`, { name }, { idempotencyKey: (0, import_node_crypto13.randomUUID)() });
3700
3728
  } catch (err) {
3701
3729
  const reason = err instanceof Error ? err.message : String(err);
3702
3730
  throw new CliError(
@@ -3713,8 +3741,8 @@ function registerPersonalResumesCopy(parent) {
3713
3741
 
3714
3742
  // src/commands/personal/resumes/publish.ts
3715
3743
  var import_node_crypto14 = require("crypto");
3716
- var import_core51 = require("@wport/core");
3717
3744
  var import_core52 = require("@wport/core");
3745
+ var import_core53 = require("@wport/core");
3718
3746
  function requireEncId4(encId) {
3719
3747
  const trimmed = encId.trim();
3720
3748
  if (!trimmed) {
@@ -3728,11 +3756,11 @@ async function runResumesPublishTransition(ctx, encId, action) {
3728
3756
  const targetStatus = action === "publish";
3729
3757
  const { body } = await personalPatch(
3730
3758
  opts,
3731
- `${import_core52.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
3759
+ `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}/published-status`,
3732
3760
  { target_status: targetStatus },
3733
3761
  { idempotencyKey: (0, import_node_crypto14.randomUUID)() }
3734
3762
  );
3735
- const result = (0, import_core51.unwrapDataResponse)(body);
3763
+ const result = (0, import_core52.unwrapDataResponse)(body);
3736
3764
  if (ctx.format === "json") {
3737
3765
  printJson({ enc_id: trimmed, is_published: result.is_published });
3738
3766
  return;
@@ -3754,7 +3782,7 @@ function registerPersonalResumesUnpublish(parent) {
3754
3782
 
3755
3783
  // src/commands/personal/resumes/delete.ts
3756
3784
  var import_node_crypto15 = require("crypto");
3757
- var import_core53 = require("@wport/core");
3785
+ var import_core54 = require("@wport/core");
3758
3786
  function requireEncId5(encId) {
3759
3787
  const trimmed = encId.trim();
3760
3788
  if (!trimmed) {
@@ -3768,7 +3796,7 @@ async function runResumesDelete(ctx, encId, confirm) {
3768
3796
  }
3769
3797
  const trimmed = requireEncId5(encId);
3770
3798
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3771
- await personalDelete(opts, `${import_core53.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
3799
+ await personalDelete(opts, `${import_core54.PERSONAL_RESUMES_BASE}/${encodeURIComponent(trimmed)}`, { idempotencyKey: (0, import_node_crypto15.randomUUID)() });
3772
3800
  if (ctx.format === "json") {
3773
3801
  printJson({ enc_id: trimmed, deleted: true });
3774
3802
  return;
@@ -3802,7 +3830,7 @@ function registerPersonalResumesCommand(parent) {
3802
3830
  // src/commands/personal/apply/index.ts
3803
3831
  var import_node_crypto16 = require("crypto");
3804
3832
  var import_node_fs11 = require("fs");
3805
- var import_core54 = require("@wport/core");
3833
+ var import_core55 = require("@wport/core");
3806
3834
 
3807
3835
  // src/commands/personal/apply/message-input.ts
3808
3836
  var import_node_fs10 = require("fs");
@@ -3884,7 +3912,7 @@ async function runPersonalApply(ctx, args) {
3884
3912
  const body = { enc_job_id: args.encJobId, enc_resume_id: args.encResumeId, application_message: args.message };
3885
3913
  let result;
3886
3914
  try {
3887
- result = await personalPost(opts, import_core54.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3915
+ result = await personalPost(opts, import_core55.PERSONAL_APPLICATIONS_BASE, body, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3888
3916
  } catch (err) {
3889
3917
  rethrowApplyError(err);
3890
3918
  }
@@ -3935,7 +3963,7 @@ async function runPersonalApplyBatch(ctx, args) {
3935
3963
  const opts = { baseUrl: ctx.baseUrl, locale: ctx.locale, timeoutMs: ctx.timeoutMs };
3936
3964
  let result;
3937
3965
  try {
3938
- result = await personalPost(opts, `${import_core54.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3966
+ result = await personalPost(opts, `${import_core55.PERSONAL_APPLICATIONS_BASE}/batch`, { applications: items }, { idempotencyKey: (0, import_node_crypto16.randomUUID)() });
3939
3967
  } catch (err) {
3940
3968
  rethrowApplyError(err);
3941
3969
  }
@@ -3963,7 +3991,7 @@ function registerPersonalCommand(program2) {
3963
3991
 
3964
3992
  // src/index.ts
3965
3993
  var program = new import_commander.Command();
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));
3994
+ program.name("wport").description("wport CLI \u2014 terminal interface to the W101 Talent Search Hub public API").version("0.10.2", "-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));
3967
3995
  registerJobsCommand(program);
3968
3996
  registerConfigCommand(program);
3969
3997
  registerDoctorCommand(program);