@hadoku/jobplatform 0.0.0-stage → 3.41.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +185 -2
  3. package/dist/App.d.ts +9 -0
  4. package/dist/App.d.ts.map +1 -0
  5. package/dist/api/applyQueue.d.ts +42 -0
  6. package/dist/api/applyQueue.d.ts.map +1 -0
  7. package/dist/api/auth.d.ts +15 -0
  8. package/dist/api/auth.d.ts.map +1 -0
  9. package/dist/api/companies.d.ts +26 -0
  10. package/dist/api/companies.d.ts.map +1 -0
  11. package/dist/api/jobs.d.ts +388 -0
  12. package/dist/api/jobs.d.ts.map +1 -0
  13. package/dist/api/packets.d.ts +28 -0
  14. package/dist/api/packets.d.ts.map +1 -0
  15. package/dist/api/profiles.d.ts +64 -0
  16. package/dist/api/profiles.d.ts.map +1 -0
  17. package/dist/api/resource.d.ts +43 -0
  18. package/dist/api/resource.d.ts.map +1 -0
  19. package/dist/api/useResource.d.ts +26 -0
  20. package/dist/api/useResource.d.ts.map +1 -0
  21. package/dist/components/ApplicationsList.d.ts +15 -0
  22. package/dist/components/ApplicationsList.d.ts.map +1 -0
  23. package/dist/components/CompaniesManager.d.ts +10 -0
  24. package/dist/components/CompaniesManager.d.ts.map +1 -0
  25. package/dist/components/FillExtensionInstall.d.ts +7 -0
  26. package/dist/components/FillExtensionInstall.d.ts.map +1 -0
  27. package/dist/components/JobCard.d.ts +17 -0
  28. package/dist/components/JobCard.d.ts.map +1 -0
  29. package/dist/components/JobDrawer.d.ts +17 -0
  30. package/dist/components/JobDrawer.d.ts.map +1 -0
  31. package/dist/components/JobsList.d.ts +18 -0
  32. package/dist/components/JobsList.d.ts.map +1 -0
  33. package/dist/components/PacketDetail.d.ts +16 -0
  34. package/dist/components/PacketDetail.d.ts.map +1 -0
  35. package/dist/components/PacketsList.d.ts +16 -0
  36. package/dist/components/PacketsList.d.ts.map +1 -0
  37. package/dist/components/ProfileEditorModal.d.ts +15 -0
  38. package/dist/components/ProfileEditorModal.d.ts.map +1 -0
  39. package/dist/components/ProfileSidebar.d.ts +24 -0
  40. package/dist/components/ProfileSidebar.d.ts.map +1 -0
  41. package/dist/components/UnansweredQuestions.d.ts +9 -0
  42. package/dist/components/UnansweredQuestions.d.ts.map +1 -0
  43. package/dist/components/VerificationCodes.d.ts +12 -0
  44. package/dist/components/VerificationCodes.d.ts.map +1 -0
  45. package/dist/components/VoteControl.d.ts +23 -0
  46. package/dist/components/VoteControl.d.ts.map +1 -0
  47. package/dist/components/matchOption.d.ts +16 -0
  48. package/dist/components/matchOption.d.ts.map +1 -0
  49. package/dist/entry.d.ts +24 -0
  50. package/dist/entry.d.ts.map +1 -0
  51. package/dist/fillExtension/bundle.d.ts +4 -0
  52. package/dist/fillExtension/bundle.d.ts.map +1 -0
  53. package/dist/fillExtension/zip.d.ts +12 -0
  54. package/dist/fillExtension/zip.d.ts.map +1 -0
  55. package/dist/index.js +5687 -0
  56. package/dist/style.css +1 -0
  57. package/package.json +35 -4
@@ -0,0 +1,388 @@
1
+ import { type Auth } from './auth';
2
+ import type { ProfileTrack, RoleLevel } from './profiles';
3
+ export interface ScoreBreakdown {
4
+ relevance: number;
5
+ level_match: number;
6
+ geo_fit: number;
7
+ comp_fit: number;
8
+ stack_fit: number;
9
+ domain_interest: number;
10
+ discipline_factor: number;
11
+ }
12
+ /** As classified at ingest. 'unknown' only for a blank title. */
13
+ export type RoleTrack = 'ic' | 'manager' | 'unknown';
14
+ /**
15
+ * V2 triage states. 'new' surfaces on read when the authed caller hasn't
16
+ * touched a job yet. Writeable values exclude 'new' (no row = 'new').
17
+ */
18
+ export type JobStateRead = 'new' | 'interested' | 'dismissed' | 'saved' | 'applied';
19
+ export type JobStateWrite = 'interested' | 'dismissed' | 'saved' | 'applied';
20
+ /** A curation vote on a posting: thumbs up or thumbs down. */
21
+ export type VoteValue = 1 | -1;
22
+ /** Mirrors FEEDBACK_REASONS in worker/src/schemas.ts — one axis per vote. */
23
+ export type FeedbackReason = 'pay' | 'location' | 'stack' | 'domain' | 'level' | 'company' | 'comp' | 'fit' | 'other';
24
+ export interface JobSummary {
25
+ id: string;
26
+ title: string;
27
+ company: string;
28
+ location: string;
29
+ workplace_type: string;
30
+ salary_min: number | null;
31
+ salary_max: number | null;
32
+ source_site: string;
33
+ url: string;
34
+ /**
35
+ * Where the form actually lives, when the posting names somewhere other than
36
+ * `url`. The card's Apply uses `application_url ?? url` — the same expression
37
+ * the drawer uses — so the two buttons can never open different pages.
38
+ */
39
+ application_url: string | null;
40
+ posted_date: string | null;
41
+ scraped_at: string;
42
+ ats: string | null;
43
+ slug: string | null;
44
+ /**
45
+ * Whether the form runner has an adapter for this posting. A PREDICTION read
46
+ * off the URL — nothing has been opened, so it must not be worded as if we
47
+ * had checked.
48
+ */
49
+ apply_tier: 'supported' | 'embedded' | 'unsupported' | 'unknown';
50
+ /** The runner has actually filled a form on this board. Evidence. */
51
+ apply_verified: boolean;
52
+ role_track: RoleTrack;
53
+ role_level: RoleLevel | null;
54
+ score: number;
55
+ score_breakdown: ScoreBreakdown;
56
+ state: JobStateRead | null;
57
+ /**
58
+ * The caller's application for this job, when one exists. Distinct from
59
+ * `state`: minting a packet lands a job_states row as 'saved', which says a
60
+ * kit was generated and nothing about whether the runner ever got the job.
61
+ */
62
+ application_status?: ApplicationStatus | null;
63
+ vote?: VoteValue | null;
64
+ vote_reasons?: string[];
65
+ }
66
+ export interface JobDetail extends JobSummary {
67
+ job_type: string;
68
+ description: string;
69
+ department: string | null;
70
+ scraper_used: string | null;
71
+ run_id: string | null;
72
+ state_updated_at: string | null;
73
+ }
74
+ export interface JobsListResponse {
75
+ jobs: JobSummary[];
76
+ total: number;
77
+ page: number;
78
+ limit: number;
79
+ has_more: boolean;
80
+ }
81
+ export interface ListJobsOptions {
82
+ profile_id?: string;
83
+ state?: JobStateRead;
84
+ hide_dismissed?: boolean;
85
+ /** Drop jobs already queued for the runner — they live under Applications. */
86
+ hide_queued?: boolean;
87
+ page?: number;
88
+ limit?: number;
89
+ sort?: JobSort;
90
+ min_score?: number;
91
+ /** View filter only — never a profile criterion. Jobs with no listed salary survive it. */
92
+ min_salary?: number;
93
+ workplace?: 'remote' | 'hybrid' | 'onsite';
94
+ }
95
+ export type JobSort = 'score' | 'date' | 'salary' | 'comp' | 'interest' | 'relevance';
96
+ export declare class JobsApiError extends Error {
97
+ status: number;
98
+ constructor(message: string, status: number);
99
+ }
100
+ export declare function listJobs(opts: ListJobsOptions, auth?: Auth): Promise<JobsListResponse>;
101
+ /**
102
+ * GET /jobs/preflight — how many corpus jobs match a keyword, track and/or
103
+ * level. Powers the editor's per-field probes ("312 matching jobs"). The track
104
+ * and level probes read the same classified columns the feed filters on, so the
105
+ * count is exactly the population the selection would produce. Read-only.
106
+ */
107
+ export declare function preflightCount(probe: {
108
+ keyword?: string;
109
+ track?: Exclude<ProfileTrack, 'either'>;
110
+ level?: RoleLevel;
111
+ }, auth?: Auth): Promise<number>;
112
+ export declare function getJob(id: string, profileId: string | undefined, auth?: Auth): Promise<JobDetail>;
113
+ /**
114
+ * PUT /jobs/:id/state — upsert the caller's triage state for one job.
115
+ * Returns the new state + server-stamped updated_at. Pass variant_slug when
116
+ * marking applied with a prepared packet, so the row remembers what was sent.
117
+ */
118
+ export declare function setJobState(id: string, state: JobStateWrite, auth?: Auth, variantSlug?: string): Promise<{
119
+ job_id: string;
120
+ state: JobStateRead;
121
+ updated_at: string;
122
+ }>;
123
+ /**
124
+ * PUT /jobs/:id/feedback — upsert the caller's vote on one posting: +1/-1
125
+ * plus multi-select axis-aligned reasons. Same session auth as the state calls.
126
+ */
127
+ export declare function setJobFeedback(id: string, vote: VoteValue, reasons: FeedbackReason[], auth?: Auth): Promise<{
128
+ job_id: string;
129
+ vote: VoteValue | null;
130
+ reasons: string[];
131
+ updated_at: string;
132
+ }>;
133
+ /**
134
+ * DELETE /jobs/:id/feedback — clear the caller's vote on one posting.
135
+ * Idempotent: safe to call when no vote exists.
136
+ */
137
+ export declare function clearJobFeedback(id: string, auth?: Auth): Promise<{
138
+ job_id: string;
139
+ vote: VoteValue | null;
140
+ reasons: string[];
141
+ updated_at: string;
142
+ }>;
143
+ /**
144
+ * POST /jobs/:id/resume — generate a tailored resume for one job. jobplatform
145
+ * proxies title/company/description to resume-api over a service binding.
146
+ */
147
+ export declare function generateResume(id: string, auth?: Auth, opts?: {
148
+ profile_type?: string;
149
+ tailor?: boolean;
150
+ }): Promise<{
151
+ resume_markdown: string;
152
+ blocks_used: string[];
153
+ cached: boolean;
154
+ }>;
155
+ /**
156
+ * POST /jobs/:id/cover-letter — generate a cover letter for one job (same
157
+ * binding path; uses the full resume rather than blocks).
158
+ */
159
+ export declare function generateCoverLetter(id: string, auth?: Auth, opts?: {
160
+ tone?: 'formal' | 'conversational';
161
+ }): Promise<{
162
+ cover_letter_markdown: string;
163
+ cached: boolean;
164
+ }>;
165
+ /**
166
+ * POST /jobs/:id/packet-link — mint a shareable packet link from an
167
+ * already-generated résumé + cover letter. jobplatform mints a resume-api
168
+ * variant with the pre-rendered markdown (instant) and returns the public
169
+ * hadoku.me/resume?v={slug} URL.
170
+ */
171
+ export declare function mintPacketLink(id: string, body: {
172
+ resume_markdown: string;
173
+ cover_letter_markdown?: string;
174
+ ttl_days?: number;
175
+ }, auth?: Auth): Promise<{
176
+ slug: string;
177
+ url: string;
178
+ }>;
179
+ export interface ScreeningAnswer {
180
+ q: string;
181
+ a: string;
182
+ }
183
+ /**
184
+ * The non-résumé half of an application kit — generated by resume-api and
185
+ * proxied through jobplatform. Everything a form/email needs besides the
186
+ * tailored résumé and cover letter.
187
+ */
188
+ export interface ApplicationExtras {
189
+ /** Cover letter, produced in the same call as the rest of the kit. */
190
+ cover_letter_markdown: string;
191
+ intro_email: string;
192
+ why_hook: string;
193
+ screening_answers: ScreeningAnswer[];
194
+ salary_line: string;
195
+ linkedin_note: string;
196
+ talking_points: string[];
197
+ /** Deterministic copy-paste block for the boring repeated form fields. */
198
+ standard_fields: string;
199
+ cached: boolean;
200
+ }
201
+ /**
202
+ * POST /jobs/:id/application-extras — generate the application extras from an
203
+ * already-generated tailored résumé. jobplatform proxies the résumé +
204
+ * title/company/description to resume-api over the service binding.
205
+ */
206
+ export declare function generateApplicationExtras(id: string, body: {
207
+ resume_markdown: string;
208
+ }, auth?: Auth): Promise<ApplicationExtras>;
209
+ /**
210
+ * One generated application packet: a job_states row carrying the resume-api
211
+ * variant slug minted for it, joined with the job. The slug keys both the
212
+ * public packet page (hadoku.me/resume?v={slug}) and its PDF.
213
+ */
214
+ export interface PacketSummary {
215
+ job_id: string;
216
+ title: string;
217
+ company: string;
218
+ location: string;
219
+ state: JobStateRead;
220
+ variant_slug: string;
221
+ updated_at: string;
222
+ }
223
+ /**
224
+ * GET /jobs/packets — every packet the caller has generated, newest first.
225
+ * Friend-gated: packets are per-user, so this 403s without auth.
226
+ */
227
+ export declare function listPackets(auth?: Auth): Promise<PacketSummary[]>;
228
+ /**
229
+ * DELETE /jobs/:id/state — clear the caller's state for one job (returns to
230
+ * implicit 'new'). Idempotent: safe to call when no state row exists.
231
+ */
232
+ export declare function clearJobState(id: string, auth?: Auth): Promise<{
233
+ job_id: string;
234
+ deleted: boolean;
235
+ }>;
236
+ export type ApplicationStatus = 'queued' | 'filled' | 'approved' | 'submitted' | 'needs_manual' | 'failed' | 'job_closed';
237
+ export interface ApplicationSummary {
238
+ id: string;
239
+ job_id: string;
240
+ variant_slug: string;
241
+ mode: 'review' | 'auto';
242
+ status: ApplicationStatus;
243
+ error: string | null;
244
+ evidence: Record<string, unknown> | null;
245
+ /**
246
+ * Digest of the fill this approval refers to, copied off `evidence` when the
247
+ * owner approves. The runner refuses to submit unless the application it
248
+ * re-fills matches, so a `filled` row without one cannot be approved.
249
+ */
250
+ approved_fingerprint: string | null;
251
+ created_at: string;
252
+ updated_at: string;
253
+ title: string;
254
+ company: string;
255
+ location: string;
256
+ /** The application form — where the hadoku Fill extension runs. */
257
+ form_url: string;
258
+ /**
259
+ * The stored fill, reconciled against the answers that exist now.
260
+ *
261
+ * `evidence` is a photograph taken when the runner filled the form and is
262
+ * never rewritten — it is what an approval refers to. These say what changed
263
+ * underneath it, so a day-old snapshot is not rendered as a live check.
264
+ * Optional because an older worker does not send them.
265
+ */
266
+ answered_since?: {
267
+ question: string;
268
+ answer: string;
269
+ }[];
270
+ still_unanswered?: string[];
271
+ /** Filled with something other than the stored standing answer. */
272
+ overridden?: {
273
+ question: string;
274
+ filled: string;
275
+ stored: string;
276
+ }[];
277
+ }
278
+ /**
279
+ * POST /jobs/:id/apply — queue one application for the PC-side form runner.
280
+ *
281
+ * This click IS the consent step: the runner only ever drains this queue and
282
+ * never picks jobs itself. Requires a minted packet, because the variant_slug
283
+ * is copied onto the row at queue time so a later re-tailor cannot silently
284
+ * change what an in-flight application sends.
285
+ */
286
+ export declare function queueApplication(id: string, mode?: 'review' | 'auto', auth?: Auth): Promise<ApplicationSummary>;
287
+ /** GET /applications — the caller's queue, newest first. Friend-gated. */
288
+ export declare function listApplications(status?: ApplicationStatus, auth?: Auth): Promise<ApplicationSummary[]>;
289
+ /**
290
+ * POST /applications/:id/approve — release a filled application for submission.
291
+ *
292
+ * Review mode's whole point: the runner pauses at `filled` with a screenshot,
293
+ * and nothing is sent until a human has looked at it and called this.
294
+ */
295
+ export declare function approveApplication(id: string, auth?: Auth): Promise<ApplicationSummary>;
296
+ export interface StandingAnswer {
297
+ /** Normalized question — what the runner matches on. */
298
+ question_key: string;
299
+ /** As the board worded it. */
300
+ question: string;
301
+ answer: string;
302
+ updated_at: string;
303
+ }
304
+ export interface UnansweredQuestion {
305
+ question_key: string;
306
+ question: string;
307
+ companies: string[];
308
+ applications: number;
309
+ /** How many applications this actually stopped. */
310
+ blocking: number;
311
+ /**
312
+ * The choices the form offers; empty when it is free text. An answer must
313
+ * match one of these verbatim to land, so these are the only answers that
314
+ * work — not suggestions.
315
+ */
316
+ options: string[];
317
+ /** Whether several of `options` may be picked; answered as "A | B". */
318
+ multi: boolean;
319
+ /**
320
+ * Already-answered questions that look like this one.
321
+ *
322
+ * Flags, never suggestions, and nothing here is applied by itself. The word
323
+ * DIFFERENCE is the payload: two work-authorization questions that differ
324
+ * only by "United States" vs "the country where the job is located" are
325
+ * identical except in the one respect that decides the answer. A pre-filled
326
+ * guess gets rubber-stamped; a stated difference gets read.
327
+ */
328
+ similar: SimilarAnswer[];
329
+ /**
330
+ * The personal fact this asks, when it is one that does not vary by employer
331
+ * — sponsorship, work authorization, the demographics, where you live. Null
332
+ * for anything answered on its own: another country, a legal agreement, a
333
+ * follow-up. Questions sharing a family are shown together and confirmed at
334
+ * once. See worker/src/questionFamily.ts.
335
+ */
336
+ family: string | null;
337
+ family_label: string | null;
338
+ /** Every distinct answer the owner has given in this family, newest first. */
339
+ family_answers: string[];
340
+ /**
341
+ * This board's option that says what the owner last said — or the answer as
342
+ * typed for free text. Null when no option clearly matches. A suggestion the
343
+ * owner confirms; nothing is saved without them.
344
+ */
345
+ suggested: string | null;
346
+ /**
347
+ * Set only when this question is back because the owner's saved answer did
348
+ * not fit this board's options and blocked the application.
349
+ */
350
+ saved_answer: string | null;
351
+ }
352
+ export interface SimilarAnswer {
353
+ question_key: string;
354
+ question: string;
355
+ answer: string;
356
+ shared_terms: string[];
357
+ /** Words this pending question adds that the answered one did not have. */
358
+ only_in_pending: string[];
359
+ /** Words only the answered one had — what that answer was scoped to. */
360
+ only_in_answered: string[];
361
+ /** One is negated and the other is not: copying would state the opposite. */
362
+ polarity_differs: boolean;
363
+ /** The runner's own matcher would transfer this unaided. */
364
+ runner_would_match: boolean;
365
+ }
366
+ export declare function listUnansweredQuestions(auth: Auth): Promise<UnansweredQuestion[]>;
367
+ export declare function listAnswers(auth: Auth): Promise<StandingAnswer[]>;
368
+ export declare function saveAnswer(question: string, answer: string, auth: Auth): Promise<StandingAnswer>;
369
+ export declare function forgetAnswer(questionKey: string, auth: Auth): Promise<StandingAnswer[]>;
370
+ /** One code an ATS emailed, as read from the hadoku.me mail feed. */
371
+ export interface VerificationCode {
372
+ id: string;
373
+ /** The employer the mail names, lowercased, or null. */
374
+ company: string | null;
375
+ subject: string;
376
+ received_at: string;
377
+ /** Null when the code could not be picked out; `text` then has the mail. */
378
+ code: string | null;
379
+ text: string | null;
380
+ }
381
+ /**
382
+ * GET /verification-codes — codes Greenhouse emailed, for the owner to type.
383
+ *
384
+ * Admin (the mailbox owner) only; anyone else gets 403, which callers treat as
385
+ * "nothing to show" rather than an error.
386
+ */
387
+ export declare function listVerificationCodes(auth?: Auth): Promise<VerificationCode[]>;
388
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../src/api/jobs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * The packet itself lives in resume-api, not here: the variant slug keys a
3
+ * minted résumé (+ cover letter) whose public page, JSON and PDF are all
4
+ * served from hadoku.me/resume. Absolute URLs because this dashboard is
5
+ * mounted under /jobplatform; the JSON endpoint is public (same-origin in
6
+ * production), so no auth headers.
7
+ */
8
+ /** Public packet page — what a recruiter sees when the link is shared. */
9
+ export declare function packetUrl(slug: string): string;
10
+ /** Server-rendered PDF of the same variant. */
11
+ export declare function packetPdfUrl(slug: string): string;
12
+ /**
13
+ * GET /resume/api/resume?v={slug} — raw JSON, not the jobplatform
14
+ * success-wrapper. An unknown or expired slug doesn't 404: resume-api falls
15
+ * back to the canonical résumé and omits `variant`, so its absence is the
16
+ * "this packet has expired" signal.
17
+ */
18
+ export interface PacketVariant {
19
+ /** Tailored résumé markdown (or the canonical résumé on fallback). */
20
+ content: string;
21
+ variant?: string;
22
+ label?: string | null;
23
+ cover_letter?: string | null;
24
+ company?: string | null;
25
+ job_title?: string | null;
26
+ }
27
+ export declare function getPacketVariant(slug: string): Promise<PacketVariant>;
28
+ //# sourceMappingURL=packets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"packets.d.ts","sourceRoot":"","sources":["../../src/api/packets.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,+CAA+C;AAC/C,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAI3E"}
@@ -0,0 +1,64 @@
1
+ export type RemotePref = 'remote' | 'hybrid' | 'onsite' | 'any';
2
+ /**
3
+ * The two orthogonal axes of "what kind of role". `track` answers "does it have
4
+ * direct reports?" and is applied server-side as a hard filter; `levels` are
5
+ * rungs on that track's ladder and are scored by distance.
6
+ *
7
+ * They replaced a single flat `role_types` list that mixed the two — where
8
+ * 'senior' and 'manager' were alternatives to each other, so the only
9
+ * expressible query was "any of these words is in the title".
10
+ */
11
+ export type ProfileTrack = 'ic' | 'manager' | 'either';
12
+ export declare const IC_LEVELS: readonly ["junior", "mid", "senior", "staff", "principal", "fellow"];
13
+ export declare const MANAGER_LEVELS: readonly ["manager", "senior_manager", "director", "vp", "cxo"];
14
+ export type IcLevel = (typeof IC_LEVELS)[number];
15
+ export type ManagerLevel = (typeof MANAGER_LEVELS)[number];
16
+ export type RoleLevel = IcLevel | ManagerLevel;
17
+ /** Ladder rungs are stored snake_case; these are what the user reads. */
18
+ export declare const LEVEL_LABELS: Record<RoleLevel, string>;
19
+ export interface JobProfile {
20
+ id: string;
21
+ name: string;
22
+ keywords: string[];
23
+ track: ProfileTrack;
24
+ levels: RoleLevel[];
25
+ remote_pref: RemotePref;
26
+ created_at: string;
27
+ /** True for the shared default profile. */
28
+ is_default: boolean;
29
+ }
30
+ export interface ProfileInput {
31
+ name: string;
32
+ keywords: string[];
33
+ track: ProfileTrack;
34
+ levels: RoleLevel[];
35
+ remote_pref: RemotePref;
36
+ }
37
+ /** A company that belongs to a profile's slice. */
38
+ export interface ProfileCompany {
39
+ id: string;
40
+ ats: string;
41
+ slug: string;
42
+ display_name: string;
43
+ added_at: string;
44
+ }
45
+ export declare class ProfilesApiError extends Error {
46
+ status: number;
47
+ constructor(message: string, status: number);
48
+ }
49
+ import { type Auth } from './auth';
50
+ export declare function listProfiles(auth?: Auth): Promise<JobProfile[]>;
51
+ export declare function createProfile(input: ProfileInput, auth?: Auth): Promise<JobProfile>;
52
+ export declare function updateProfile(id: string, input: Partial<ProfileInput>, auth?: Auth): Promise<JobProfile>;
53
+ export declare function deleteProfile(id: string, auth?: Auth): Promise<void>;
54
+ export declare function listProfileCompanies(profileId: string, auth?: Auth): Promise<ProfileCompany[]>;
55
+ export declare function addProfileCompany(profileId: string, company: {
56
+ ats: string;
57
+ slug: string;
58
+ display_name: string;
59
+ }, auth?: Auth): Promise<{
60
+ company: ProfileCompany;
61
+ search_triggered: boolean;
62
+ }>;
63
+ export declare function removeProfileCompany(profileId: string, companyId: string, auth?: Auth): Promise<void>;
64
+ //# sourceMappingURL=profiles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiles.d.ts","sourceRoot":"","sources":["../../src/api/profiles.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAA;AAE/D;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,IAAI,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEtD,eAAO,MAAM,SAAS,sEAAuE,CAAA;AAC7F,eAAO,MAAM,cAAc,iEAAkE,CAAA;AAE7F,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAA;AAChD,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAC1D,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,YAAY,CAAA;AAE9C,yEAAyE;AACzE,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAYlD,CAAA;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,2CAA2C;IAC3C,UAAU,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,KAAK,EAAE,YAAY,CAAA;IACnB,MAAM,EAAE,SAAS,EAAE,CAAA;IACnB,WAAW,EAAE,UAAU,CAAA;CACxB;AAED,mDAAmD;AACnD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;CACjB;AASD,qBAAa,gBAAiB,SAAQ,KAAK;IAGhC,MAAM,EAAE,MAAM;gBADrB,OAAO,EAAE,MAAM,EACR,MAAM,EAAE,MAAM;CAKxB;AAED,OAAO,EAAe,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAA;AAa/C,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAQrE;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC,CASzF;AAED,wBAAsB,aAAa,CACjC,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,EAC5B,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,UAAU,CAAC,CASrB;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAO1E;AAID,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,cAAc,EAAE,CAAC,CAQ3B;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,EAC5D,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC;IAAE,OAAO,EAAE,cAAc,CAAC;IAAC,gBAAgB,EAAE,OAAO,CAAA;CAAE,CAAC,CAQjE;AAED,wBAAsB,oBAAoB,CACxC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,IAAI,GACV,OAAO,CAAC,IAAI,CAAC,CAMf"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * A tiny stale-while-revalidate cache for the dashboard's GET endpoints.
3
+ *
4
+ * Every list in this app used to refetch from zero on mount, which is what
5
+ * makes the UI feel slow even when nothing changed: opening a job and pressing
6
+ * back, switching to Packets and returning, or paging the feed and paging back
7
+ * each cost a full round trip behind a "Loading…" line. The scored feed is the
8
+ * worst of them — it ranks the whole corpus per request — so a cache hit there
9
+ * is the difference between an instant view and several seconds of blank.
10
+ *
11
+ * Deliberately small: an in-memory Map that lives as long as the mounted MFE.
12
+ * Nothing is persisted, so a reload is still a cold read and there is no
13
+ * cross-session staleness to reason about.
14
+ */
15
+ /** Below this age a cached value is served without a background refresh. */
16
+ export declare const FRESH_MS = 30000;
17
+ export interface FetchOptions<T> {
18
+ /**
19
+ * Fires synchronously with a cached value when there is one, so a caller can
20
+ * paint immediately and then settle on the resolved promise.
21
+ */
22
+ onStale?: (cached: T, fresh: boolean) => void;
23
+ /**
24
+ * How long a value counts as fresh. The default suits a feed, where a stale
25
+ * read should still be re-checked promptly. Answers that only move when the
26
+ * corpus is re-scraped — the editor's "312 matching jobs" probes, each a
27
+ * full-table LIKE — pass something much longer.
28
+ */
29
+ maxAgeMs?: number;
30
+ }
31
+ /** Run `fetcher` for `key`, sharing one request between concurrent callers. */
32
+ export declare function fetchResource<T>(key: string, fetcher: () => Promise<T>, { onStale, maxAgeMs }?: FetchOptions<T>): Promise<T>;
33
+ /** Read a cached value without triggering a request. */
34
+ export declare function peekResource<T>(key: string): T | undefined;
35
+ /**
36
+ * Drop every key starting with `prefix`.
37
+ *
38
+ * Callers pass the prefix that brackets what a write actually invalidated —
39
+ * `'jobs:'` after a profile edit re-scores the feed, `'profiles:'` after a
40
+ * profile is saved or deleted.
41
+ */
42
+ export declare function invalidateResource(prefix: string): void;
43
+ //# sourceMappingURL=resource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../../src/api/resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AA8BH,4EAA4E;AAC5E,eAAO,MAAM,QAAQ,QAAS,CAAA;AAE9B,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAC7C;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,CAAC,EAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,EAAE,OAAO,EAAE,QAAmB,EAAE,GAAE,YAAY,CAAC,CAAC,CAAM,GACrD,OAAO,CAAC,CAAC,CAAC,CAgCZ;AAED,wDAAwD;AACxD,wBAAgB,YAAY,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAG1D;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAIvD"}
@@ -0,0 +1,26 @@
1
+ export interface ResourceState<T> {
2
+ data: T | undefined;
3
+ /** True only while there is nothing to show — a background refresh is not "loading". */
4
+ loading: boolean;
5
+ /** A refresh is in flight over data already on screen. Dim it, don't replace it. */
6
+ refreshing: boolean;
7
+ error: unknown;
8
+ reload: () => void;
9
+ }
10
+ /**
11
+ * Read a cached GET endpoint into a component.
12
+ *
13
+ * The point is what it does NOT do: it never drops back to an empty state to
14
+ * show a spinner. A cached value paints on the first render — before any
15
+ * effect runs — and a refresh swaps it out only once the new value has landed.
16
+ * That is what turns "Loading jobs…" on every filter change into a list that
17
+ * stays put and updates underneath.
18
+ *
19
+ * Pass `enabled: false` to hold off entirely (the feed uses it to avoid firing
20
+ * a request for a profile the sidebar is still resolving).
21
+ */
22
+ export declare function useResource<T>(key: string, fetcher: () => Promise<T>, { enabled, maxAgeMs }?: {
23
+ enabled?: boolean;
24
+ maxAgeMs?: number;
25
+ }): ResourceState<T>;
26
+ //# sourceMappingURL=useResource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useResource.d.ts","sourceRoot":"","sources":["../../src/api/useResource.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,GAAG,SAAS,CAAA;IACnB,wFAAwF;IACxF,OAAO,EAAE,OAAO,CAAA;IAChB,oFAAoF;IACpF,UAAU,EAAE,OAAO,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,EAAE,MAAM,IAAI,CAAA;CACnB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAC3B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EACzB,EAAE,OAAc,EAAE,QAAQ,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1E,aAAa,CAAC,CAAC,CAAC,CA4DlB"}
@@ -0,0 +1,15 @@
1
+ import type { Auth } from '../api/auth';
2
+ interface Props {
3
+ auth: Auth;
4
+ }
5
+ /**
6
+ * The Applications view: the approve-to-apply queue (issue #15).
7
+ *
8
+ * This is a workflow, not a reference list — the one action it offers is
9
+ * Approve, and only on `filled` rows. That is the review-mode contract: the
10
+ * runner fills the form and stops with a screenshot, and nothing reaches an
11
+ * employer until a human has looked at that screenshot and said yes here.
12
+ */
13
+ export declare function ApplicationsList({ auth }: Props): import("react/jsx-runtime").JSX.Element;
14
+ export {};
15
+ //# sourceMappingURL=ApplicationsList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ApplicationsList.d.ts","sourceRoot":"","sources":["../../src/components/ApplicationsList.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAMvC,UAAU,KAAK;IACb,IAAI,EAAE,IAAI,CAAA;CACX;AAmGD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,2CAoO/C"}
@@ -0,0 +1,10 @@
1
+ import type { Auth } from '../api/auth';
2
+ interface Props {
3
+ auth: Auth;
4
+ profileId: string | null;
5
+ /** Bumped by the parent when companies change, so the job feed can refetch. */
6
+ onCompaniesChanged?: () => void;
7
+ }
8
+ export declare function CompaniesManager({ auth, profileId, onCompaniesChanged }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=CompaniesManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CompaniesManager.d.ts","sourceRoot":"","sources":["../../src/components/CompaniesManager.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAIvC,UAAU,KAAK;IACb,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,+EAA+E;IAC/E,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;CAChC;AAqBD,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,kBAAkB,EAAE,EAAE,KAAK,2CAgP9E"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Where the owner gets the extension a send session runs on. Chrome only loads
3
+ * an unpacked extension from a folder on disk, so this is a download plus the
4
+ * four clicks that load it — on whichever machine they're sending from.
5
+ */
6
+ export declare function FillExtensionInstall(): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=FillExtensionInstall.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FillExtensionInstall.d.ts","sourceRoot":"","sources":["../../src/components/FillExtensionInstall.tsx"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,oBAAoB,4CAgCnC"}
@@ -0,0 +1,17 @@
1
+ import type { FeedbackReason, JobSummary, VoteValue } from '../api/jobs';
2
+ import type { ApplyStatus } from '../api/applyQueue';
3
+ import type { Auth } from '../api/auth';
4
+ interface Props {
5
+ job: JobSummary;
6
+ showScore: boolean;
7
+ auth: Auth;
8
+ vote: VoteValue | null;
9
+ voteReasons: FeedbackReason[];
10
+ onClick: () => void;
11
+ onVote: (jobId: string, vote: VoteValue | null, reasons: FeedbackReason[]) => void;
12
+ onApply: (jobId: string) => void;
13
+ applyStatus?: ApplyStatus;
14
+ }
15
+ export declare function JobCard({ job, showScore, auth, vote, voteReasons, onClick, onVote, onApply, applyStatus }: Props): import("react/jsx-runtime").JSX.Element;
16
+ export {};
17
+ //# sourceMappingURL=JobCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JobCard.d.ts","sourceRoot":"","sources":["../../src/components/JobCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACxE,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAGvC,UAAU,KAAK;IACb,GAAG,EAAE,UAAU,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;IAClB,IAAI,EAAE,IAAI,CAAA;IAEV,IAAI,EAAE,SAAS,GAAG,IAAI,CAAA;IACtB,WAAW,EAAE,cAAc,EAAE,CAAA;IAC7B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,IAAI,CAAA;IAGlF,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAEhC,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAsDD,wBAAgB,OAAO,CAAC,EACtB,GAAG,EACH,SAAS,EACT,IAAI,EACJ,IAAI,EACJ,WAAW,EACX,OAAO,EACP,MAAM,EACN,OAAO,EACP,WAAW,EACZ,EAAE,KAAK,2CAsHP"}