@curviate/cli 0.1.0 → 0.3.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 +34 -0
- package/dist/{account-YOW2MCZS.js → account-3I63RFVN.js} +2 -2
- package/dist/chunk-42VUUKQ3.js +57 -0
- package/dist/chunk-7TWHAKKA.js +92 -0
- package/dist/{chunk-6JNCLLNY.js → chunk-QQRTODHN.js} +5 -0
- package/dist/{chunk-2NCPJJPC.js → chunk-UPNQPAJG.js} +3 -2
- package/dist/cli.js +13 -13
- package/dist/{company-IKVDW7MX.js → company-EARWRU2N.js} +14 -4
- package/dist/{config-4JOXBFYX.js → config-E2XQNLSX.js} +1 -1
- package/dist/{connect-HLDHFBGX.js → connect-LRYVZCN6.js} +22 -6
- package/dist/{inbox-JBLYJMV2.js → inbox-O4ZETUIU.js} +2 -2
- package/dist/{login-VWJEBBFU.js → login-PUTCMS5B.js} +38 -12
- package/dist/{message-IK7VGB63.js → message-A3XMZCQA.js} +21 -3
- package/dist/{post-EAAGVR5D.js → post-HOXZPFVI.js} +2 -2
- package/dist/{profile-WXA3NC7D.js → profile-RU472SNL.js} +53 -11
- package/dist/{recruiter-TGCV36EH.js → recruiter-7SE3YCVZ.js} +94 -11
- package/dist/{sales-nav-XGFO5I6F.js → sales-nav-E3TH7CL7.js} +48 -9
- package/dist/{search-LHPTHPWH.js → search-ZPGKDJIT.js} +124 -17
- package/dist/{webhook-QM5LGAUF.js → webhook-VSM72KL5.js} +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,40 @@ a new command or flag is a minor; a breaking command/flag/exit-code change is a
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [0.3.0] - 2026-06-28
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `profile me` and `profile get` now return a slim 9-field projection by default (`id`, `first_name`, `last_name`, `headline`, `location`, `industry`, `profile_url`, `picture_url`, `current_position`); pass `--verbose` to get the full response.
|
|
16
|
+
- `profile get` synthesizes `current_position` from `work_experience[0]` when present.
|
|
17
|
+
- `profile get` and `profile me` accept `--sections` to request specific LinkedIn profile sections from the API.
|
|
18
|
+
- `profile get --posts --is-company` resolves a company slug to an account ID automatically (non-numeric IDs call `getCompany` first).
|
|
19
|
+
- `company get` now returns a slim 12-field projection by default (including `headquarters` and `messaging`); pass `--verbose` to get the full response.
|
|
20
|
+
- `login` persists `--base-url` to the named profile; re-login without `--base-url` preserves the existing base URL.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- `company` command now exits 2 with an error when `--sections` is passed (unsupported flag for that surface).
|
|
25
|
+
- `slimProfile` work_experience field mapping corrected (`position`→`title`, `company`→`company_name`); `is_current` now derived from `end == null`; `company_id` is always `null` (the experience-entry ID is not a company ID).
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Updated `@curviate/sdk` dependency to `^0.2.0` (adds `getMe` `linkedin_sections`, normalized `OwnProfile`, `Chat.subject`).
|
|
30
|
+
|
|
31
|
+
## [0.2.0] - 2026-06-24
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
|
|
35
|
+
- `message inmail` now requires and forwards the `--surface` flag (was silently dropped).
|
|
36
|
+
- `connect respond` now requires and forwards `--shared-secret` (was silently dropped).
|
|
37
|
+
- `recruiter message new` uses the correct field name `attendee_ids` (was `attendees`).
|
|
38
|
+
- `recruiter job create` now forwards the full job body via JSON and scalar flags (was a no-op).
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- `search` and `recruiter search` / `sales-navigator search` accept `--filters` for raw JSON filter objects and named filter flags (`--title`, `--company`, `--location`, `--school`, `--industry`) for common parameters.
|
|
43
|
+
- `search` and `recruiter search` / `sales-navigator search` accept `--url` (profile URL filter) and `--keywords`.
|
|
44
|
+
|
|
11
45
|
## [0.1.0] - 2026-06-22
|
|
12
46
|
|
|
13
47
|
### Added
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
renderSuccess,
|
|
12
12
|
renderUnexpectedError,
|
|
13
13
|
resolveEffectiveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UPNQPAJG.js";
|
|
15
15
|
import {
|
|
16
16
|
GLOBAL_FLAGS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QQRTODHN.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/account.ts
|
|
20
20
|
import { defineCommand } from "citty";
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/search-filters.ts
|
|
4
|
+
import { readFile } from "fs/promises";
|
|
5
|
+
async function readStdin() {
|
|
6
|
+
const chunks = [];
|
|
7
|
+
for await (const chunk of process.stdin) {
|
|
8
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
9
|
+
}
|
|
10
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
11
|
+
}
|
|
12
|
+
var DEFAULT_FILTER_READERS = {
|
|
13
|
+
readFile: (path) => readFile(path, "utf8"),
|
|
14
|
+
readStdin
|
|
15
|
+
};
|
|
16
|
+
async function assembleFilters(flags, readers = DEFAULT_FILTER_READERS) {
|
|
17
|
+
let raw;
|
|
18
|
+
let source;
|
|
19
|
+
if (flags["filters-file"] !== void 0) {
|
|
20
|
+
source = `--filters-file ${flags["filters-file"]}`;
|
|
21
|
+
try {
|
|
22
|
+
raw = await readers.readFile(flags["filters-file"]);
|
|
23
|
+
} catch {
|
|
24
|
+
return { error: `cannot read ${source}` };
|
|
25
|
+
}
|
|
26
|
+
} else if (flags.filters === "-") {
|
|
27
|
+
source = "--filters - (stdin)";
|
|
28
|
+
raw = await readers.readStdin();
|
|
29
|
+
} else if (flags.filters !== void 0) {
|
|
30
|
+
source = "--filters";
|
|
31
|
+
raw = flags.filters;
|
|
32
|
+
}
|
|
33
|
+
if (raw === void 0) return { body: {} };
|
|
34
|
+
let parsed;
|
|
35
|
+
try {
|
|
36
|
+
parsed = JSON.parse(raw);
|
|
37
|
+
} catch {
|
|
38
|
+
return { error: `${source} is not valid JSON` };
|
|
39
|
+
}
|
|
40
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
41
|
+
return { error: `${source} must be a JSON object` };
|
|
42
|
+
}
|
|
43
|
+
return { body: parsed };
|
|
44
|
+
}
|
|
45
|
+
function splitCsv(value) {
|
|
46
|
+
return value.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
47
|
+
}
|
|
48
|
+
function splitCsvNumbers(value) {
|
|
49
|
+
return splitCsv(value).map((s) => Number(s)).filter((n) => Number.isFinite(n));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export {
|
|
53
|
+
DEFAULT_FILTER_READERS,
|
|
54
|
+
assembleFilters,
|
|
55
|
+
splitCsv,
|
|
56
|
+
splitCsvNumbers
|
|
57
|
+
};
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/lib/slim.ts
|
|
4
|
+
function synthesizeCurrentPosition(workExperience) {
|
|
5
|
+
if (!Array.isArray(workExperience) || workExperience.length === 0) {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
const entry = workExperience[0];
|
|
9
|
+
return {
|
|
10
|
+
title: entry["position"] ?? null,
|
|
11
|
+
company_name: entry["company"] ?? null,
|
|
12
|
+
company_id: null,
|
|
13
|
+
is_current: entry["end"] == null
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function synthesizeHeadquarters(locations) {
|
|
17
|
+
if (!Array.isArray(locations)) return null;
|
|
18
|
+
const hq = locations.find(
|
|
19
|
+
(l) => l["is_headquarter"] === true
|
|
20
|
+
);
|
|
21
|
+
if (!hq) return null;
|
|
22
|
+
return {
|
|
23
|
+
city: hq["city"] ?? null,
|
|
24
|
+
country: hq["country"] ?? null,
|
|
25
|
+
area: hq["area"] ?? null
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function slimProfileMe(data) {
|
|
29
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
30
|
+
const rawOrgs = Array.isArray(d["organizations"]) ? d["organizations"] : [];
|
|
31
|
+
const organizations = rawOrgs.map((org) => ({
|
|
32
|
+
id: org["id"] ?? null,
|
|
33
|
+
mailbox_id: org["mailbox_id"] ?? null,
|
|
34
|
+
name: org["name"] ?? null
|
|
35
|
+
}));
|
|
36
|
+
return {
|
|
37
|
+
provider_id: d["provider_id"] ?? null,
|
|
38
|
+
first_name: d["first_name"] ?? null,
|
|
39
|
+
last_name: d["last_name"] ?? null,
|
|
40
|
+
public_identifier: d["public_identifier"] ?? null,
|
|
41
|
+
location: d["location"] ?? null,
|
|
42
|
+
email: d["email"] ?? null,
|
|
43
|
+
occupation: d["occupation"] ?? null,
|
|
44
|
+
is_premium: d["is_premium"] ?? null,
|
|
45
|
+
organizations
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function slimProfile(data) {
|
|
49
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
50
|
+
const rawWE = Array.isArray(d["work_experience"]) ? d["work_experience"] : [];
|
|
51
|
+
const currentPosition = synthesizeCurrentPosition(rawWE);
|
|
52
|
+
return {
|
|
53
|
+
provider_id: d["provider_id"] ?? null,
|
|
54
|
+
first_name: d["first_name"] ?? null,
|
|
55
|
+
last_name: d["last_name"] ?? null,
|
|
56
|
+
headline: d["headline"] ?? null,
|
|
57
|
+
location: d["location"] ?? null,
|
|
58
|
+
occupation: d["occupation"] ?? null,
|
|
59
|
+
network_distance: d["network_distance"] ?? null,
|
|
60
|
+
public_identifier: d["public_identifier"] ?? null,
|
|
61
|
+
current_position: currentPosition
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function slimCompany(data) {
|
|
65
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
66
|
+
const rawMessaging = d["messaging"] !== null && d["messaging"] !== void 0 && typeof d["messaging"] === "object" ? d["messaging"] : null;
|
|
67
|
+
const messaging = {
|
|
68
|
+
is_enabled: rawMessaging?.["is_enabled"] ?? false
|
|
69
|
+
};
|
|
70
|
+
const rawLocations = Array.isArray(d["locations"]) ? d["locations"] : [];
|
|
71
|
+
const headquarters = synthesizeHeadquarters(rawLocations);
|
|
72
|
+
return {
|
|
73
|
+
id: d["id"] ?? null,
|
|
74
|
+
name: d["name"] ?? null,
|
|
75
|
+
public_identifier: d["public_identifier"] ?? null,
|
|
76
|
+
profile_url: d["profile_url"] ?? null,
|
|
77
|
+
industry: d["industry"] ?? null,
|
|
78
|
+
employee_count: d["employee_count"] ?? null,
|
|
79
|
+
employee_count_range: d["employee_count_range"] ?? null,
|
|
80
|
+
website: d["website"] ?? null,
|
|
81
|
+
foundation_date: d["foundation_date"] ?? null,
|
|
82
|
+
messaging,
|
|
83
|
+
headquarters,
|
|
84
|
+
followers_count: d["followers_count"] ?? null
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export {
|
|
89
|
+
slimProfileMe,
|
|
90
|
+
slimProfile,
|
|
91
|
+
slimCompany
|
|
92
|
+
};
|
|
@@ -180,6 +180,11 @@ var GLOBAL_FLAGS = {
|
|
|
180
180
|
type: "boolean",
|
|
181
181
|
description: "Render the request that would be sent without calling the API.",
|
|
182
182
|
default: false
|
|
183
|
+
},
|
|
184
|
+
verbose: {
|
|
185
|
+
type: "boolean",
|
|
186
|
+
description: "Output the full SDK response instead of the slim default.",
|
|
187
|
+
default: false
|
|
183
188
|
}
|
|
184
189
|
};
|
|
185
190
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
readConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-QQRTODHN.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/resolve.ts
|
|
7
7
|
var DEFAULT_BASE_URL = "https://api.curviate.com";
|
|
@@ -76,7 +76,8 @@ function applyProjection(data, fields) {
|
|
|
76
76
|
function renderSuccess(data, opts, out) {
|
|
77
77
|
const json = isJsonMode(opts);
|
|
78
78
|
const fields = opts.fields ? opts.fields.split(",").map((f) => f.trim()).filter(Boolean) : [];
|
|
79
|
-
const
|
|
79
|
+
const slimmed = !opts.verbose && opts.slim ? opts.slim(data) : data;
|
|
80
|
+
const projected = applyProjection(slimmed, fields);
|
|
80
81
|
if (json) {
|
|
81
82
|
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
82
83
|
} else {
|
package/dist/cli.js
CHANGED
|
@@ -134,22 +134,22 @@ var main = defineCommand({
|
|
|
134
134
|
// Subcommand registry — names and descriptions are static for help rendering;
|
|
135
135
|
// the handler implementation is loaded lazily on first invocation.
|
|
136
136
|
subCommands: {
|
|
137
|
-
login: () => import("./login-
|
|
138
|
-
config: () => import("./config-
|
|
137
|
+
login: () => import("./login-PUTCMS5B.js").then((m) => m.loginCommand),
|
|
138
|
+
config: () => import("./config-E2XQNLSX.js").then((m) => m.configCommand),
|
|
139
139
|
// ---------------------------------------------------------------------------
|
|
140
140
|
// Noun groups — lazy-loaded on first invocation.
|
|
141
141
|
// ---------------------------------------------------------------------------
|
|
142
|
-
profile: () => import("./profile-
|
|
143
|
-
company: () => import("./company-
|
|
144
|
-
connect: () => import("./connect-
|
|
145
|
-
search: () => import("./search-
|
|
146
|
-
inbox: () => import("./inbox-
|
|
147
|
-
message: () => import("./message-
|
|
148
|
-
post: () => import("./post-
|
|
149
|
-
account: () => import("./account-
|
|
150
|
-
webhook: () => import("./webhook-
|
|
151
|
-
"sales-nav": () => import("./sales-nav-
|
|
152
|
-
recruiter: () => import("./recruiter-
|
|
142
|
+
profile: () => import("./profile-RU472SNL.js").then((m) => m.profileCommand),
|
|
143
|
+
company: () => import("./company-EARWRU2N.js").then((m) => m.companyCommand),
|
|
144
|
+
connect: () => import("./connect-LRYVZCN6.js").then((m) => m.connectCommand),
|
|
145
|
+
search: () => import("./search-ZPGKDJIT.js").then((m) => m.searchCommand),
|
|
146
|
+
inbox: () => import("./inbox-O4ZETUIU.js").then((m) => m.inboxCommand),
|
|
147
|
+
message: () => import("./message-A3XMZCQA.js").then((m) => m.messageCommand),
|
|
148
|
+
post: () => import("./post-HOXZPFVI.js").then((m) => m.postCommand),
|
|
149
|
+
account: () => import("./account-3I63RFVN.js").then((m) => m.accountCommand),
|
|
150
|
+
webhook: () => import("./webhook-VSM72KL5.js").then((m) => m.webhookCommand),
|
|
151
|
+
"sales-nav": () => import("./sales-nav-E3TH7CL7.js").then((m) => m.salesNavCommand),
|
|
152
|
+
recruiter: () => import("./recruiter-7SE3YCVZ.js").then((m) => m.recruiterCommand)
|
|
153
153
|
},
|
|
154
154
|
async run() {
|
|
155
155
|
const { runMain } = await import("citty");
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
slimCompany
|
|
4
|
+
} from "./chunk-7TWHAKKA.js";
|
|
2
5
|
import {
|
|
3
6
|
resolveIdentifier
|
|
4
7
|
} from "./chunk-BNUTM6KD.js";
|
|
@@ -8,10 +11,10 @@ import {
|
|
|
8
11
|
renderSuccess,
|
|
9
12
|
renderUnexpectedError,
|
|
10
13
|
resolveEffectiveConfig
|
|
11
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UPNQPAJG.js";
|
|
12
15
|
import {
|
|
13
16
|
GLOBAL_FLAGS
|
|
14
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QQRTODHN.js";
|
|
15
18
|
|
|
16
19
|
// src/commands/company.ts
|
|
17
20
|
import { defineCommand } from "citty";
|
|
@@ -30,12 +33,18 @@ async function runCompanyGet(client, flags, out) {
|
|
|
30
33
|
out.stderr.write("error: --all is not supported on non-paginated commands.\n");
|
|
31
34
|
process.exit(2);
|
|
32
35
|
}
|
|
36
|
+
if (flags.sections !== void 0) {
|
|
37
|
+
out.stderr.write("error: --sections is not supported on company commands.\n");
|
|
38
|
+
process.exit(2);
|
|
39
|
+
}
|
|
33
40
|
const rawId = flags.id ?? "";
|
|
34
41
|
const resolvedId = resolveIdentifier(rawId);
|
|
35
42
|
const outOpts = {
|
|
36
43
|
json: (flags.json ?? false) || !process.stdout.isTTY,
|
|
37
44
|
isTTY: process.stdout.isTTY ?? false,
|
|
38
|
-
fields: flags.fields
|
|
45
|
+
fields: flags.fields,
|
|
46
|
+
verbose: flags.verbose ?? false,
|
|
47
|
+
slim: slimCompany
|
|
39
48
|
};
|
|
40
49
|
try {
|
|
41
50
|
const getCompany = flags.account ? client.account(flags.account).profiles.getCompany.bind(client.account(flags.account).profiles) : client.profiles.getCompany.bind(client.profiles);
|
|
@@ -56,7 +65,8 @@ var companyCommand = defineCommand({
|
|
|
56
65
|
meta: { name: "company", description: "Fetch a company profile by URL or slug." },
|
|
57
66
|
args: {
|
|
58
67
|
...GLOBAL_FLAGS,
|
|
59
|
-
id: { type: "positional", description: "Company identifier (URL, slug, or native id)." }
|
|
68
|
+
id: { type: "positional", description: "Company identifier (URL, slug, or native id)." },
|
|
69
|
+
sections: { type: "string", description: "Not supported on company commands \u2014 usage error (exit 2) if supplied." }
|
|
60
70
|
},
|
|
61
71
|
async run({ args }) {
|
|
62
72
|
const flags = args;
|
|
@@ -14,10 +14,10 @@ import {
|
|
|
14
14
|
renderSuccess,
|
|
15
15
|
renderUnexpectedError,
|
|
16
16
|
resolveEffectiveConfig
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UPNQPAJG.js";
|
|
18
18
|
import {
|
|
19
19
|
GLOBAL_FLAGS
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-QQRTODHN.js";
|
|
21
21
|
|
|
22
22
|
// src/commands/connect.ts
|
|
23
23
|
import { defineCommand } from "citty";
|
|
@@ -155,11 +155,19 @@ async function runConnectRespond(client, flags, out) {
|
|
|
155
155
|
const accountId = requireAccount(flags.account, out);
|
|
156
156
|
const invitationId = flags.id ?? "";
|
|
157
157
|
const action = flags.action ?? "";
|
|
158
|
+
const sharedSecret = flags["shared-secret"] ?? "";
|
|
159
|
+
if (!sharedSecret) {
|
|
160
|
+
out.stderr.write(
|
|
161
|
+
"error: --shared-secret is required. Read it from `connect received` (each item carries its per-invitation shared_secret).\n"
|
|
162
|
+
);
|
|
163
|
+
process.exit(2);
|
|
164
|
+
}
|
|
165
|
+
const body = { action, shared_secret: sharedSecret };
|
|
158
166
|
if (flags.preview) {
|
|
159
167
|
const preview = buildPreviewOutput({
|
|
160
168
|
method: "invites.respond",
|
|
161
169
|
args: { invitation_id: invitationId },
|
|
162
|
-
body
|
|
170
|
+
body,
|
|
163
171
|
account: accountId
|
|
164
172
|
});
|
|
165
173
|
out.stdout.write(JSON.stringify(preview) + "\n");
|
|
@@ -168,7 +176,7 @@ async function runConnectRespond(client, flags, out) {
|
|
|
168
176
|
const ns = client.account(accountId);
|
|
169
177
|
const outOpts = resolveOutputOpts(flags);
|
|
170
178
|
try {
|
|
171
|
-
const result = await ns.invites.respond(invitationId,
|
|
179
|
+
const result = await ns.invites.respond(invitationId, body);
|
|
172
180
|
renderSuccess(result, outOpts, out);
|
|
173
181
|
} catch (err) {
|
|
174
182
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -232,7 +240,10 @@ var connectSentCommand = defineCommand({
|
|
|
232
240
|
}
|
|
233
241
|
});
|
|
234
242
|
var connectReceivedCommand = defineCommand({
|
|
235
|
-
meta: {
|
|
243
|
+
meta: {
|
|
244
|
+
name: "received",
|
|
245
|
+
description: "List received connection invitations. Each item carries a shared_secret \u2014 pass it to `connect respond --shared-secret`."
|
|
246
|
+
},
|
|
236
247
|
args: { ...GLOBAL_FLAGS },
|
|
237
248
|
async run({ args }) {
|
|
238
249
|
const flags = args;
|
|
@@ -257,7 +268,12 @@ var connectRespondCommand = defineCommand({
|
|
|
257
268
|
args: {
|
|
258
269
|
...GLOBAL_FLAGS,
|
|
259
270
|
id: { type: "positional", description: "Invitation id to respond to." },
|
|
260
|
-
action: { type: "string", description: "Response action: accept or decline.", required: true }
|
|
271
|
+
action: { type: "string", description: "Response action: accept or decline.", required: true },
|
|
272
|
+
"shared-secret": {
|
|
273
|
+
type: "string",
|
|
274
|
+
description: "Per-invitation shared secret \u2014 read it from `connect received`.",
|
|
275
|
+
required: true
|
|
276
|
+
}
|
|
261
277
|
},
|
|
262
278
|
async run({ args }) {
|
|
263
279
|
const flags = args;
|
|
@@ -8,10 +8,10 @@ import {
|
|
|
8
8
|
renderSuccess,
|
|
9
9
|
renderUnexpectedError,
|
|
10
10
|
resolveEffectiveConfig
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-UPNQPAJG.js";
|
|
12
12
|
import {
|
|
13
13
|
GLOBAL_FLAGS
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QQRTODHN.js";
|
|
15
15
|
|
|
16
16
|
// src/commands/inbox.ts
|
|
17
17
|
import { defineCommand } from "citty";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
GLOBAL_FLAGS,
|
|
4
4
|
writeProfile
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QQRTODHN.js";
|
|
6
6
|
|
|
7
7
|
// src/commands/login.ts
|
|
8
8
|
import { defineCommand } from "citty";
|
|
@@ -54,6 +54,31 @@ async function readlineSync(prompt, opts = {}) {
|
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
// src/commands/login.ts
|
|
57
|
+
async function runLogin(args, out) {
|
|
58
|
+
const profileName = args.profile ?? "default";
|
|
59
|
+
const apiKey = (args["api-key"] ?? "").trim();
|
|
60
|
+
if (!apiKey) {
|
|
61
|
+
out.stderr.write("error: API key must not be empty.\n");
|
|
62
|
+
process.exit(2);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const baseUrl = args["base-url"];
|
|
66
|
+
if (baseUrl === "") {
|
|
67
|
+
out.stderr.write("error: --base-url must not be empty.\n");
|
|
68
|
+
process.exit(2);
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const account = args.account;
|
|
72
|
+
const entry = { apiKey, account };
|
|
73
|
+
if (baseUrl !== void 0 && baseUrl !== "") {
|
|
74
|
+
entry.baseUrl = baseUrl;
|
|
75
|
+
}
|
|
76
|
+
await writeProfile(profileName, entry);
|
|
77
|
+
out.stderr.write(
|
|
78
|
+
`Saved to profile "${profileName}". Run \`curviate profile me\` to verify.
|
|
79
|
+
`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
57
82
|
var loginCommand = defineCommand({
|
|
58
83
|
meta: {
|
|
59
84
|
name: "login",
|
|
@@ -89,18 +114,18 @@ var loginCommand = defineCommand({
|
|
|
89
114
|
"error: no API key \u2014 pass --api-key or run interactively on a TTY.\n"
|
|
90
115
|
);
|
|
91
116
|
process.exit(2);
|
|
117
|
+
return;
|
|
92
118
|
}
|
|
93
119
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
`
|
|
120
|
+
const out = { stderr: { write: (s) => process.stderr.write(s) } };
|
|
121
|
+
await runLogin(
|
|
122
|
+
{
|
|
123
|
+
"api-key": apiKey,
|
|
124
|
+
account: args.account,
|
|
125
|
+
"base-url": args["base-url"],
|
|
126
|
+
profile: profileName
|
|
127
|
+
},
|
|
128
|
+
out
|
|
104
129
|
);
|
|
105
130
|
}
|
|
106
131
|
});
|
|
@@ -118,5 +143,6 @@ async function promptMasked(prompt) {
|
|
|
118
143
|
return readlineSync(prompt, { mask: true });
|
|
119
144
|
}
|
|
120
145
|
export {
|
|
121
|
-
loginCommand
|
|
146
|
+
loginCommand,
|
|
147
|
+
runLogin
|
|
122
148
|
};
|
|
@@ -19,10 +19,10 @@ import {
|
|
|
19
19
|
renderSuccess,
|
|
20
20
|
renderUnexpectedError,
|
|
21
21
|
resolveEffectiveConfig
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-UPNQPAJG.js";
|
|
23
23
|
import {
|
|
24
24
|
GLOBAL_FLAGS
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-QQRTODHN.js";
|
|
26
26
|
|
|
27
27
|
// src/commands/message.ts
|
|
28
28
|
import { defineCommand } from "citty";
|
|
@@ -62,6 +62,8 @@ function normalizeAttachPaths(attach) {
|
|
|
62
62
|
if (!attach) return [];
|
|
63
63
|
return Array.isArray(attach) ? attach : [attach];
|
|
64
64
|
}
|
|
65
|
+
var INMAIL_SURFACES = ["sales_nav", "recruiter"];
|
|
66
|
+
var MEMBER_URN_RE = /^urn:li:member:\d+$/;
|
|
65
67
|
async function handleSdkError(err, outOpts, out) {
|
|
66
68
|
const { CurviateError } = await import("@curviate/sdk");
|
|
67
69
|
if (err instanceof CurviateError) {
|
|
@@ -268,11 +270,26 @@ async function runMessageAttachment(client, flags, out, isTTY) {
|
|
|
268
270
|
}
|
|
269
271
|
async function runMessageInMail(client, flags, out) {
|
|
270
272
|
const accountId = requireAccount(flags.account, out);
|
|
273
|
+
const surface = flags.surface ?? "";
|
|
274
|
+
if (!INMAIL_SURFACES.includes(surface)) {
|
|
275
|
+
out.stderr.write(
|
|
276
|
+
`error: --surface is required and must be one of ${INMAIL_SURFACES.join(", ")}.
|
|
277
|
+
`
|
|
278
|
+
);
|
|
279
|
+
process.exit(2);
|
|
280
|
+
}
|
|
271
281
|
const recipientUrn = resolveIdentifier(flags.to ?? "");
|
|
282
|
+
if (!MEMBER_URN_RE.test(recipientUrn)) {
|
|
283
|
+
out.stderr.write(
|
|
284
|
+
"error: --to must be a LinkedIn member URN (e.g. urn:li:member:99999), not a URL or slug.\n"
|
|
285
|
+
);
|
|
286
|
+
process.exit(2);
|
|
287
|
+
}
|
|
272
288
|
const subject = flags.subject ?? "";
|
|
273
289
|
const text = flags.text ?? "";
|
|
274
290
|
const body = {
|
|
275
291
|
recipient_urn: recipientUrn,
|
|
292
|
+
surface,
|
|
276
293
|
subject,
|
|
277
294
|
text
|
|
278
295
|
};
|
|
@@ -467,7 +484,8 @@ var messageInMailCommand = defineCommand({
|
|
|
467
484
|
meta: { name: "inmail", description: "Send an InMail to a member." },
|
|
468
485
|
args: {
|
|
469
486
|
...GLOBAL_FLAGS,
|
|
470
|
-
to: { type: "string", description: "Recipient
|
|
487
|
+
to: { type: "string", description: "Recipient member URN (urn:li:member:<id>). Must be a URN, not a URL or slug.", required: true },
|
|
488
|
+
surface: { type: "string", description: "InMail surface: sales_nav or recruiter.", required: true },
|
|
471
489
|
subject: { type: "string", description: "InMail subject line.", required: true },
|
|
472
490
|
text: { type: "positional", description: "InMail body text." }
|
|
473
491
|
},
|
|
@@ -15,10 +15,10 @@ import {
|
|
|
15
15
|
renderSuccess,
|
|
16
16
|
renderUnexpectedError,
|
|
17
17
|
resolveEffectiveConfig
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-UPNQPAJG.js";
|
|
19
19
|
import {
|
|
20
20
|
GLOBAL_FLAGS
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-QQRTODHN.js";
|
|
22
22
|
|
|
23
23
|
// src/commands/post.ts
|
|
24
24
|
import { defineCommand } from "citty";
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
slimProfile,
|
|
4
|
+
slimProfileMe
|
|
5
|
+
} from "./chunk-7TWHAKKA.js";
|
|
2
6
|
import {
|
|
3
7
|
buildPreviewOutput
|
|
4
8
|
} from "./chunk-R3VLWLVV.js";
|
|
@@ -14,10 +18,10 @@ import {
|
|
|
14
18
|
renderSuccess,
|
|
15
19
|
renderUnexpectedError,
|
|
16
20
|
resolveEffectiveConfig
|
|
17
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-UPNQPAJG.js";
|
|
18
22
|
import {
|
|
19
23
|
GLOBAL_FLAGS
|
|
20
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-QQRTODHN.js";
|
|
21
25
|
|
|
22
26
|
// src/commands/profile.ts
|
|
23
27
|
import { defineCommand } from "citty";
|
|
@@ -50,18 +54,28 @@ function resolveOutputOpts(flags) {
|
|
|
50
54
|
return {
|
|
51
55
|
json: (flags.json ?? false) || !process.stdout.isTTY,
|
|
52
56
|
isTTY: process.stdout.isTTY ?? false,
|
|
53
|
-
fields: flags.fields
|
|
57
|
+
fields: flags.fields,
|
|
58
|
+
verbose: flags.verbose ?? false
|
|
54
59
|
};
|
|
55
60
|
}
|
|
56
61
|
async function runProfileMe(client, flags, out) {
|
|
57
62
|
rejectPreviewOnRead(flags.preview, out);
|
|
58
63
|
rejectAllOnNonPaginated(flags.all, out);
|
|
64
|
+
if (flags.sections === "") {
|
|
65
|
+
out.stderr.write("error: --sections must not be empty. Omit the flag or provide section names.\n");
|
|
66
|
+
process.exit(2);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
59
69
|
const accountId = requireAccount(flags.account, out);
|
|
60
70
|
const ns = client.account(accountId);
|
|
71
|
+
const params = {};
|
|
72
|
+
if (flags.sections) {
|
|
73
|
+
params["linkedin_sections"] = flags.sections.split(",").map((s) => s.trim()).filter(Boolean);
|
|
74
|
+
}
|
|
61
75
|
try {
|
|
62
|
-
const result = await ns.profiles.getMe();
|
|
63
|
-
const
|
|
64
|
-
renderSuccess(result,
|
|
76
|
+
const result = await ns.profiles.getMe(params);
|
|
77
|
+
const outOpts = { ...resolveOutputOpts(flags), slim: slimProfileMe };
|
|
78
|
+
renderSuccess(result, outOpts, out);
|
|
65
79
|
} catch (err) {
|
|
66
80
|
const { CurviateError } = await import("@curviate/sdk");
|
|
67
81
|
if (err instanceof CurviateError) {
|
|
@@ -75,6 +89,12 @@ async function runProfileMe(client, flags, out) {
|
|
|
75
89
|
}
|
|
76
90
|
async function runProfileGet(client, flags, out) {
|
|
77
91
|
rejectPreviewOnRead(flags.preview, out);
|
|
92
|
+
const isListCommand = flags.posts || flags.comments || flags.reactions || flags.followers;
|
|
93
|
+
if (!isListCommand && flags.sections === "") {
|
|
94
|
+
out.stderr.write("error: --sections must not be empty. Omit the flag or provide section names.\n");
|
|
95
|
+
process.exit(2);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
78
98
|
const accountId = requireAccount(flags.account, out);
|
|
79
99
|
const rawId = flags.id ?? "";
|
|
80
100
|
const resolvedId = resolveIdentifier(rawId);
|
|
@@ -90,8 +110,16 @@ async function runProfileGet(client, flags, out) {
|
|
|
90
110
|
if (flags["is-company"]) params["is_company"] = true;
|
|
91
111
|
if (limit !== void 0) params["limit"] = limit;
|
|
92
112
|
if (cursor) params["cursor"] = cursor;
|
|
113
|
+
let postId = resolvedId;
|
|
114
|
+
if (flags["is-company"]) {
|
|
115
|
+
const isNumericId = /^\d+$/.test(resolvedId);
|
|
116
|
+
if (!isNumericId) {
|
|
117
|
+
const companyData = await ns.profiles.getCompany(resolvedId);
|
|
118
|
+
postId = companyData["id"];
|
|
119
|
+
}
|
|
120
|
+
}
|
|
93
121
|
if (all) {
|
|
94
|
-
const fn = (p) => ns.profiles.listPosts(
|
|
122
|
+
const fn = (p) => ns.profiles.listPosts(postId, p);
|
|
95
123
|
for await (const item of streamAll(fn, params, {
|
|
96
124
|
maxPages,
|
|
97
125
|
onTruncated: (msg) => out.stderr.write(msg + "\n")
|
|
@@ -99,7 +127,7 @@ async function runProfileGet(client, flags, out) {
|
|
|
99
127
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
100
128
|
}
|
|
101
129
|
} else {
|
|
102
|
-
const result = await ns.profiles.listPosts(
|
|
130
|
+
const result = await ns.profiles.listPosts(postId, params);
|
|
103
131
|
renderSuccess(result, outOpts, out);
|
|
104
132
|
}
|
|
105
133
|
} else if (flags.comments) {
|
|
@@ -154,8 +182,12 @@ async function runProfileGet(client, flags, out) {
|
|
|
154
182
|
rejectAllOnNonPaginated(flags.all, out);
|
|
155
183
|
const params = {};
|
|
156
184
|
if (flags.notify) params["notify"] = true;
|
|
185
|
+
if (flags.sections) {
|
|
186
|
+
params["linkedin_sections"] = flags.sections.split(",").map((s) => s.trim()).filter(Boolean);
|
|
187
|
+
}
|
|
157
188
|
const result = await ns.profiles.get(resolvedId, params);
|
|
158
|
-
|
|
189
|
+
const getOutOpts = { ...outOpts, slim: slimProfile };
|
|
190
|
+
renderSuccess(result, getOutOpts, out);
|
|
159
191
|
}
|
|
160
192
|
} catch (err) {
|
|
161
193
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -237,7 +269,13 @@ async function runProfileEndorse(client, flags, out) {
|
|
|
237
269
|
}
|
|
238
270
|
var profileMeCommand = defineCommand({
|
|
239
271
|
meta: { name: "me", description: "Get your own LinkedIn profile." },
|
|
240
|
-
args: {
|
|
272
|
+
args: {
|
|
273
|
+
...GLOBAL_FLAGS,
|
|
274
|
+
sections: {
|
|
275
|
+
type: "string",
|
|
276
|
+
description: "Comma-separated LinkedIn sections to fetch (e.g. experience,education)."
|
|
277
|
+
}
|
|
278
|
+
},
|
|
241
279
|
async run({ args }) {
|
|
242
280
|
const flags = args;
|
|
243
281
|
const cfg = await resolveEffectiveConfig({
|
|
@@ -312,7 +350,11 @@ var profileCommand = defineCommand({
|
|
|
312
350
|
reactions: { type: "boolean", description: "List the profile's reactions.", default: false },
|
|
313
351
|
followers: { type: "boolean", description: "List the profile's followers.", default: false },
|
|
314
352
|
"is-company": { type: "boolean", description: "When listing posts, treat the profile as a company page.", default: false },
|
|
315
|
-
notify: { type: "boolean", description: "Signal a profile view when fetching.", default: false }
|
|
353
|
+
notify: { type: "boolean", description: "Signal a profile view when fetching.", default: false },
|
|
354
|
+
sections: {
|
|
355
|
+
type: "string",
|
|
356
|
+
description: "Comma-separated LinkedIn sections to fetch (e.g. experience,education)."
|
|
357
|
+
}
|
|
316
358
|
},
|
|
317
359
|
subCommands: {
|
|
318
360
|
me: profileMeCommand,
|
|
@@ -13,6 +13,11 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
resolveIdentifier
|
|
15
15
|
} from "./chunk-BNUTM6KD.js";
|
|
16
|
+
import {
|
|
17
|
+
DEFAULT_FILTER_READERS,
|
|
18
|
+
assembleFilters,
|
|
19
|
+
splitCsv
|
|
20
|
+
} from "./chunk-42VUUKQ3.js";
|
|
16
21
|
import {
|
|
17
22
|
streamAll
|
|
18
23
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -22,13 +27,14 @@ import {
|
|
|
22
27
|
renderSuccess,
|
|
23
28
|
renderUnexpectedError,
|
|
24
29
|
resolveEffectiveConfig
|
|
25
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-UPNQPAJG.js";
|
|
26
31
|
import {
|
|
27
32
|
GLOBAL_FLAGS
|
|
28
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-QQRTODHN.js";
|
|
29
34
|
|
|
30
35
|
// src/commands/recruiter.ts
|
|
31
36
|
import { defineCommand } from "citty";
|
|
37
|
+
import { readFile } from "fs/promises";
|
|
32
38
|
function buildOutputStreams() {
|
|
33
39
|
return {
|
|
34
40
|
stdout: { write: (s) => process.stdout.write(s) },
|
|
@@ -69,6 +75,51 @@ async function handleSdkError(err, outOpts, out) {
|
|
|
69
75
|
renderUnexpectedError(err, out);
|
|
70
76
|
process.exit(1);
|
|
71
77
|
}
|
|
78
|
+
async function readStdin() {
|
|
79
|
+
const chunks = [];
|
|
80
|
+
for await (const chunk of process.stdin) {
|
|
81
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
82
|
+
}
|
|
83
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
84
|
+
}
|
|
85
|
+
var DEFAULT_JOB_CREATE_READERS = {
|
|
86
|
+
readFile: (path) => readFile(path, "utf8"),
|
|
87
|
+
readStdin
|
|
88
|
+
};
|
|
89
|
+
async function assembleJobCreateBody(flags, readers) {
|
|
90
|
+
let base = {};
|
|
91
|
+
let raw;
|
|
92
|
+
let source;
|
|
93
|
+
if (flags["body-file"] !== void 0) {
|
|
94
|
+
source = `--body-file ${flags["body-file"]}`;
|
|
95
|
+
try {
|
|
96
|
+
raw = await readers.readFile(flags["body-file"]);
|
|
97
|
+
} catch {
|
|
98
|
+
return { error: `cannot read ${source}` };
|
|
99
|
+
}
|
|
100
|
+
} else if (flags.body === "-") {
|
|
101
|
+
source = "--body - (stdin)";
|
|
102
|
+
raw = await readers.readStdin();
|
|
103
|
+
} else if (flags.body !== void 0) {
|
|
104
|
+
return { error: "--body only accepts '-' (read JSON from stdin); use --body-file <path> for a file." };
|
|
105
|
+
}
|
|
106
|
+
if (raw !== void 0) {
|
|
107
|
+
let parsed;
|
|
108
|
+
try {
|
|
109
|
+
parsed = JSON.parse(raw);
|
|
110
|
+
} catch {
|
|
111
|
+
return { error: `${source} is not valid JSON` };
|
|
112
|
+
}
|
|
113
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
114
|
+
return { error: `${source} must be a JSON object` };
|
|
115
|
+
}
|
|
116
|
+
base = parsed;
|
|
117
|
+
}
|
|
118
|
+
if (flags["job-title"] !== void 0) base["job_title"] = { text: flags["job-title"] };
|
|
119
|
+
if (flags.description !== void 0) base["description"] = flags.description;
|
|
120
|
+
if (flags["employment-type"] !== void 0) base["employment_type"] = flags["employment-type"];
|
|
121
|
+
return { body: base };
|
|
122
|
+
}
|
|
72
123
|
async function runRecruiterSync(client, flags, out) {
|
|
73
124
|
rejectPreviewOnRead(flags.preview, out);
|
|
74
125
|
const accountId = requireAccount(flags.account, out);
|
|
@@ -107,13 +158,13 @@ async function runRecruiterMessageNew(client, flags, out) {
|
|
|
107
158
|
throw err;
|
|
108
159
|
}
|
|
109
160
|
const body = {
|
|
110
|
-
|
|
161
|
+
attendee_ids: [to],
|
|
111
162
|
text
|
|
112
163
|
};
|
|
113
164
|
if (flags.preview) {
|
|
114
165
|
const preview = buildPreviewOutput({
|
|
115
166
|
method: "recruiter.startChat",
|
|
116
|
-
args: {
|
|
167
|
+
args: { attendee_ids: [to] },
|
|
117
168
|
body: { ...body },
|
|
118
169
|
account: accountId,
|
|
119
170
|
attachments: [
|
|
@@ -154,7 +205,7 @@ async function runRecruiterProfile(client, flags, out) {
|
|
|
154
205
|
await handleSdkError(err, outOpts, out);
|
|
155
206
|
}
|
|
156
207
|
}
|
|
157
|
-
async function runRecruiterSearchPeople(client, flags, out) {
|
|
208
|
+
async function runRecruiterSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
158
209
|
rejectPreviewOnRead(flags.preview, out);
|
|
159
210
|
const accountId = requireAccount(flags.account, out);
|
|
160
211
|
const ns = client.account(accountId);
|
|
@@ -163,8 +214,18 @@ async function runRecruiterSearchPeople(client, flags, out) {
|
|
|
163
214
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
164
215
|
const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
|
|
165
216
|
const cursor = flags.cursor;
|
|
166
|
-
const
|
|
217
|
+
const assembled = await assembleFilters(flags, readers);
|
|
218
|
+
if ("error" in assembled) {
|
|
219
|
+
out.stderr.write(`error: ${assembled.error}
|
|
220
|
+
`);
|
|
221
|
+
process.exit(2);
|
|
222
|
+
}
|
|
223
|
+
const body = assembled.body;
|
|
167
224
|
if (flags.keywords) body["keywords"] = flags.keywords;
|
|
225
|
+
if (flags.locale) body["locale"] = flags.locale;
|
|
226
|
+
if (flags["employment-type"]) body["employment_type"] = splitCsv(flags["employment-type"]);
|
|
227
|
+
if (flags.function) body["function"] = splitCsv(flags.function);
|
|
228
|
+
if (flags["profile-language"]) body["profile_language"] = splitCsv(flags["profile-language"]);
|
|
168
229
|
const params = {};
|
|
169
230
|
if (limit !== void 0) params["limit"] = limit;
|
|
170
231
|
if (cursor) params["cursor"] = cursor;
|
|
@@ -200,6 +261,8 @@ async function runRecruiterGetParameters(client, flags, out) {
|
|
|
200
261
|
const outOpts = resolveOutputOpts(flags);
|
|
201
262
|
const params = {};
|
|
202
263
|
if (flags.type) params["type"] = flags.type;
|
|
264
|
+
if (flags.keywords) params["keywords"] = flags.keywords;
|
|
265
|
+
if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
|
|
203
266
|
try {
|
|
204
267
|
const result = await ns.recruiter.getParameters(params);
|
|
205
268
|
renderSuccess(result, outOpts, out);
|
|
@@ -353,10 +416,16 @@ async function runRecruiterListJobs(client, flags, out) {
|
|
|
353
416
|
await handleSdkError(err, outOpts, out);
|
|
354
417
|
}
|
|
355
418
|
}
|
|
356
|
-
async function runRecruiterCreateJob(client, flags, out) {
|
|
419
|
+
async function runRecruiterCreateJob(client, flags, out, readers = DEFAULT_JOB_CREATE_READERS) {
|
|
357
420
|
const accountId = requireAccount(flags.account, out);
|
|
358
421
|
const outOpts = resolveOutputOpts(flags);
|
|
359
|
-
const
|
|
422
|
+
const assembled = await assembleJobCreateBody(flags, readers);
|
|
423
|
+
if ("error" in assembled) {
|
|
424
|
+
out.stderr.write(`error: ${assembled.error}
|
|
425
|
+
`);
|
|
426
|
+
process.exit(2);
|
|
427
|
+
}
|
|
428
|
+
const body = assembled.body;
|
|
360
429
|
if (flags.preview) {
|
|
361
430
|
const preview = buildPreviewOutput({
|
|
362
431
|
method: "recruiter.createJob",
|
|
@@ -561,7 +630,13 @@ var recruiterSearchPeopleCommand = defineCommand({
|
|
|
561
630
|
meta: { name: "people", description: "Search Recruiter member profiles." },
|
|
562
631
|
args: {
|
|
563
632
|
...GLOBAL_FLAGS,
|
|
564
|
-
keywords: { type: "string", description: "Keyword search string." }
|
|
633
|
+
keywords: { type: "string", description: "Keyword search string." },
|
|
634
|
+
filters: { type: "string", description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin." },
|
|
635
|
+
"filters-file": { type: "string", description: "Path to a JSON file with the filter body." },
|
|
636
|
+
locale: { type: "string", description: "Result locale, e.g. en." },
|
|
637
|
+
"employment-type": { type: "string", description: "Employment type ids (comma-separated)." },
|
|
638
|
+
function: { type: "string", description: "Job function ids (comma-separated)." },
|
|
639
|
+
"profile-language": { type: "string", description: "Profile language codes (comma-separated)." }
|
|
565
640
|
},
|
|
566
641
|
async run({ args }) {
|
|
567
642
|
const flags = args;
|
|
@@ -585,7 +660,8 @@ var recruiterSearchParametersCommand = defineCommand({
|
|
|
585
660
|
meta: { name: "parameters", description: "Resolve Recruiter filter parameter IDs." },
|
|
586
661
|
args: {
|
|
587
662
|
...GLOBAL_FLAGS,
|
|
588
|
-
type: { type: "string", description: "Parameter type (e.g. LOCATION, INDUSTRY, TITLE).", required: true }
|
|
663
|
+
type: { type: "string", description: "Parameter type (e.g. LOCATION, INDUSTRY, TITLE).", required: true },
|
|
664
|
+
keywords: { type: "string", description: "Human term to resolve (e.g. Berlin)." }
|
|
589
665
|
},
|
|
590
666
|
async run({ args }) {
|
|
591
667
|
const flags = args;
|
|
@@ -768,7 +844,14 @@ var recruiterJobsCommand = defineCommand({
|
|
|
768
844
|
});
|
|
769
845
|
var recruiterJobCreateCommand = defineCommand({
|
|
770
846
|
meta: { name: "create", description: "Create a Recruiter job posting draft." },
|
|
771
|
-
args: {
|
|
847
|
+
args: {
|
|
848
|
+
...GLOBAL_FLAGS,
|
|
849
|
+
"body-file": { type: "string", description: "Path to a JSON file with the full job-create body." },
|
|
850
|
+
body: { type: "string", description: "Read the JSON job-create body from stdin (pass '-')." },
|
|
851
|
+
"job-title": { type: "string", description: "Job title text (merged over the JSON as job_title.text)." },
|
|
852
|
+
description: { type: "string", description: "Job description (merged over the JSON)." },
|
|
853
|
+
"employment-type": { type: "string", description: "Employment type, e.g. FULL_TIME (merged over the JSON)." }
|
|
854
|
+
},
|
|
772
855
|
async run({ args }) {
|
|
773
856
|
const flags = args;
|
|
774
857
|
const cfg = await resolveEffectiveConfig({
|
|
@@ -9,6 +9,12 @@ import {
|
|
|
9
9
|
import {
|
|
10
10
|
resolveIdentifier
|
|
11
11
|
} from "./chunk-BNUTM6KD.js";
|
|
12
|
+
import {
|
|
13
|
+
DEFAULT_FILTER_READERS,
|
|
14
|
+
assembleFilters,
|
|
15
|
+
splitCsv,
|
|
16
|
+
splitCsvNumbers
|
|
17
|
+
} from "./chunk-42VUUKQ3.js";
|
|
12
18
|
import {
|
|
13
19
|
streamAll
|
|
14
20
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -18,10 +24,10 @@ import {
|
|
|
18
24
|
renderSuccess,
|
|
19
25
|
renderUnexpectedError,
|
|
20
26
|
resolveEffectiveConfig
|
|
21
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-UPNQPAJG.js";
|
|
22
28
|
import {
|
|
23
29
|
GLOBAL_FLAGS
|
|
24
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-QQRTODHN.js";
|
|
25
31
|
|
|
26
32
|
// src/commands/sales-nav.ts
|
|
27
33
|
import { defineCommand } from "citty";
|
|
@@ -80,7 +86,7 @@ async function runSalesNavSync(client, flags, out) {
|
|
|
80
86
|
await handleSdkError(err, outOpts, out);
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
|
-
async function runSalesNavSearchPeople(client, flags, out) {
|
|
89
|
+
async function runSalesNavSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
84
90
|
rejectPreviewOnRead(flags.preview, out);
|
|
85
91
|
const accountId = requireAccount(flags.account, out);
|
|
86
92
|
const ns = client.account(accountId);
|
|
@@ -89,8 +95,18 @@ async function runSalesNavSearchPeople(client, flags, out) {
|
|
|
89
95
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
90
96
|
const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
|
|
91
97
|
const cursor = flags.cursor;
|
|
92
|
-
const
|
|
98
|
+
const assembled = await assembleFilters(flags, readers);
|
|
99
|
+
if ("error" in assembled) {
|
|
100
|
+
out.stderr.write(`error: ${assembled.error}
|
|
101
|
+
`);
|
|
102
|
+
process.exit(2);
|
|
103
|
+
}
|
|
104
|
+
const body = assembled.body;
|
|
93
105
|
if (flags.keywords) body["keywords"] = flags.keywords;
|
|
106
|
+
if (flags["first-name"]) body["first_name"] = flags["first-name"];
|
|
107
|
+
if (flags["last-name"]) body["last_name"] = flags["last-name"];
|
|
108
|
+
if (flags.groups) body["groups"] = splitCsv(flags.groups);
|
|
109
|
+
if (flags["profile-language"]) body["profile_language"] = splitCsv(flags["profile-language"]);
|
|
94
110
|
const params = {};
|
|
95
111
|
if (limit !== void 0) params["limit"] = limit;
|
|
96
112
|
if (cursor) params["cursor"] = cursor;
|
|
@@ -119,7 +135,7 @@ async function runSalesNavSearchPeople(client, flags, out) {
|
|
|
119
135
|
await handleSdkError(err, outOpts, out);
|
|
120
136
|
}
|
|
121
137
|
}
|
|
122
|
-
async function runSalesNavSearchCompanies(client, flags, out) {
|
|
138
|
+
async function runSalesNavSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
123
139
|
rejectPreviewOnRead(flags.preview, out);
|
|
124
140
|
const accountId = requireAccount(flags.account, out);
|
|
125
141
|
const ns = client.account(accountId);
|
|
@@ -128,8 +144,17 @@ async function runSalesNavSearchCompanies(client, flags, out) {
|
|
|
128
144
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
129
145
|
const limit = flags.limit ? parseInt(flags.limit, 10) : void 0;
|
|
130
146
|
const cursor = flags.cursor;
|
|
131
|
-
const
|
|
147
|
+
const assembled = await assembleFilters(flags, readers);
|
|
148
|
+
if ("error" in assembled) {
|
|
149
|
+
out.stderr.write(`error: ${assembled.error}
|
|
150
|
+
`);
|
|
151
|
+
process.exit(2);
|
|
152
|
+
}
|
|
153
|
+
const body = assembled.body;
|
|
132
154
|
if (flags.keywords) body["keywords"] = flags.keywords;
|
|
155
|
+
if (flags.technologies) body["technologies"] = splitCsv(flags.technologies);
|
|
156
|
+
if (flags["recent-activities"]) body["recent_activities"] = splitCsv(flags["recent-activities"]);
|
|
157
|
+
if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
|
|
133
158
|
const params = {};
|
|
134
159
|
if (limit !== void 0) params["limit"] = limit;
|
|
135
160
|
if (cursor) params["cursor"] = cursor;
|
|
@@ -165,6 +190,8 @@ async function runSalesNavGetParameters(client, flags, out) {
|
|
|
165
190
|
const outOpts = resolveOutputOpts(flags);
|
|
166
191
|
const params = {};
|
|
167
192
|
if (flags.type) params["type"] = flags.type;
|
|
193
|
+
if (flags.keywords) params["keywords"] = flags.keywords;
|
|
194
|
+
if (flags.limit) params["limit"] = parseInt(flags.limit, 10);
|
|
168
195
|
try {
|
|
169
196
|
const result = await ns.salesNavigator.getParameters(params);
|
|
170
197
|
renderSuccess(result, outOpts, out);
|
|
@@ -329,7 +356,13 @@ var salesNavSearchPeopleCommand = defineCommand({
|
|
|
329
356
|
meta: { name: "people", description: "Search Sales Navigator member profiles." },
|
|
330
357
|
args: {
|
|
331
358
|
...GLOBAL_FLAGS,
|
|
332
|
-
keywords: { type: "string", description: "Keyword search string." }
|
|
359
|
+
keywords: { type: "string", description: "Keyword search string." },
|
|
360
|
+
filters: { type: "string", description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin." },
|
|
361
|
+
"filters-file": { type: "string", description: "Path to a JSON file with the filter body." },
|
|
362
|
+
"first-name": { type: "string", description: "First name to match." },
|
|
363
|
+
"last-name": { type: "string", description: "Last name to match." },
|
|
364
|
+
groups: { type: "string", description: "Group ids (comma-separated)." },
|
|
365
|
+
"profile-language": { type: "string", description: "Profile language codes (comma-separated)." }
|
|
333
366
|
},
|
|
334
367
|
async run({ args }) {
|
|
335
368
|
const flags = args;
|
|
@@ -353,7 +386,12 @@ var salesNavSearchCompaniesCommand = defineCommand({
|
|
|
353
386
|
meta: { name: "companies", description: "Search Sales Navigator companies." },
|
|
354
387
|
args: {
|
|
355
388
|
...GLOBAL_FLAGS,
|
|
356
|
-
keywords: { type: "string", description: "Keyword search string." }
|
|
389
|
+
keywords: { type: "string", description: "Keyword search string." },
|
|
390
|
+
filters: { type: "string", description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin." },
|
|
391
|
+
"filters-file": { type: "string", description: "Path to a JSON file with the filter body." },
|
|
392
|
+
technologies: { type: "string", description: "Technology tags (comma-separated)." },
|
|
393
|
+
"recent-activities": { type: "string", description: "Recent activity ids (comma-separated)." },
|
|
394
|
+
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." }
|
|
357
395
|
},
|
|
358
396
|
async run({ args }) {
|
|
359
397
|
const flags = args;
|
|
@@ -377,7 +415,8 @@ var salesNavSearchParametersCommand = defineCommand({
|
|
|
377
415
|
meta: { name: "parameters", description: "Resolve Sales Navigator filter parameter IDs." },
|
|
378
416
|
args: {
|
|
379
417
|
...GLOBAL_FLAGS,
|
|
380
|
-
type: { type: "string", description: "Parameter type (e.g. LOCATION, INDUSTRY, TITLE).", required: true }
|
|
418
|
+
type: { type: "string", description: "Parameter type (e.g. LOCATION, INDUSTRY, TITLE).", required: true },
|
|
419
|
+
keywords: { type: "string", description: "Human term to resolve (e.g. Berlin)." }
|
|
381
420
|
},
|
|
382
421
|
async run({ args }) {
|
|
383
422
|
const flags = args;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
DEFAULT_FILTER_READERS,
|
|
4
|
+
assembleFilters,
|
|
5
|
+
splitCsv,
|
|
6
|
+
splitCsvNumbers
|
|
7
|
+
} from "./chunk-42VUUKQ3.js";
|
|
2
8
|
import {
|
|
3
9
|
streamAll
|
|
4
10
|
} from "./chunk-SND3NHCT.js";
|
|
@@ -8,13 +14,23 @@ import {
|
|
|
8
14
|
renderSuccess,
|
|
9
15
|
renderUnexpectedError,
|
|
10
16
|
resolveEffectiveConfig
|
|
11
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-UPNQPAJG.js";
|
|
12
18
|
import {
|
|
13
19
|
GLOBAL_FLAGS
|
|
14
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-QQRTODHN.js";
|
|
15
21
|
|
|
16
22
|
// src/commands/search.ts
|
|
17
23
|
import { defineCommand } from "citty";
|
|
24
|
+
var FILTER_FLAGS = {
|
|
25
|
+
filters: {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Filter body as a JSON object (escape hatch for the full filter surface); '-' reads JSON from stdin."
|
|
28
|
+
},
|
|
29
|
+
"filters-file": {
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "Path to a JSON file with the filter body."
|
|
32
|
+
}
|
|
33
|
+
};
|
|
18
34
|
function buildOutputStreams() {
|
|
19
35
|
return {
|
|
20
36
|
stdout: { write: (s) => process.stdout.write(s) },
|
|
@@ -47,22 +63,66 @@ function resolveOutputOpts(flags) {
|
|
|
47
63
|
fields: flags.fields
|
|
48
64
|
};
|
|
49
65
|
}
|
|
50
|
-
function
|
|
51
|
-
const body = {};
|
|
66
|
+
function applyCommonSearchFlags(body, flags) {
|
|
52
67
|
if (flags.keywords) body["keywords"] = flags.keywords;
|
|
53
68
|
if (flags.url) body["url"] = flags.url;
|
|
54
69
|
if (flags.cursor) body["cursor"] = flags.cursor;
|
|
55
70
|
if (flags.limit) body["limit"] = parseInt(flags.limit, 10);
|
|
56
|
-
return body;
|
|
57
71
|
}
|
|
58
|
-
|
|
72
|
+
var NAMED_FLAG_MAPPERS = {
|
|
73
|
+
people(body, flags) {
|
|
74
|
+
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
75
|
+
if (flags.location) body["location"] = splitCsv(flags.location);
|
|
76
|
+
if (flags.company) body["company"] = splitCsv(flags.company);
|
|
77
|
+
if (flags["past-company"]) body["past_company"] = splitCsv(flags["past-company"]);
|
|
78
|
+
if (flags.school) body["school"] = splitCsv(flags.school);
|
|
79
|
+
if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
|
|
80
|
+
if (flags["connections-of"]) body["connections_of"] = flags["connections-of"];
|
|
81
|
+
if (flags["followers-of"]) body["followers_of"] = flags["followers-of"];
|
|
82
|
+
},
|
|
83
|
+
companies(body, flags) {
|
|
84
|
+
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
85
|
+
if (flags.location) body["location"] = splitCsv(flags.location);
|
|
86
|
+
if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
|
|
87
|
+
},
|
|
88
|
+
posts(body, flags) {
|
|
89
|
+
if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
|
|
90
|
+
if (flags["date-posted"]) body["date_posted"] = flags["date-posted"];
|
|
91
|
+
if (flags["content-type"]) body["content_type"] = flags["content-type"];
|
|
92
|
+
},
|
|
93
|
+
jobs(body, flags) {
|
|
94
|
+
if (flags.location) body["location"] = splitCsv(flags.location);
|
|
95
|
+
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
96
|
+
if (flags.seniority) body["seniority"] = splitCsv(flags.seniority);
|
|
97
|
+
if (flags.function) body["function"] = splitCsv(flags.function);
|
|
98
|
+
if (flags["job-type"]) body["job_type"] = splitCsv(flags["job-type"]);
|
|
99
|
+
if (flags.company) body["company"] = splitCsv(flags.company);
|
|
100
|
+
if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
|
|
101
|
+
if (flags.region) body["region"] = flags.region;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
async function buildSearchBody(kind, flags, readers) {
|
|
105
|
+
const assembled = await assembleFilters(flags, readers);
|
|
106
|
+
if ("error" in assembled) return assembled;
|
|
107
|
+
const body = assembled.body;
|
|
108
|
+
applyCommonSearchFlags(body, flags);
|
|
109
|
+
NAMED_FLAG_MAPPERS[kind](body, flags);
|
|
110
|
+
return { body };
|
|
111
|
+
}
|
|
112
|
+
async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
59
113
|
rejectPreviewOnRead(flags.preview, out);
|
|
60
114
|
const accountId = requireAccount(flags.account, out);
|
|
61
115
|
const ns = client.account(accountId);
|
|
62
116
|
const outOpts = resolveOutputOpts(flags);
|
|
63
117
|
const all = flags.all ?? false;
|
|
64
118
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
65
|
-
const
|
|
119
|
+
const assembled = await buildSearchBody("people", flags, readers);
|
|
120
|
+
if ("error" in assembled) {
|
|
121
|
+
out.stderr.write(`error: ${assembled.error}
|
|
122
|
+
`);
|
|
123
|
+
process.exit(2);
|
|
124
|
+
}
|
|
125
|
+
const body = assembled.body;
|
|
66
126
|
try {
|
|
67
127
|
if (all) {
|
|
68
128
|
const fn = (p) => ns.search.people(p);
|
|
@@ -87,14 +147,20 @@ async function runSearchPeople(client, flags, out) {
|
|
|
87
147
|
process.exit(1);
|
|
88
148
|
}
|
|
89
149
|
}
|
|
90
|
-
async function runSearchCompanies(client, flags, out) {
|
|
150
|
+
async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
91
151
|
rejectPreviewOnRead(flags.preview, out);
|
|
92
152
|
const accountId = requireAccount(flags.account, out);
|
|
93
153
|
const ns = client.account(accountId);
|
|
94
154
|
const outOpts = resolveOutputOpts(flags);
|
|
95
155
|
const all = flags.all ?? false;
|
|
96
156
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
97
|
-
const
|
|
157
|
+
const assembled = await buildSearchBody("companies", flags, readers);
|
|
158
|
+
if ("error" in assembled) {
|
|
159
|
+
out.stderr.write(`error: ${assembled.error}
|
|
160
|
+
`);
|
|
161
|
+
process.exit(2);
|
|
162
|
+
}
|
|
163
|
+
const body = assembled.body;
|
|
98
164
|
try {
|
|
99
165
|
if (all) {
|
|
100
166
|
const fn = (p) => ns.search.companies(p);
|
|
@@ -119,14 +185,20 @@ async function runSearchCompanies(client, flags, out) {
|
|
|
119
185
|
process.exit(1);
|
|
120
186
|
}
|
|
121
187
|
}
|
|
122
|
-
async function runSearchPosts(client, flags, out) {
|
|
188
|
+
async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
123
189
|
rejectPreviewOnRead(flags.preview, out);
|
|
124
190
|
const accountId = requireAccount(flags.account, out);
|
|
125
191
|
const ns = client.account(accountId);
|
|
126
192
|
const outOpts = resolveOutputOpts(flags);
|
|
127
193
|
const all = flags.all ?? false;
|
|
128
194
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
129
|
-
const
|
|
195
|
+
const assembled = await buildSearchBody("posts", flags, readers);
|
|
196
|
+
if ("error" in assembled) {
|
|
197
|
+
out.stderr.write(`error: ${assembled.error}
|
|
198
|
+
`);
|
|
199
|
+
process.exit(2);
|
|
200
|
+
}
|
|
201
|
+
const body = assembled.body;
|
|
130
202
|
try {
|
|
131
203
|
if (all) {
|
|
132
204
|
const fn = (p) => ns.search.posts(p);
|
|
@@ -151,14 +223,20 @@ async function runSearchPosts(client, flags, out) {
|
|
|
151
223
|
process.exit(1);
|
|
152
224
|
}
|
|
153
225
|
}
|
|
154
|
-
async function runSearchJobs(client, flags, out) {
|
|
226
|
+
async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
155
227
|
rejectPreviewOnRead(flags.preview, out);
|
|
156
228
|
const accountId = requireAccount(flags.account, out);
|
|
157
229
|
const ns = client.account(accountId);
|
|
158
230
|
const outOpts = resolveOutputOpts(flags);
|
|
159
231
|
const all = flags.all ?? false;
|
|
160
232
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
161
|
-
const
|
|
233
|
+
const assembled = await buildSearchBody("jobs", flags, readers);
|
|
234
|
+
if ("error" in assembled) {
|
|
235
|
+
out.stderr.write(`error: ${assembled.error}
|
|
236
|
+
`);
|
|
237
|
+
process.exit(2);
|
|
238
|
+
}
|
|
239
|
+
const body = assembled.body;
|
|
162
240
|
try {
|
|
163
241
|
if (all) {
|
|
164
242
|
const fn = (p) => ns.search.jobs(p);
|
|
@@ -212,7 +290,16 @@ var searchPeopleCommand = defineCommand({
|
|
|
212
290
|
args: {
|
|
213
291
|
...GLOBAL_FLAGS,
|
|
214
292
|
keywords: { type: "string", description: "Full-text keyword search." },
|
|
215
|
-
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." }
|
|
293
|
+
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
294
|
+
...FILTER_FLAGS,
|
|
295
|
+
industry: { type: "string", description: "Industry ids (comma-separated)." },
|
|
296
|
+
location: { type: "string", description: "Location ids (comma-separated)." },
|
|
297
|
+
company: { type: "string", description: "Current company ids (comma-separated)." },
|
|
298
|
+
"past-company": { type: "string", description: "Past company ids (comma-separated)." },
|
|
299
|
+
school: { type: "string", description: "School ids (comma-separated)." },
|
|
300
|
+
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." },
|
|
301
|
+
"connections-of": { type: "string", description: "Member id whose connections to search." },
|
|
302
|
+
"followers-of": { type: "string", description: "Member id whose followers to search." }
|
|
216
303
|
},
|
|
217
304
|
async run({ args }) {
|
|
218
305
|
const flags = args;
|
|
@@ -236,7 +323,12 @@ var searchCompaniesCommand = defineCommand({
|
|
|
236
323
|
meta: { name: "companies", description: "Search LinkedIn companies." },
|
|
237
324
|
args: {
|
|
238
325
|
...GLOBAL_FLAGS,
|
|
239
|
-
keywords: { type: "string", description: "Full-text keyword search." }
|
|
326
|
+
keywords: { type: "string", description: "Full-text keyword search." },
|
|
327
|
+
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
328
|
+
...FILTER_FLAGS,
|
|
329
|
+
industry: { type: "string", description: "Industry ids (comma-separated)." },
|
|
330
|
+
location: { type: "string", description: "Location ids (comma-separated)." },
|
|
331
|
+
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." }
|
|
240
332
|
},
|
|
241
333
|
async run({ args }) {
|
|
242
334
|
const flags = args;
|
|
@@ -260,7 +352,12 @@ var searchPostsCommand = defineCommand({
|
|
|
260
352
|
meta: { name: "posts", description: "Search LinkedIn posts." },
|
|
261
353
|
args: {
|
|
262
354
|
...GLOBAL_FLAGS,
|
|
263
|
-
keywords: { type: "string", description: "Full-text keyword search." }
|
|
355
|
+
keywords: { type: "string", description: "Full-text keyword search." },
|
|
356
|
+
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
357
|
+
...FILTER_FLAGS,
|
|
358
|
+
"sort-by": { type: "string", description: "Sort order (e.g. relevance, date)." },
|
|
359
|
+
"date-posted": { type: "string", description: "Date-posted window (e.g. past-day, past-week)." },
|
|
360
|
+
"content-type": { type: "string", description: "Content type (e.g. videos, images, jobs)." }
|
|
264
361
|
},
|
|
265
362
|
async run({ args }) {
|
|
266
363
|
const flags = args;
|
|
@@ -284,7 +381,17 @@ var searchJobsCommand = defineCommand({
|
|
|
284
381
|
meta: { name: "jobs", description: "Search LinkedIn jobs." },
|
|
285
382
|
args: {
|
|
286
383
|
...GLOBAL_FLAGS,
|
|
287
|
-
keywords: { type: "string", description: "Full-text keyword search." }
|
|
384
|
+
keywords: { type: "string", description: "Full-text keyword search." },
|
|
385
|
+
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
386
|
+
...FILTER_FLAGS,
|
|
387
|
+
location: { type: "string", description: "Location ids (comma-separated)." },
|
|
388
|
+
industry: { type: "string", description: "Industry ids (comma-separated)." },
|
|
389
|
+
seniority: { type: "string", description: "Seniority ids (comma-separated)." },
|
|
390
|
+
function: { type: "string", description: "Job function ids (comma-separated)." },
|
|
391
|
+
"job-type": { type: "string", description: "Job type ids, e.g. F,P (comma-separated)." },
|
|
392
|
+
company: { type: "string", description: "Company ids (comma-separated)." },
|
|
393
|
+
"sort-by": { type: "string", description: "Sort order (e.g. relevance, recent)." },
|
|
394
|
+
region: { type: "string", description: "Region id." }
|
|
288
395
|
},
|
|
289
396
|
async run({ args }) {
|
|
290
397
|
const flags = args;
|
|
@@ -11,10 +11,10 @@ import {
|
|
|
11
11
|
renderSuccess,
|
|
12
12
|
renderUnexpectedError,
|
|
13
13
|
resolveEffectiveConfig
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-UPNQPAJG.js";
|
|
15
15
|
import {
|
|
16
16
|
GLOBAL_FLAGS
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-QQRTODHN.js";
|
|
18
18
|
|
|
19
19
|
// src/commands/webhook.ts
|
|
20
20
|
import { defineCommand } from "citty";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curviate/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Official command-line interface for the Curviate API.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"access": "public"
|
|
18
18
|
},
|
|
19
19
|
"bin": {
|
|
20
|
-
"curviate": "
|
|
20
|
+
"curviate": "dist/cli.js"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist/",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@curviate/sdk": "^0.
|
|
43
|
+
"@curviate/sdk": "^0.2.0",
|
|
44
44
|
"citty": "^0.1.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|