@curviate/cli 0.6.0 → 0.7.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 +43 -0
- package/dist/{account-ZWBNNQKQ.js → account-O5GZNE72.js} +3 -2
- package/dist/{chunk-SND3NHCT.js → chunk-GXTZION6.js} +1 -2
- package/dist/{chunk-6VBOKOQJ.js → chunk-J5KGG2EE.js} +81 -0
- package/dist/cli.js +10 -10
- package/dist/{company-SZPGJE3M.js → company-HPHLJCKB.js} +3 -3
- package/dist/{connect-RMT7OS3I.js → connect-EUJBSLNM.js} +11 -9
- package/dist/{inbox-MIKI4HU3.js → inbox-YV6GPRG6.js} +5 -3
- package/dist/{post-2FYHZAKC.js → post-KBSR3ADF.js} +7 -4
- package/dist/{profile-NDDG26PL.js → profile-GGUBDI3P.js} +23 -14
- package/dist/{recruiter-3DRGDOVV.js → recruiter-7UEBT3JZ.js} +7 -4
- package/dist/{sales-nav-7WPN7BT4.js → sales-nav-LSBARRGL.js} +5 -3
- package/dist/{search-QO237C4O.js → search-RZYVGGMN.js} +168 -36
- package/dist/{webhook-FDIERREB.js → webhook-F6CRIISR.js} +3 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,49 @@ 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.7.0] - 2026-07-01
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- `search` — named filter flags that previously required raw `--filters` JSON:
|
|
16
|
+
- **companies**: `--has-job-offers`, `--headcount <buckets>` (comma-separated
|
|
17
|
+
size buckets `1-10 … 5001-10000`; `10001+` reports a usage error).
|
|
18
|
+
- **jobs**: `--title <ids>`, `--presence`, `--benefits`, `--commitments`,
|
|
19
|
+
`--has-verifications`, `--under-10-applicants`, `--in-your-network`,
|
|
20
|
+
`--fair-chance-employer`, `--location-within-area <miles>`.
|
|
21
|
+
- **people**: `--connections-of`, `--followers-of` (comma-separated → array).
|
|
22
|
+
- **posts**: `--posted-by-member`, `--posted-by-company`, `--posted-by-me`,
|
|
23
|
+
`--mentioning-member`, `--mentioning-company`, `--author-industry`,
|
|
24
|
+
`--author-company`, `--author-keywords`.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- `search jobs` slim `company_name` was always `null` — now derived from the
|
|
29
|
+
nested `company.name` (handles postings with no linked company). `--verbose`
|
|
30
|
+
still returns the raw response unchanged.
|
|
31
|
+
- `search parameters --type`, `search jobs --seniority`/`--job-type`, and
|
|
32
|
+
`search posts --content-type` help text now lists the correct/complete
|
|
33
|
+
enumerations (no behavior change).
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Updated `@curviate/sdk` dependency to `^0.5.0`.
|
|
38
|
+
|
|
39
|
+
## [0.6.1] - 2026-07-01
|
|
40
|
+
|
|
41
|
+
### Added
|
|
42
|
+
|
|
43
|
+
- `search people --title` (→ `advanced_keywords.title` keyword, nested-merged),
|
|
44
|
+
`--industry`, `--profile-language`; `--filters` deep-merge (named flags win).
|
|
45
|
+
- `search jobs --location` → `region` (single id) + `--region` alias +
|
|
46
|
+
`--date-posted <days>` (number).
|
|
47
|
+
- `search posts --date-posted` hyphen→underscore normalize.
|
|
48
|
+
- `--all` truncation emits `{"object":"stream_truncated",…}` JSON.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- Updated `@curviate/sdk` dependency to `^0.4.1`.
|
|
53
|
+
|
|
11
54
|
## [0.6.0] - 2026-06-30
|
|
12
55
|
|
|
13
56
|
### Added
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-R3VLWLVV.js";
|
|
5
5
|
import {
|
|
6
6
|
streamAll
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GXTZION6.js";
|
|
8
8
|
import {
|
|
9
9
|
createClient,
|
|
10
10
|
renderError,
|
|
@@ -68,7 +68,8 @@ async function runAccountList(client, flags, out) {
|
|
|
68
68
|
const fn = (p) => client.accounts.list(p);
|
|
69
69
|
for await (const item of streamAll(fn, params, {
|
|
70
70
|
maxPages,
|
|
71
|
-
onTruncated: (
|
|
71
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
72
|
+
`)
|
|
72
73
|
})) {
|
|
73
74
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
74
75
|
}
|
|
@@ -32,9 +32,8 @@ async function* streamAll(fn, params, opts = {}) {
|
|
|
32
32
|
cursor = page.cursor;
|
|
33
33
|
if (!cursor) break;
|
|
34
34
|
if (pageCount >= maxPages) {
|
|
35
|
-
const msg = `Streaming truncated at ${maxPages} page(s) \u2014 more results may exist. Increase --max-pages or use --cursor / --limit for manual paging.`;
|
|
36
35
|
if (opts.onTruncated) {
|
|
37
|
-
opts.onTruncated(
|
|
36
|
+
opts.onTruncated(pageCount, cursor !== null && cursor !== void 0);
|
|
38
37
|
}
|
|
39
38
|
break;
|
|
40
39
|
}
|
|
@@ -106,6 +106,79 @@ function slimInviteReceived(data) {
|
|
|
106
106
|
cursor: d["cursor"] ?? null
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
|
+
function slimSearchPeopleItem(item) {
|
|
110
|
+
return {
|
|
111
|
+
id: item["id"] ?? null,
|
|
112
|
+
public_identifier: item["public_identifier"] ?? null,
|
|
113
|
+
full_name: item["full_name"] ?? null,
|
|
114
|
+
headline: item["headline"] ?? null,
|
|
115
|
+
location: item["location"] ?? null,
|
|
116
|
+
network_distance: item["network_distance"] ?? null
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function slimSearchPeople(data) {
|
|
120
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
121
|
+
const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchPeopleItem) : [];
|
|
122
|
+
return { ...d, items };
|
|
123
|
+
}
|
|
124
|
+
function slimSearchCompaniesItem(item) {
|
|
125
|
+
const result = {
|
|
126
|
+
id: item["id"] ?? null,
|
|
127
|
+
name: item["name"] ?? null,
|
|
128
|
+
location: item["location"] ?? null,
|
|
129
|
+
followers_count: item["followers_count"] ?? null
|
|
130
|
+
};
|
|
131
|
+
if (Object.prototype.hasOwnProperty.call(item, "industry")) {
|
|
132
|
+
result["industry"] = item["industry"];
|
|
133
|
+
}
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
function slimSearchCompanies(data) {
|
|
137
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
138
|
+
const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchCompaniesItem) : [];
|
|
139
|
+
return { ...d, items };
|
|
140
|
+
}
|
|
141
|
+
function slimSearchJobsItem(item) {
|
|
142
|
+
const company = item["company"];
|
|
143
|
+
return {
|
|
144
|
+
job_urn: item["job_urn"] ?? null,
|
|
145
|
+
title: item["title"] ?? null,
|
|
146
|
+
location: item["location"] ?? null,
|
|
147
|
+
company_name: company?.["name"] ?? null,
|
|
148
|
+
posted_at: item["posted_at"] ?? null,
|
|
149
|
+
easy_apply: item["easy_apply"] ?? null
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function slimSearchJobs(data) {
|
|
153
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
154
|
+
const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchJobsItem) : [];
|
|
155
|
+
return { ...d, items };
|
|
156
|
+
}
|
|
157
|
+
function slimSearchPostsItem(item) {
|
|
158
|
+
const rawAuthor = item["author"] !== null && item["author"] !== void 0 && typeof item["author"] === "object" ? item["author"] : null;
|
|
159
|
+
const author = rawAuthor !== null ? { name: rawAuthor["name"] ?? null } : null;
|
|
160
|
+
const rawText = item["text"];
|
|
161
|
+
let text;
|
|
162
|
+
if (rawText === null || rawText === void 0) {
|
|
163
|
+
text = null;
|
|
164
|
+
} else {
|
|
165
|
+
const s = String(rawText);
|
|
166
|
+
text = s.length > 200 ? s.slice(0, 200) : s;
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
post_urn: item["post_urn"] ?? null,
|
|
170
|
+
posted_at: item["posted_at"] ?? null,
|
|
171
|
+
author,
|
|
172
|
+
text,
|
|
173
|
+
reaction_count: item["reaction_count"] ?? null,
|
|
174
|
+
comment_count: item["comment_count"] ?? null
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function slimSearchPosts(data) {
|
|
178
|
+
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
179
|
+
const items = Array.isArray(d["items"]) ? d["items"].map(slimSearchPostsItem) : [];
|
|
180
|
+
return { ...d, items };
|
|
181
|
+
}
|
|
109
182
|
function slimCompany(data) {
|
|
110
183
|
const d = data !== null && data !== void 0 && typeof data === "object" ? data : {};
|
|
111
184
|
const rawMessaging = d["messaging"] !== null && d["messaging"] !== void 0 && typeof d["messaging"] === "object" ? d["messaging"] : null;
|
|
@@ -137,5 +210,13 @@ export {
|
|
|
137
210
|
slimInviteSent,
|
|
138
211
|
slimInviteReceivedItem,
|
|
139
212
|
slimInviteReceived,
|
|
213
|
+
slimSearchPeopleItem,
|
|
214
|
+
slimSearchPeople,
|
|
215
|
+
slimSearchCompaniesItem,
|
|
216
|
+
slimSearchCompanies,
|
|
217
|
+
slimSearchJobsItem,
|
|
218
|
+
slimSearchJobs,
|
|
219
|
+
slimSearchPostsItem,
|
|
220
|
+
slimSearchPosts,
|
|
140
221
|
slimCompany
|
|
141
222
|
};
|
package/dist/cli.js
CHANGED
|
@@ -143,17 +143,17 @@ var main = defineCommand({
|
|
|
143
143
|
// ---------------------------------------------------------------------------
|
|
144
144
|
// Noun groups — lazy-loaded on first invocation.
|
|
145
145
|
// ---------------------------------------------------------------------------
|
|
146
|
-
profile: () => import("./profile-
|
|
147
|
-
company: () => import("./company-
|
|
148
|
-
connect: () => import("./connect-
|
|
149
|
-
search: () => import("./search-
|
|
150
|
-
inbox: () => import("./inbox-
|
|
146
|
+
profile: () => import("./profile-GGUBDI3P.js").then((m) => m.profileCommand),
|
|
147
|
+
company: () => import("./company-HPHLJCKB.js").then((m) => m.companyCommand),
|
|
148
|
+
connect: () => import("./connect-EUJBSLNM.js").then((m) => m.connectCommand),
|
|
149
|
+
search: () => import("./search-RZYVGGMN.js").then((m) => m.searchCommand),
|
|
150
|
+
inbox: () => import("./inbox-YV6GPRG6.js").then((m) => m.inboxCommand),
|
|
151
151
|
message: () => import("./message-YRMLMHK7.js").then((m) => m.messageCommand),
|
|
152
|
-
post: () => import("./post-
|
|
153
|
-
account: () => import("./account-
|
|
154
|
-
webhook: () => import("./webhook-
|
|
155
|
-
"sales-nav": () => import("./sales-nav-
|
|
156
|
-
recruiter: () => import("./recruiter-
|
|
152
|
+
post: () => import("./post-KBSR3ADF.js").then((m) => m.postCommand),
|
|
153
|
+
account: () => import("./account-O5GZNE72.js").then((m) => m.accountCommand),
|
|
154
|
+
webhook: () => import("./webhook-F6CRIISR.js").then((m) => m.webhookCommand),
|
|
155
|
+
"sales-nav": () => import("./sales-nav-LSBARRGL.js").then((m) => m.salesNavCommand),
|
|
156
|
+
recruiter: () => import("./recruiter-7UEBT3JZ.js").then((m) => m.recruiterCommand)
|
|
157
157
|
},
|
|
158
158
|
async run() {
|
|
159
159
|
const { runMain } = await import("citty");
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildPreviewOutput
|
|
4
4
|
} from "./chunk-R3VLWLVV.js";
|
|
5
|
-
import {
|
|
6
|
-
slimInviteReceived,
|
|
7
|
-
slimInviteReceivedItem,
|
|
8
|
-
slimInviteSent,
|
|
9
|
-
slimInviteSentItem
|
|
10
|
-
} from "./chunk-6VBOKOQJ.js";
|
|
11
5
|
import {
|
|
12
6
|
resolveIdentifier
|
|
13
7
|
} from "./chunk-SZB3CFRZ.js";
|
|
14
8
|
import {
|
|
15
9
|
streamAll
|
|
16
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GXTZION6.js";
|
|
11
|
+
import {
|
|
12
|
+
slimInviteReceived,
|
|
13
|
+
slimInviteReceivedItem,
|
|
14
|
+
slimInviteSent,
|
|
15
|
+
slimInviteSentItem
|
|
16
|
+
} from "./chunk-J5KGG2EE.js";
|
|
17
17
|
import {
|
|
18
18
|
createClient,
|
|
19
19
|
renderError,
|
|
@@ -104,7 +104,8 @@ async function runConnectSent(client, flags, out) {
|
|
|
104
104
|
const fn = (p) => ns.invites.listSent(p);
|
|
105
105
|
for await (const item of streamAll(fn, params, {
|
|
106
106
|
maxPages,
|
|
107
|
-
onTruncated: (
|
|
107
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
108
|
+
`)
|
|
108
109
|
})) {
|
|
109
110
|
const projected = !flags.verbose ? slimInviteSentItem(item) : item;
|
|
110
111
|
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
@@ -141,7 +142,8 @@ async function runConnectReceived(client, flags, out) {
|
|
|
141
142
|
const fn = (p) => ns.invites.listReceived(p);
|
|
142
143
|
for await (const item of streamAll(fn, params, {
|
|
143
144
|
maxPages,
|
|
144
|
-
onTruncated: (
|
|
145
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
146
|
+
`)
|
|
145
147
|
})) {
|
|
146
148
|
const projected = !flags.verbose ? slimInviteReceivedItem(item) : item;
|
|
147
149
|
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-SZB3CFRZ.js";
|
|
5
5
|
import {
|
|
6
6
|
streamAll
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GXTZION6.js";
|
|
8
8
|
import {
|
|
9
9
|
createClient,
|
|
10
10
|
renderError,
|
|
@@ -92,7 +92,8 @@ async function runInboxList(client, flags, out) {
|
|
|
92
92
|
const fn = (p) => ns.messaging.listChats(p);
|
|
93
93
|
for await (const item of streamAll(fn, params, {
|
|
94
94
|
maxPages,
|
|
95
|
-
onTruncated: (
|
|
95
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
96
|
+
`)
|
|
96
97
|
})) {
|
|
97
98
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
98
99
|
}
|
|
@@ -140,7 +141,8 @@ async function runInboxMessages(client, flags, out) {
|
|
|
140
141
|
const fn = (p) => ns.messaging.listMessages(chatId, p);
|
|
141
142
|
for await (const item of streamAll(fn, params, {
|
|
142
143
|
maxPages,
|
|
143
|
-
onTruncated: (
|
|
144
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
145
|
+
`)
|
|
144
146
|
})) {
|
|
145
147
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
146
148
|
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-R3VLWLVV.js";
|
|
12
12
|
import {
|
|
13
13
|
streamAll
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-GXTZION6.js";
|
|
15
15
|
import {
|
|
16
16
|
createClient,
|
|
17
17
|
renderError,
|
|
@@ -92,7 +92,8 @@ async function runPostList(client, flags, out) {
|
|
|
92
92
|
const fn = (p) => ns.posts.list(p);
|
|
93
93
|
for await (const item of streamAll(fn, params, {
|
|
94
94
|
maxPages,
|
|
95
|
-
onTruncated: (
|
|
95
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
96
|
+
`)
|
|
96
97
|
})) {
|
|
97
98
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
98
99
|
}
|
|
@@ -246,7 +247,8 @@ async function runPostComments(client, flags, out) {
|
|
|
246
247
|
const fn = (p) => ns.posts.listComments(postId, p);
|
|
247
248
|
for await (const item of streamAll(fn, params, {
|
|
248
249
|
maxPages,
|
|
249
|
-
onTruncated: (
|
|
250
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
251
|
+
`)
|
|
250
252
|
})) {
|
|
251
253
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
252
254
|
}
|
|
@@ -308,7 +310,8 @@ async function runPostReactions(client, flags, out) {
|
|
|
308
310
|
const fn = (p) => ns.posts.listReactions(postId, p);
|
|
309
311
|
for await (const item of streamAll(fn, params, {
|
|
310
312
|
maxPages,
|
|
311
|
-
onTruncated: (
|
|
313
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
314
|
+
`)
|
|
312
315
|
})) {
|
|
313
316
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
314
317
|
}
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildPreviewOutput
|
|
4
4
|
} from "./chunk-R3VLWLVV.js";
|
|
5
|
-
import {
|
|
6
|
-
slimProfile,
|
|
7
|
-
slimProfileMe
|
|
8
|
-
} from "./chunk-6VBOKOQJ.js";
|
|
9
5
|
import {
|
|
10
6
|
resolveIdentifier
|
|
11
7
|
} from "./chunk-SZB3CFRZ.js";
|
|
12
8
|
import {
|
|
13
9
|
streamAll
|
|
14
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GXTZION6.js";
|
|
11
|
+
import {
|
|
12
|
+
slimProfile,
|
|
13
|
+
slimProfileMe
|
|
14
|
+
} from "./chunk-J5KGG2EE.js";
|
|
15
15
|
import {
|
|
16
16
|
createClient,
|
|
17
17
|
renderError,
|
|
@@ -86,7 +86,8 @@ async function runProfileMe(client, flags, out) {
|
|
|
86
86
|
const fn = (p) => ns.profiles.listPosts(ownSlug, p);
|
|
87
87
|
for await (const item of streamAll(fn, params2, {
|
|
88
88
|
maxPages,
|
|
89
|
-
onTruncated: (
|
|
89
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
90
|
+
`)
|
|
90
91
|
})) {
|
|
91
92
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
92
93
|
}
|
|
@@ -99,7 +100,8 @@ async function runProfileMe(client, flags, out) {
|
|
|
99
100
|
const fn = (p) => ns.profiles.listComments(ownSlug, p);
|
|
100
101
|
for await (const item of streamAll(fn, params2, {
|
|
101
102
|
maxPages,
|
|
102
|
-
onTruncated: (
|
|
103
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
104
|
+
`)
|
|
103
105
|
})) {
|
|
104
106
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
105
107
|
}
|
|
@@ -112,7 +114,8 @@ async function runProfileMe(client, flags, out) {
|
|
|
112
114
|
const fn = (p) => ns.profiles.listReactions(ownSlug, p);
|
|
113
115
|
for await (const item of streamAll(fn, params2, {
|
|
114
116
|
maxPages,
|
|
115
|
-
onTruncated: (
|
|
117
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
118
|
+
`)
|
|
116
119
|
})) {
|
|
117
120
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
118
121
|
}
|
|
@@ -125,7 +128,8 @@ async function runProfileMe(client, flags, out) {
|
|
|
125
128
|
const fn = (p) => ns.profiles.listFollowers(ownSlug, p);
|
|
126
129
|
for await (const item of streamAll(fn, params2, {
|
|
127
130
|
maxPages,
|
|
128
|
-
onTruncated: (
|
|
131
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
132
|
+
`)
|
|
129
133
|
})) {
|
|
130
134
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
131
135
|
}
|
|
@@ -200,7 +204,8 @@ async function runProfileGet(client, flags, out) {
|
|
|
200
204
|
const fn = (p) => ns.profiles.listPosts(postId, p);
|
|
201
205
|
for await (const item of streamAll(fn, params, {
|
|
202
206
|
maxPages,
|
|
203
|
-
onTruncated: (
|
|
207
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
208
|
+
`)
|
|
204
209
|
})) {
|
|
205
210
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
206
211
|
}
|
|
@@ -216,7 +221,8 @@ async function runProfileGet(client, flags, out) {
|
|
|
216
221
|
const fn = (p) => ns.profiles.listComments(resolvedId, p);
|
|
217
222
|
for await (const item of streamAll(fn, params, {
|
|
218
223
|
maxPages,
|
|
219
|
-
onTruncated: (
|
|
224
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
225
|
+
`)
|
|
220
226
|
})) {
|
|
221
227
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
222
228
|
}
|
|
@@ -232,7 +238,8 @@ async function runProfileGet(client, flags, out) {
|
|
|
232
238
|
const fn = (p) => ns.profiles.listReactions(resolvedId, p);
|
|
233
239
|
for await (const item of streamAll(fn, params, {
|
|
234
240
|
maxPages,
|
|
235
|
-
onTruncated: (
|
|
241
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
242
|
+
`)
|
|
236
243
|
})) {
|
|
237
244
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
238
245
|
}
|
|
@@ -248,7 +255,8 @@ async function runProfileGet(client, flags, out) {
|
|
|
248
255
|
const fn = (p) => ns.profiles.listFollowers(resolvedId, p);
|
|
249
256
|
for await (const item of streamAll(fn, params, {
|
|
250
257
|
maxPages,
|
|
251
|
-
onTruncated: (
|
|
258
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
259
|
+
`)
|
|
252
260
|
})) {
|
|
253
261
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
254
262
|
}
|
|
@@ -295,7 +303,8 @@ async function runProfileConnections(client, flags, out) {
|
|
|
295
303
|
const fn = (p) => ns.profiles.listConnections(p);
|
|
296
304
|
for await (const item of streamAll(fn, params, {
|
|
297
305
|
maxPages,
|
|
298
|
-
onTruncated: (
|
|
306
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
307
|
+
`)
|
|
299
308
|
})) {
|
|
300
309
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
301
310
|
}
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
} from "./chunk-42VUUKQ3.js";
|
|
21
21
|
import {
|
|
22
22
|
streamAll
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-GXTZION6.js";
|
|
24
24
|
import {
|
|
25
25
|
createClient,
|
|
26
26
|
renderError,
|
|
@@ -242,7 +242,8 @@ async function runRecruiterSearchPeople(client, flags, out, readers = DEFAULT_FI
|
|
|
242
242
|
};
|
|
243
243
|
for await (const item of streamAll(fn, params, {
|
|
244
244
|
maxPages,
|
|
245
|
-
onTruncated: (
|
|
245
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
246
|
+
`)
|
|
246
247
|
})) {
|
|
247
248
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
248
249
|
}
|
|
@@ -287,7 +288,8 @@ async function runRecruiterListProjects(client, flags, out) {
|
|
|
287
288
|
const fn = (p) => ns.recruiter.listProjects(p);
|
|
288
289
|
for await (const item of streamAll(fn, params, {
|
|
289
290
|
maxPages,
|
|
290
|
-
onTruncated: (
|
|
291
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
292
|
+
`)
|
|
291
293
|
})) {
|
|
292
294
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
293
295
|
}
|
|
@@ -404,7 +406,8 @@ async function runRecruiterListJobs(client, flags, out) {
|
|
|
404
406
|
const fn = (p) => ns.recruiter.listJobs(p);
|
|
405
407
|
for await (const item of streamAll(fn, params, {
|
|
406
408
|
maxPages,
|
|
407
|
-
onTruncated: (
|
|
409
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
410
|
+
`)
|
|
408
411
|
})) {
|
|
409
412
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
410
413
|
}
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "./chunk-42VUUKQ3.js";
|
|
18
18
|
import {
|
|
19
19
|
streamAll
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-GXTZION6.js";
|
|
21
21
|
import {
|
|
22
22
|
createClient,
|
|
23
23
|
renderError,
|
|
@@ -123,7 +123,8 @@ async function runSalesNavSearchPeople(client, flags, out, readers = DEFAULT_FIL
|
|
|
123
123
|
};
|
|
124
124
|
for await (const item of streamAll(fn, params, {
|
|
125
125
|
maxPages,
|
|
126
|
-
onTruncated: (
|
|
126
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
127
|
+
`)
|
|
127
128
|
})) {
|
|
128
129
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
129
130
|
}
|
|
@@ -171,7 +172,8 @@ async function runSalesNavSearchCompanies(client, flags, out, readers = DEFAULT_
|
|
|
171
172
|
};
|
|
172
173
|
for await (const item of streamAll(fn, params, {
|
|
173
174
|
maxPages,
|
|
174
|
-
onTruncated: (
|
|
175
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
176
|
+
`)
|
|
175
177
|
})) {
|
|
176
178
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
177
179
|
}
|
|
@@ -7,7 +7,17 @@ import {
|
|
|
7
7
|
} from "./chunk-42VUUKQ3.js";
|
|
8
8
|
import {
|
|
9
9
|
streamAll
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GXTZION6.js";
|
|
11
|
+
import {
|
|
12
|
+
slimSearchCompanies,
|
|
13
|
+
slimSearchCompaniesItem,
|
|
14
|
+
slimSearchJobs,
|
|
15
|
+
slimSearchJobsItem,
|
|
16
|
+
slimSearchPeople,
|
|
17
|
+
slimSearchPeopleItem,
|
|
18
|
+
slimSearchPosts,
|
|
19
|
+
slimSearchPostsItem
|
|
20
|
+
} from "./chunk-J5KGG2EE.js";
|
|
11
21
|
import {
|
|
12
22
|
createClient,
|
|
13
23
|
renderError,
|
|
@@ -21,14 +31,24 @@ import {
|
|
|
21
31
|
|
|
22
32
|
// src/commands/search.ts
|
|
23
33
|
import { defineCommand } from "citty";
|
|
34
|
+
var HEADCOUNT_BUCKETS = {
|
|
35
|
+
"1-10": { min: 1, max: 10 },
|
|
36
|
+
"11-50": { min: 11, max: 50 },
|
|
37
|
+
"51-200": { min: 51, max: 200 },
|
|
38
|
+
"201-500": { min: 201, max: 500 },
|
|
39
|
+
"501-1000": { min: 501, max: 1e3 },
|
|
40
|
+
"1001-5000": { min: 1001, max: 5e3 },
|
|
41
|
+
"5001-10000": { min: 5001, max: 1e4 }
|
|
42
|
+
};
|
|
43
|
+
var PEOPLE_INVALID_FLAGS = ["seniority", "function", "employment-type", "sort-by"];
|
|
24
44
|
var FILTER_FLAGS = {
|
|
25
45
|
filters: {
|
|
26
46
|
type: "string",
|
|
27
|
-
description: "Filter body as a JSON object (
|
|
47
|
+
description: "Filter body as a JSON object (named flags win on conflict; server validates and strips unknown fields); '-' reads JSON from stdin."
|
|
28
48
|
},
|
|
29
49
|
"filters-file": {
|
|
30
50
|
type: "string",
|
|
31
|
-
description: "Path to a JSON file with the filter body."
|
|
51
|
+
description: "Path to a JSON file with the filter body (named flags win on conflict)."
|
|
32
52
|
}
|
|
33
53
|
};
|
|
34
54
|
function buildOutputStreams() {
|
|
@@ -60,7 +80,8 @@ function resolveOutputOpts(flags) {
|
|
|
60
80
|
return {
|
|
61
81
|
json: (flags.json ?? false) || !process.stdout.isTTY,
|
|
62
82
|
isTTY: process.stdout.isTTY ?? false,
|
|
63
|
-
fields: flags.fields
|
|
83
|
+
fields: flags.fields,
|
|
84
|
+
verbose: flags.verbose ?? false
|
|
64
85
|
};
|
|
65
86
|
}
|
|
66
87
|
function applyCommonSearchFlags(body, flags) {
|
|
@@ -69,6 +90,10 @@ function applyCommonSearchFlags(body, flags) {
|
|
|
69
90
|
if (flags.cursor) body["cursor"] = flags.cursor;
|
|
70
91
|
if (flags.limit) body["limit"] = parseInt(flags.limit, 10);
|
|
71
92
|
}
|
|
93
|
+
function mergeNested(body, key, patch) {
|
|
94
|
+
const existing = body[key] !== null && body[key] !== void 0 && typeof body[key] === "object" && !Array.isArray(body[key]) ? body[key] : {};
|
|
95
|
+
body[key] = { ...existing, ...patch };
|
|
96
|
+
}
|
|
72
97
|
var NAMED_FLAG_MAPPERS = {
|
|
73
98
|
people(body, flags) {
|
|
74
99
|
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
@@ -77,28 +102,71 @@ var NAMED_FLAG_MAPPERS = {
|
|
|
77
102
|
if (flags["past-company"]) body["past_company"] = splitCsv(flags["past-company"]);
|
|
78
103
|
if (flags.school) body["school"] = splitCsv(flags.school);
|
|
79
104
|
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"];
|
|
105
|
+
if (flags["connections-of"]) body["connections_of"] = splitCsv(flags["connections-of"]);
|
|
106
|
+
if (flags["followers-of"]) body["followers_of"] = splitCsv(flags["followers-of"]);
|
|
107
|
+
if (flags.title) {
|
|
108
|
+
const existingAK = body["advanced_keywords"] !== null && body["advanced_keywords"] !== void 0 && typeof body["advanced_keywords"] === "object" && !Array.isArray(body["advanced_keywords"]) ? body["advanced_keywords"] : {};
|
|
109
|
+
body["advanced_keywords"] = { ...existingAK, title: flags.title };
|
|
110
|
+
}
|
|
111
|
+
if (flags["profile-language"]) body["profile_language"] = splitCsv(flags["profile-language"]);
|
|
82
112
|
},
|
|
83
113
|
companies(body, flags) {
|
|
84
114
|
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
85
115
|
if (flags.location) body["location"] = splitCsv(flags.location);
|
|
86
116
|
if (flags["network-distance"]) body["network_distance"] = splitCsvNumbers(flags["network-distance"]);
|
|
117
|
+
if (flags["has-job-offers"]) body["has_job_offers"] = true;
|
|
118
|
+
if (flags.headcount) {
|
|
119
|
+
const buckets = splitCsv(flags.headcount);
|
|
120
|
+
const mapped = [];
|
|
121
|
+
for (const bucket of buckets) {
|
|
122
|
+
const range = HEADCOUNT_BUCKETS[bucket];
|
|
123
|
+
if (!range) return `--headcount: unrecognized bucket "${bucket}"`;
|
|
124
|
+
mapped.push(range);
|
|
125
|
+
}
|
|
126
|
+
body["headcount"] = mapped;
|
|
127
|
+
}
|
|
87
128
|
},
|
|
88
129
|
posts(body, flags) {
|
|
89
130
|
if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
|
|
90
|
-
if (flags["date-posted"]) body["date_posted"] = flags["date-posted"];
|
|
131
|
+
if (flags["date-posted"]) body["date_posted"] = flags["date-posted"].replace(/-/g, "_");
|
|
91
132
|
if (flags["content-type"]) body["content_type"] = flags["content-type"];
|
|
133
|
+
if (flags["posted-by-member"]) mergeNested(body, "posted_by", { member: splitCsv(flags["posted-by-member"]) });
|
|
134
|
+
if (flags["posted-by-company"]) mergeNested(body, "posted_by", { company: splitCsv(flags["posted-by-company"]) });
|
|
135
|
+
if (flags["posted-by-me"]) mergeNested(body, "posted_by", { me: true });
|
|
136
|
+
if (flags["mentioning-member"]) mergeNested(body, "mentioning", { member: splitCsv(flags["mentioning-member"]) });
|
|
137
|
+
if (flags["mentioning-company"]) mergeNested(body, "mentioning", { company: splitCsv(flags["mentioning-company"]) });
|
|
138
|
+
if (flags["author-industry"]) mergeNested(body, "author", { industry: splitCsv(flags["author-industry"]) });
|
|
139
|
+
if (flags["author-company"]) mergeNested(body, "author", { company: splitCsv(flags["author-company"]) });
|
|
140
|
+
if (flags["author-keywords"]) mergeNested(body, "author", { keywords: flags["author-keywords"] });
|
|
92
141
|
},
|
|
93
142
|
jobs(body, flags) {
|
|
94
|
-
if (flags.location) body["
|
|
143
|
+
if (flags.location) body["region"] = flags.location;
|
|
95
144
|
if (flags.industry) body["industry"] = splitCsv(flags.industry);
|
|
96
145
|
if (flags.seniority) body["seniority"] = splitCsv(flags.seniority);
|
|
97
146
|
if (flags.function) body["function"] = splitCsv(flags.function);
|
|
98
147
|
if (flags["job-type"]) body["job_type"] = splitCsv(flags["job-type"]);
|
|
99
148
|
if (flags.company) body["company"] = splitCsv(flags.company);
|
|
100
149
|
if (flags["sort-by"]) body["sort_by"] = flags["sort-by"];
|
|
150
|
+
if (flags["date-posted"] !== void 0 && flags["date-posted"] !== "") {
|
|
151
|
+
body["date_posted"] = Number(flags["date-posted"]);
|
|
152
|
+
}
|
|
101
153
|
if (flags.region) body["region"] = flags.region;
|
|
154
|
+
if (flags.title) body["role"] = splitCsv(flags.title);
|
|
155
|
+
if (flags.presence) body["presence"] = splitCsv(flags.presence);
|
|
156
|
+
if (flags.benefits) body["benefits"] = splitCsv(flags.benefits);
|
|
157
|
+
if (flags.commitments) body["commitments"] = splitCsv(flags.commitments);
|
|
158
|
+
if (flags["has-verifications"]) body["has_verifications"] = true;
|
|
159
|
+
if (flags["under-10-applicants"]) body["under_10_applicants"] = true;
|
|
160
|
+
if (flags["in-your-network"]) body["in_your_network"] = true;
|
|
161
|
+
if (flags["fair-chance-employer"]) body["fair_chance_employer"] = true;
|
|
162
|
+
if (flags["location-within-area"] !== void 0) {
|
|
163
|
+
const raw = flags["location-within-area"];
|
|
164
|
+
const n = Number(raw);
|
|
165
|
+
if (raw.trim() === "" || !Number.isFinite(n)) {
|
|
166
|
+
return `--location-within-area: must be a number (miles)`;
|
|
167
|
+
}
|
|
168
|
+
body["location_within_area"] = n;
|
|
169
|
+
}
|
|
102
170
|
}
|
|
103
171
|
};
|
|
104
172
|
async function buildSearchBody(kind, flags, readers) {
|
|
@@ -106,14 +174,25 @@ async function buildSearchBody(kind, flags, readers) {
|
|
|
106
174
|
if ("error" in assembled) return assembled;
|
|
107
175
|
const body = assembled.body;
|
|
108
176
|
applyCommonSearchFlags(body, flags);
|
|
109
|
-
NAMED_FLAG_MAPPERS[kind](body, flags);
|
|
177
|
+
const mapperError = NAMED_FLAG_MAPPERS[kind](body, flags);
|
|
178
|
+
if (mapperError) return { error: mapperError };
|
|
110
179
|
return { body };
|
|
111
180
|
}
|
|
112
181
|
async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READERS) {
|
|
113
182
|
rejectPreviewOnRead(flags.preview, out);
|
|
183
|
+
for (const f of PEOPLE_INVALID_FLAGS) {
|
|
184
|
+
if (flags[f]) {
|
|
185
|
+
out.stderr.write(
|
|
186
|
+
`error: --${f} is not valid for \`search people\` (classic LinkedIn search). Use \`search jobs\` or \`sales-nav search people\` for this filter.
|
|
187
|
+
`
|
|
188
|
+
);
|
|
189
|
+
process.exit(2);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
114
192
|
const accountId = requireAccount(flags.account, out);
|
|
115
193
|
const ns = client.account(accountId);
|
|
116
194
|
const outOpts = resolveOutputOpts(flags);
|
|
195
|
+
const verbose = flags.verbose ?? false;
|
|
117
196
|
const all = flags.all ?? false;
|
|
118
197
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
119
198
|
const assembled = await buildSearchBody("people", flags, readers);
|
|
@@ -128,13 +207,17 @@ async function runSearchPeople(client, flags, out, readers = DEFAULT_FILTER_READ
|
|
|
128
207
|
const fn = (p) => ns.search.people(p);
|
|
129
208
|
for await (const item of streamAll(fn, body, {
|
|
130
209
|
maxPages,
|
|
131
|
-
|
|
210
|
+
// Write JSON truncation sentinel to stdout as the last NDJSON line
|
|
211
|
+
onTruncated: (pagesFetched, hasMore) => out.stdout.write(
|
|
212
|
+
JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
|
|
213
|
+
)
|
|
132
214
|
})) {
|
|
133
|
-
|
|
215
|
+
const projected = verbose ? item : slimSearchPeopleItem(item);
|
|
216
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
134
217
|
}
|
|
135
218
|
} else {
|
|
136
219
|
const result = await ns.search.people(body);
|
|
137
|
-
renderSuccess(result, outOpts, out);
|
|
220
|
+
renderSuccess(result, { ...outOpts, slim: slimSearchPeople }, out);
|
|
138
221
|
}
|
|
139
222
|
} catch (err) {
|
|
140
223
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -152,6 +235,7 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
|
|
|
152
235
|
const accountId = requireAccount(flags.account, out);
|
|
153
236
|
const ns = client.account(accountId);
|
|
154
237
|
const outOpts = resolveOutputOpts(flags);
|
|
238
|
+
const verbose = flags.verbose ?? false;
|
|
155
239
|
const all = flags.all ?? false;
|
|
156
240
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
157
241
|
const assembled = await buildSearchBody("companies", flags, readers);
|
|
@@ -166,13 +250,16 @@ async function runSearchCompanies(client, flags, out, readers = DEFAULT_FILTER_R
|
|
|
166
250
|
const fn = (p) => ns.search.companies(p);
|
|
167
251
|
for await (const item of streamAll(fn, body, {
|
|
168
252
|
maxPages,
|
|
169
|
-
onTruncated: (
|
|
253
|
+
onTruncated: (pagesFetched, hasMore) => out.stdout.write(
|
|
254
|
+
JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
|
|
255
|
+
)
|
|
170
256
|
})) {
|
|
171
|
-
|
|
257
|
+
const projected = verbose ? item : slimSearchCompaniesItem(item);
|
|
258
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
172
259
|
}
|
|
173
260
|
} else {
|
|
174
261
|
const result = await ns.search.companies(body);
|
|
175
|
-
renderSuccess(result, outOpts, out);
|
|
262
|
+
renderSuccess(result, { ...outOpts, slim: slimSearchCompanies }, out);
|
|
176
263
|
}
|
|
177
264
|
} catch (err) {
|
|
178
265
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -190,6 +277,7 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
|
|
|
190
277
|
const accountId = requireAccount(flags.account, out);
|
|
191
278
|
const ns = client.account(accountId);
|
|
192
279
|
const outOpts = resolveOutputOpts(flags);
|
|
280
|
+
const verbose = flags.verbose ?? false;
|
|
193
281
|
const all = flags.all ?? false;
|
|
194
282
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
195
283
|
const assembled = await buildSearchBody("posts", flags, readers);
|
|
@@ -204,13 +292,16 @@ async function runSearchPosts(client, flags, out, readers = DEFAULT_FILTER_READE
|
|
|
204
292
|
const fn = (p) => ns.search.posts(p);
|
|
205
293
|
for await (const item of streamAll(fn, body, {
|
|
206
294
|
maxPages,
|
|
207
|
-
onTruncated: (
|
|
295
|
+
onTruncated: (pagesFetched, hasMore) => out.stdout.write(
|
|
296
|
+
JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
|
|
297
|
+
)
|
|
208
298
|
})) {
|
|
209
|
-
|
|
299
|
+
const projected = verbose ? item : slimSearchPostsItem(item);
|
|
300
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
210
301
|
}
|
|
211
302
|
} else {
|
|
212
303
|
const result = await ns.search.posts(body);
|
|
213
|
-
renderSuccess(result, outOpts, out);
|
|
304
|
+
renderSuccess(result, { ...outOpts, slim: slimSearchPosts }, out);
|
|
214
305
|
}
|
|
215
306
|
} catch (err) {
|
|
216
307
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -228,6 +319,7 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
|
|
|
228
319
|
const accountId = requireAccount(flags.account, out);
|
|
229
320
|
const ns = client.account(accountId);
|
|
230
321
|
const outOpts = resolveOutputOpts(flags);
|
|
322
|
+
const verbose = flags.verbose ?? false;
|
|
231
323
|
const all = flags.all ?? false;
|
|
232
324
|
const maxPages = flags["max-pages"] ? parseInt(flags["max-pages"], 10) : 100;
|
|
233
325
|
const assembled = await buildSearchBody("jobs", flags, readers);
|
|
@@ -242,13 +334,16 @@ async function runSearchJobs(client, flags, out, readers = DEFAULT_FILTER_READER
|
|
|
242
334
|
const fn = (p) => ns.search.jobs(p);
|
|
243
335
|
for await (const item of streamAll(fn, body, {
|
|
244
336
|
maxPages,
|
|
245
|
-
onTruncated: (
|
|
337
|
+
onTruncated: (pagesFetched, hasMore) => out.stdout.write(
|
|
338
|
+
JSON.stringify({ object: "stream_truncated", pages_fetched: pagesFetched, has_more: hasMore }) + "\n"
|
|
339
|
+
)
|
|
246
340
|
})) {
|
|
247
|
-
|
|
341
|
+
const projected = verbose ? item : slimSearchJobsItem(item);
|
|
342
|
+
out.stdout.write(JSON.stringify(projected) + "\n");
|
|
248
343
|
}
|
|
249
344
|
} else {
|
|
250
345
|
const result = await ns.search.jobs(body);
|
|
251
|
-
renderSuccess(result, outOpts, out);
|
|
346
|
+
renderSuccess(result, { ...outOpts, slim: slimSearchJobs }, out);
|
|
252
347
|
}
|
|
253
348
|
} catch (err) {
|
|
254
349
|
const { CurviateError } = await import("@curviate/sdk");
|
|
@@ -286,7 +381,7 @@ async function runSearchParameters(client, flags, out) {
|
|
|
286
381
|
}
|
|
287
382
|
}
|
|
288
383
|
var searchPeopleCommand = defineCommand({
|
|
289
|
-
meta: { name: "people", description: "Search
|
|
384
|
+
meta: { name: "people", description: "Search members with structured filters." },
|
|
290
385
|
args: {
|
|
291
386
|
...GLOBAL_FLAGS,
|
|
292
387
|
keywords: { type: "string", description: "Full-text keyword search." },
|
|
@@ -298,8 +393,11 @@ var searchPeopleCommand = defineCommand({
|
|
|
298
393
|
"past-company": { type: "string", description: "Past company ids (comma-separated)." },
|
|
299
394
|
school: { type: "string", description: "School ids (comma-separated)." },
|
|
300
395
|
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." },
|
|
301
|
-
"connections-of": { type: "string", description:
|
|
302
|
-
"followers-of": { type: "string", description:
|
|
396
|
+
"connections-of": { type: "string", description: 'member id(s), comma-separated (resolve: search parameters --type CONNECTIONS --keywords "<name>")' },
|
|
397
|
+
"followers-of": { type: "string", description: 'member id(s), comma-separated (resolve: search parameters --type PEOPLE --keywords "<name>")' },
|
|
398
|
+
// People-specific filter flags
|
|
399
|
+
title: { type: "string", description: "Job title keyword filter (maps to advanced_keywords.title)." },
|
|
400
|
+
"profile-language": { type: "string", description: "Profile language codes (comma-separated, e.g. en,de)." }
|
|
303
401
|
},
|
|
304
402
|
async run({ args }) {
|
|
305
403
|
const flags = args;
|
|
@@ -320,7 +418,7 @@ var searchPeopleCommand = defineCommand({
|
|
|
320
418
|
}
|
|
321
419
|
});
|
|
322
420
|
var searchCompaniesCommand = defineCommand({
|
|
323
|
-
meta: { name: "companies", description: "Search
|
|
421
|
+
meta: { name: "companies", description: "Search companies." },
|
|
324
422
|
args: {
|
|
325
423
|
...GLOBAL_FLAGS,
|
|
326
424
|
keywords: { type: "string", description: "Full-text keyword search." },
|
|
@@ -328,7 +426,12 @@ var searchCompaniesCommand = defineCommand({
|
|
|
328
426
|
...FILTER_FLAGS,
|
|
329
427
|
industry: { type: "string", description: "Industry ids (comma-separated)." },
|
|
330
428
|
location: { type: "string", description: "Location ids (comma-separated)." },
|
|
331
|
-
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." }
|
|
429
|
+
"network-distance": { type: "string", description: "Network distance, 1-3 (comma-separated)." },
|
|
430
|
+
"has-job-offers": { type: "boolean", description: "only companies with active job listings" },
|
|
431
|
+
headcount: {
|
|
432
|
+
type: "string",
|
|
433
|
+
description: "company size, comma-separated: 1-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10001+ (10001+ not yet supported)"
|
|
434
|
+
}
|
|
332
435
|
},
|
|
333
436
|
async run({ args }) {
|
|
334
437
|
const flags = args;
|
|
@@ -349,15 +452,23 @@ var searchCompaniesCommand = defineCommand({
|
|
|
349
452
|
}
|
|
350
453
|
});
|
|
351
454
|
var searchPostsCommand = defineCommand({
|
|
352
|
-
meta: { name: "posts", description: "Search
|
|
455
|
+
meta: { name: "posts", description: "Search posts." },
|
|
353
456
|
args: {
|
|
354
457
|
...GLOBAL_FLAGS,
|
|
355
458
|
keywords: { type: "string", description: "Full-text keyword search." },
|
|
356
459
|
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
357
460
|
...FILTER_FLAGS,
|
|
358
461
|
"sort-by": { type: "string", description: "Sort order (e.g. relevance, date)." },
|
|
359
|
-
"date-posted": { type: "string", description: "
|
|
360
|
-
"content-type": { type: "string", description: "
|
|
462
|
+
"date-posted": { type: "string", description: "time window: past_day, past_week, or past_month (hyphens also accepted: past-day, past-week, past-month)" },
|
|
463
|
+
"content-type": { type: "string", description: "content type: videos, images, live_videos, collaborative_articles, documents" },
|
|
464
|
+
"posted-by-member": { type: "string", description: "member id(s), comma-separated (resolve: search parameters --type PEOPLE); merges into posted_by" },
|
|
465
|
+
"posted-by-company": { type: "string", description: "company id(s), comma-separated (resolve: search parameters --type COMPANY); merges into posted_by" },
|
|
466
|
+
"posted-by-me": { type: "boolean", description: "only posts authored by you; merges into posted_by" },
|
|
467
|
+
"mentioning-member": { type: "string", description: "member id(s) mentioned in the post, comma-separated (resolve: search parameters --type PEOPLE); merges into mentioning" },
|
|
468
|
+
"mentioning-company": { type: "string", description: "company id(s) mentioned in the post, comma-separated (resolve: search parameters --type COMPANY); merges into mentioning" },
|
|
469
|
+
"author-industry": { type: "string", description: "author's industry id(s), comma-separated (resolve: search parameters --type INDUSTRY); merges into author" },
|
|
470
|
+
"author-company": { type: "string", description: "author's company id(s), comma-separated (resolve: search parameters --type COMPANY); merges into author" },
|
|
471
|
+
"author-keywords": { type: "string", description: "author keyword filter (free text); merges into author" }
|
|
361
472
|
},
|
|
362
473
|
async run({ args }) {
|
|
363
474
|
const flags = args;
|
|
@@ -378,20 +489,37 @@ var searchPostsCommand = defineCommand({
|
|
|
378
489
|
}
|
|
379
490
|
});
|
|
380
491
|
var searchJobsCommand = defineCommand({
|
|
381
|
-
meta: { name: "jobs", description: "Search
|
|
492
|
+
meta: { name: "jobs", description: "Search jobs." },
|
|
382
493
|
args: {
|
|
383
494
|
...GLOBAL_FLAGS,
|
|
384
495
|
keywords: { type: "string", description: "Full-text keyword search." },
|
|
385
496
|
url: { type: "string", description: "Pasted LinkedIn search URL (mutually exclusive with filters)." },
|
|
386
497
|
...FILTER_FLAGS,
|
|
387
|
-
location
|
|
498
|
+
// On jobs, --location maps to the geo region filter (not a location array — different API shape for jobs vs people)
|
|
499
|
+
location: { type: "string", description: "geo region id (single id; resolve via search parameters --type LOCATION); maps to region filter" },
|
|
388
500
|
industry: { type: "string", description: "Industry ids (comma-separated)." },
|
|
389
|
-
seniority: { type: "string", description: "
|
|
501
|
+
seniority: { type: "string", description: "seniority level, closed enum: executive|director|mid_senior|associate|entry|intern (comma-separated)" },
|
|
390
502
|
function: { type: "string", description: "Job function ids (comma-separated)." },
|
|
391
|
-
"job-type": { type: "string", description: "
|
|
503
|
+
"job-type": { type: "string", description: "job type, independent 7-value enum: full_time|part_time|contract|temporary|volunteer|internship|other (comma-separated)" },
|
|
392
504
|
company: { type: "string", description: "Company ids (comma-separated)." },
|
|
393
505
|
"sort-by": { type: "string", description: "Sort order (e.g. relevance, recent)." },
|
|
394
|
-
|
|
506
|
+
"date-posted": { type: "string", description: "maximum job age in days (a number \u2014 e.g. 7, 14, 30; not an enum string)" },
|
|
507
|
+
region: { type: "string", description: "alias for --location (same body field: region)" },
|
|
508
|
+
title: {
|
|
509
|
+
type: "string",
|
|
510
|
+
description: "job title id(s), comma-separated (resolve: search parameters --type JOB_TITLE); ID-based targeting \u2014 unlike search people --title, which is free-text"
|
|
511
|
+
},
|
|
512
|
+
presence: { type: "string", description: "work presence, comma-separated: on_site, hybrid, remote" },
|
|
513
|
+
benefits: { type: "string", description: "benefit ids, comma-separated" },
|
|
514
|
+
commitments: { type: "string", description: "commitment/employment types, comma-separated" },
|
|
515
|
+
"has-verifications": { type: "boolean", description: "only jobs with verified details" },
|
|
516
|
+
"under-10-applicants": { type: "boolean", description: "only jobs with fewer than 10 applicants" },
|
|
517
|
+
"in-your-network": { type: "boolean", description: "only jobs where you have a connection at the company" },
|
|
518
|
+
"fair-chance-employer": { type: "boolean", description: "only fair-chance employer jobs" },
|
|
519
|
+
"location-within-area": {
|
|
520
|
+
type: "string",
|
|
521
|
+
description: "radius in miles from --location (requires --location; numeric only)"
|
|
522
|
+
}
|
|
395
523
|
},
|
|
396
524
|
async run({ args }) {
|
|
397
525
|
const flags = args;
|
|
@@ -415,7 +543,11 @@ var searchParametersCommand = defineCommand({
|
|
|
415
543
|
meta: { name: "parameters", description: "Resolve human-readable terms to opaque filter IDs." },
|
|
416
544
|
args: {
|
|
417
545
|
...GLOBAL_FLAGS,
|
|
418
|
-
type: {
|
|
546
|
+
type: {
|
|
547
|
+
type: "string",
|
|
548
|
+
description: "Parameter type: LOCATION, PEOPLE, CONNECTIONS, COMPANY, SCHOOL, INDUSTRY, SERVICE, JOB_FUNCTION, JOB_TITLE, EMPLOYMENT_TYPE, SKILL.",
|
|
549
|
+
required: true
|
|
550
|
+
},
|
|
419
551
|
keywords: { type: "string", description: "Human term to resolve (not required for EMPLOYMENT_TYPE)." }
|
|
420
552
|
},
|
|
421
553
|
async run({ args }) {
|
|
@@ -437,7 +569,7 @@ var searchParametersCommand = defineCommand({
|
|
|
437
569
|
}
|
|
438
570
|
});
|
|
439
571
|
var searchCommand = defineCommand({
|
|
440
|
-
meta: { name: "search", description: "Search
|
|
572
|
+
meta: { name: "search", description: "Search people, companies, posts, and jobs." },
|
|
441
573
|
subCommands: {
|
|
442
574
|
people: searchPeopleCommand,
|
|
443
575
|
companies: searchCompaniesCommand,
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-R3VLWLVV.js";
|
|
5
5
|
import {
|
|
6
6
|
streamAll
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-GXTZION6.js";
|
|
8
8
|
import {
|
|
9
9
|
createClient,
|
|
10
10
|
renderError,
|
|
@@ -110,7 +110,8 @@ async function runWebhookList(client, flags, out) {
|
|
|
110
110
|
const fn = (p) => client.webhooks.list(p);
|
|
111
111
|
for await (const item of streamAll(fn, params, {
|
|
112
112
|
maxPages,
|
|
113
|
-
onTruncated: (
|
|
113
|
+
onTruncated: (n) => out.stderr.write(`Streaming truncated at ${n} page(s). Use --all --max-pages or --cursor for manual paging.
|
|
114
|
+
`)
|
|
114
115
|
})) {
|
|
115
116
|
out.stdout.write(JSON.stringify(item) + "\n");
|
|
116
117
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@curviate/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Official command-line interface for the Curviate API.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@curviate/sdk": "^0.
|
|
43
|
+
"@curviate/sdk": "^0.5.0",
|
|
44
44
|
"citty": "^0.1.6"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|