job-pro 1.0.12 → 1.0.14

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.
Files changed (2) hide show
  1. package/dist/index.js +55 -5
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -127,7 +127,8 @@ USAGE
127
127
  job-pro profile show print the loaded profile
128
128
  job-pro find <keyword> search ALL 50 companies in parallel
129
129
  [--limit N] [--companies a,b,c]
130
- [--timeout ms] [--compact]
130
+ [--timeout ms] [--apply-ready]
131
+ [--compact | --text]
131
132
  job-pro --version
132
133
  job-pro help
133
134
 
@@ -1087,10 +1088,23 @@ async function main() {
1087
1088
  }
1088
1089
  if (cmd === "find") {
1089
1090
  const compact = args.includes("--compact");
1091
+ const textMode = args.includes("--text");
1092
+ const applyReadyOnly = args.includes("--apply-ready");
1090
1093
  const keyword = args[1];
1091
1094
  if (!keyword || keyword.startsWith("--")) {
1092
- die(`usage: job-pro find <keyword> [--limit N] [--companies a,b,c] [--timeout ms] [--compact]`);
1095
+ die(`usage: job-pro find <keyword> [--limit N] [--companies a,b,c] [--timeout ms] [--apply-ready] [--compact | --text]`);
1093
1096
  }
1097
+ // Static apply-readiness map. Source of truth for what kind of submission
1098
+ // each adapter supports — kept in sync with apply-smoke's submit_kind tally.
1099
+ const ANON_ADAPTERS = new Set(["xpeng", "weride", "hoyoverse"]);
1100
+ const EXTERNAL_ADAPTERS = new Set(["hikvision", "cicc", "cainiao", "webank", "unitree"]);
1101
+ const applyStatusFor = (adapterKey) => {
1102
+ if (EXTERNAL_ADAPTERS.has(adapterKey))
1103
+ return "external";
1104
+ if (ANON_ADAPTERS.has(adapterKey))
1105
+ return "anon";
1106
+ return loadSession(adapterKey) ? "session" : "missing-session";
1107
+ };
1094
1108
  const { args: aLimit, value: limitStr } = popFlagValue(args, "--limit");
1095
1109
  const { args: aCompanies, value: companiesStr } = popFlagValue(aLimit, "--companies");
1096
1110
  const { args: aTimeout, value: timeoutStr } = popFlagValue(aCompanies, "--timeout");
@@ -1125,7 +1139,7 @@ async function main() {
1125
1139
  return { company, ok: false, count: 0, positions: [], message: r.message ?? "search failed", elapsed_ms: elapsed };
1126
1140
  }
1127
1141
  const positions = Array.isArray(r?.positions) ? r.positions.slice(0, limit) : [];
1128
- return { company, ok: true, count: positions.length, positions, elapsed_ms: elapsed };
1142
+ return { company, ok: true, count: positions.length, positions, apply_status: applyStatusFor(company), elapsed_ms: elapsed };
1129
1143
  }
1130
1144
  catch (err) {
1131
1145
  const elapsed = Date.now() - t0;
@@ -1138,8 +1152,44 @@ async function main() {
1138
1152
  }
1139
1153
  }));
1140
1154
  const totalMs = Date.now() - startedAt;
1141
- const withHits = settled.filter((r) => r.count > 0);
1155
+ const allHits = settled.filter((r) => r.count > 0);
1156
+ const withHits = applyReadyOnly
1157
+ ? allHits.filter((r) => r.apply_status === "anon" || r.apply_status === "session")
1158
+ : allHits;
1142
1159
  const total = withHits.reduce((s, r) => s + r.count, 0);
1160
+ const failed = settled.filter((r) => !r.ok).map((r) => ({ company: r.company, message: r.message }));
1161
+ if (textMode) {
1162
+ const STATUS_ICON = {
1163
+ anon: "✅",
1164
+ session: "🟢",
1165
+ "missing-session": "🟡",
1166
+ external: "⛔",
1167
+ };
1168
+ const filterNote = applyReadyOnly ? " [apply-ready only]" : "";
1169
+ console.log(`\nfind "${keyword}" — ${total} hit(s) across ${withHits.length}/${scope.length} companies (${totalMs}ms)${filterNote}\n`);
1170
+ for (const r of withHits) {
1171
+ const icon = STATUS_ICON[r.apply_status ?? ""] ?? "?";
1172
+ console.log(`${icon} ${r.company} (${r.count}) — ${r.apply_status}`);
1173
+ for (const p of r.positions) {
1174
+ const title = (p.title ?? "").trim().replace(/\s+/g, " ");
1175
+ const loc = (p.work_cities ?? "").trim();
1176
+ console.log(` ${p.post_id ?? "?"} ${title}${loc ? ` — ${loc}` : ""}`);
1177
+ if (p.apply_url)
1178
+ console.log(` ${p.apply_url}`);
1179
+ }
1180
+ console.log("");
1181
+ }
1182
+ const hiddenCount = allHits.length - withHits.length;
1183
+ if (applyReadyOnly && hiddenCount > 0) {
1184
+ console.log(`(${hiddenCount} company-bucket(s) hidden — missing-session / external)\n`);
1185
+ }
1186
+ if (failed.length > 0) {
1187
+ console.log(`Failed (${failed.length}):`);
1188
+ for (const f of failed)
1189
+ console.log(` ${f.company}: ${f.message}`);
1190
+ }
1191
+ return;
1192
+ }
1143
1193
  emit({
1144
1194
  ok: true,
1145
1195
  keyword,
@@ -1148,7 +1198,7 @@ async function main() {
1148
1198
  scanned_companies: scope.length,
1149
1199
  elapsed_ms: totalMs,
1150
1200
  results: withHits,
1151
- failed: settled.filter((r) => !r.ok).map((r) => ({ company: r.company, message: r.message })),
1201
+ failed,
1152
1202
  }, compact);
1153
1203
  return;
1154
1204
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "job-pro",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "description": "Query Chinese big-tech campus recruiting from your terminal. 50 companies, all 50 live. 46 via each company's own API; the 4 with no public canonical feed (Hikvision, CICC, Cainiao, WeBank) surfaced via Liepin as a clearly-labeled third-party fallback. No signup, no token, no server.",
5
5
  "homepage": "https://job.ha7ch.com",
6
6
  "repository": "https://github.com/HA7CH/job-pro",