@prodigio-io/sdk 2.1.8 → 3.0.1
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/README.md +1 -7
- package/dist/index.d.mts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +33 -311
- package/dist/index.mjs +33 -311
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -46,12 +46,6 @@ Creates a new client. Get your API key from your Prodigio dashboard under **Sett
|
|
|
46
46
|
|
|
47
47
|
```typescript
|
|
48
48
|
const prodigio = new Prodigio('pk_live_...');
|
|
49
|
-
|
|
50
|
-
// Or with config object
|
|
51
|
-
const prodigio = new Prodigio({
|
|
52
|
-
apiKey: 'pk_live_...',
|
|
53
|
-
baseUrl: 'https://hire.prodigio.io', // optional
|
|
54
|
-
});
|
|
55
49
|
```
|
|
56
50
|
|
|
57
51
|
### `prodigio.jobs.list(params?)`
|
|
@@ -89,7 +83,7 @@ const attachment = await prodigio.upload.achievement(file);
|
|
|
89
83
|
|
|
90
84
|
### `prodigio.applications.submit(params)`
|
|
91
85
|
|
|
92
|
-
Submits a candidate application.
|
|
86
|
+
Submits a candidate application.
|
|
93
87
|
|
|
94
88
|
```typescript
|
|
95
89
|
const result = await prodigio.applications.submit({
|
package/dist/index.d.mts
CHANGED
|
@@ -90,6 +90,7 @@ interface BadgeProps {
|
|
|
90
90
|
rel: string;
|
|
91
91
|
text: string;
|
|
92
92
|
}
|
|
93
|
+
|
|
93
94
|
declare class ProdigioError extends Error {
|
|
94
95
|
readonly status: number;
|
|
95
96
|
readonly code?: string | undefined;
|
|
@@ -113,14 +114,17 @@ declare class Prodigio {
|
|
|
113
114
|
readonly applications: {
|
|
114
115
|
submit: (params: SubmitApplicationParams) => Promise<ApplicationResult>;
|
|
115
116
|
};
|
|
116
|
-
static
|
|
117
|
+
static init(config: ProdigioInitConfig): Promise<void>;
|
|
118
|
+
static destroy(): void;
|
|
117
119
|
static badge(poweredBy?: PoweredBy): BadgeProps;
|
|
118
120
|
static meta(): {
|
|
119
121
|
name: string;
|
|
120
122
|
content: string;
|
|
121
123
|
};
|
|
122
|
-
static
|
|
123
|
-
|
|
124
|
+
static readonly POWERED_BY: {
|
|
125
|
+
text: string;
|
|
126
|
+
url: string;
|
|
127
|
+
};
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
export { type Achievement, type Applicant, type ApplicationResult, type BadgeProps, type CVInfo, type Job, type ListJobsParams, type PoweredBy, Prodigio, type ProdigioConfig, ProdigioError, type ProdigioInitConfig, type SalaryRange, type SubmitApplicationParams, type UploadResult, Prodigio as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -90,6 +90,7 @@ interface BadgeProps {
|
|
|
90
90
|
rel: string;
|
|
91
91
|
text: string;
|
|
92
92
|
}
|
|
93
|
+
|
|
93
94
|
declare class ProdigioError extends Error {
|
|
94
95
|
readonly status: number;
|
|
95
96
|
readonly code?: string | undefined;
|
|
@@ -113,14 +114,17 @@ declare class Prodigio {
|
|
|
113
114
|
readonly applications: {
|
|
114
115
|
submit: (params: SubmitApplicationParams) => Promise<ApplicationResult>;
|
|
115
116
|
};
|
|
116
|
-
static
|
|
117
|
+
static init(config: ProdigioInitConfig): Promise<void>;
|
|
118
|
+
static destroy(): void;
|
|
117
119
|
static badge(poweredBy?: PoweredBy): BadgeProps;
|
|
118
120
|
static meta(): {
|
|
119
121
|
name: string;
|
|
120
122
|
content: string;
|
|
121
123
|
};
|
|
122
|
-
static
|
|
123
|
-
|
|
124
|
+
static readonly POWERED_BY: {
|
|
125
|
+
text: string;
|
|
126
|
+
url: string;
|
|
127
|
+
};
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
export { type Achievement, type Applicant, type ApplicationResult, type BadgeProps, type CVInfo, type Job, type ListJobsParams, type PoweredBy, Prodigio, type ProdigioConfig, ProdigioError, type ProdigioInitConfig, type SalaryRange, type SubmitApplicationParams, type UploadResult, Prodigio as default };
|
package/dist/index.js
CHANGED
|
@@ -26,17 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
});
|
|
27
27
|
module.exports = __toCommonJS(index_exports);
|
|
28
28
|
var DEFAULT_BASE_URL = "https://hire.prodigio.io";
|
|
29
|
-
var
|
|
30
|
-
var GRACE_PERIOD_MS = 5 * 60 * 1e3;
|
|
31
|
-
var PRODIGIO_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
32
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy85BNWaJVQQA/AFsz612
|
|
33
|
-
I+3K94s6P7r9zoSUvxDhn2J1INyuc27EIcMOHHPDxChrzJGv6bozGbpexYSIIgQd
|
|
34
|
-
ge9Ge9P/J+THQMdUmAbidfp/mR1i0vISaaBvKfFQfIGkuXpzbQB8eEV1s0jACMSd
|
|
35
|
-
qRSKeJEKSKPf3OkWVhaWi4KxT9H14W6lJMBrE0ZaGbAog2HmG69f5+5JjvxU6TWR
|
|
36
|
-
BojS5CYGvSvAIQGnsWm3Rz/HfZoPg1VRMRkGYCbLIVyV3XjLPo/VqBGuvjZSRTk+
|
|
37
|
-
HW72H1ZvBsBnNSEKkOSp5r43Du3x2KUQdYyV7p0iIwMRnMq2enBEEb2qrrj7huln
|
|
38
|
-
BQIDAQAB
|
|
39
|
-
-----END PUBLIC KEY-----`;
|
|
29
|
+
var CDN_URL = "https://cdn.prodigio.io/sdk/v2/sdk.js";
|
|
40
30
|
var ProdigioError = class extends Error {
|
|
41
31
|
constructor(message, status, code) {
|
|
42
32
|
super(message);
|
|
@@ -45,203 +35,30 @@ var ProdigioError = class extends Error {
|
|
|
45
35
|
this.name = "ProdigioError";
|
|
46
36
|
}
|
|
47
37
|
};
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const b64 = b64url.replace(/-/g, "+").replace(/_/g, "/").padEnd(
|
|
57
|
-
b64url.length + (4 - b64url.length % 4) % 4,
|
|
58
|
-
"="
|
|
59
|
-
);
|
|
60
|
-
const binary = atob(b64);
|
|
61
|
-
const buf = new Uint8Array(binary.length);
|
|
62
|
-
for (let i = 0; i < binary.length; i++) buf[i] = binary.charCodeAt(i);
|
|
63
|
-
return buf.buffer;
|
|
64
|
-
}
|
|
65
|
-
async function verifyBadgeToken(token) {
|
|
66
|
-
try {
|
|
67
|
-
if (typeof crypto === "undefined" || !crypto.subtle) return null;
|
|
68
|
-
const parts = token.split(".");
|
|
69
|
-
if (parts.length !== 3) return null;
|
|
70
|
-
const [headerB64, payloadB64, sigB64] = parts;
|
|
71
|
-
const signature = base64urlToArrayBuffer(sigB64);
|
|
72
|
-
const keyData = pemToArrayBuffer(PRODIGIO_PUBLIC_KEY_PEM);
|
|
73
|
-
const publicKey = await crypto.subtle.importKey(
|
|
74
|
-
"spki",
|
|
75
|
-
keyData,
|
|
76
|
-
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
|
|
77
|
-
false,
|
|
78
|
-
["verify"]
|
|
79
|
-
);
|
|
80
|
-
const valid = await crypto.subtle.verify(
|
|
81
|
-
"RSASSA-PKCS1-v1_5",
|
|
82
|
-
publicKey,
|
|
83
|
-
signature,
|
|
84
|
-
new TextEncoder().encode(`${headerB64}.${payloadB64}`)
|
|
85
|
-
);
|
|
86
|
-
if (!valid) return null;
|
|
87
|
-
const claims = JSON.parse(atob(payloadB64.replace(/-/g, "+").replace(/_/g, "/")));
|
|
88
|
-
if (claims.exp < Math.floor(Date.now() / 1e3)) return null;
|
|
89
|
-
return claims;
|
|
90
|
-
} catch {
|
|
91
|
-
return null;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
var BADGE_ELEMENT_ID = "prodigio-badge-widget";
|
|
95
|
-
function injectBadge(_position, badgeContainer) {
|
|
96
|
-
if (typeof document === "undefined") return;
|
|
97
|
-
if (document.getElementById(BADGE_ELEMENT_ID)) return;
|
|
98
|
-
const wrapper = document.createElement("div");
|
|
99
|
-
wrapper.id = BADGE_ELEMENT_ID;
|
|
100
|
-
wrapper.style.cssText = `
|
|
101
|
-
width: 100%; display: flex; justify-content: flex-end;
|
|
102
|
-
padding: 16px 20px; box-sizing: border-box;
|
|
103
|
-
`;
|
|
104
|
-
const el = document.createElement("a");
|
|
105
|
-
el.href = "https://prodigio.io";
|
|
106
|
-
el.target = "_blank";
|
|
107
|
-
el.rel = "noopener noreferrer";
|
|
108
|
-
el.setAttribute("data-prodigio-badge", "true");
|
|
109
|
-
el.setAttribute("aria-label", "Hiring powered by Prodigio");
|
|
110
|
-
el.style.cssText = `
|
|
111
|
-
display: inline-flex; align-items: center; gap: 7px;
|
|
112
|
-
padding: 7px 14px; background: #ffffff; border: 1px solid #e5e5e5;
|
|
113
|
-
border-radius: 24px; box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
114
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
115
|
-
font-size: 12px; font-weight: 400; color: #555555;
|
|
116
|
-
text-decoration: none; cursor: pointer; transition: box-shadow 0.15s ease;
|
|
117
|
-
white-space: nowrap;
|
|
118
|
-
`;
|
|
119
|
-
el.innerHTML = `
|
|
120
|
-
<span style="color:#555555;font-weight:400;">Hiring powered by</span>
|
|
121
|
-
<span style="display:inline-flex;align-items:center;gap:5px;">
|
|
122
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
123
|
-
<rect width="24" height="24" rx="6" fill="#3730A3"/>
|
|
124
|
-
<path d="M7 7h5.5a3.5 3.5 0 0 1 0 7H7V7z" fill="#fff"/>
|
|
125
|
-
<path d="M7 14h6a3 3 0 0 1 0 6H7v-6z" fill="#fff" opacity="0.6"/>
|
|
126
|
-
</svg>
|
|
127
|
-
<span style="color:#111111;font-weight:600;font-size:12px;">Prodigio</span>
|
|
128
|
-
</span>
|
|
129
|
-
`;
|
|
130
|
-
el.addEventListener("mouseenter", () => {
|
|
131
|
-
el.style.boxShadow = "0 4px 12px rgba(0,0,0,0.12)";
|
|
132
|
-
});
|
|
133
|
-
el.addEventListener("mouseleave", () => {
|
|
134
|
-
el.style.boxShadow = "0 2px 8px rgba(0,0,0,0.08)";
|
|
135
|
-
});
|
|
136
|
-
wrapper.appendChild(el);
|
|
137
|
-
findBadgeContainer(badgeContainer).appendChild(wrapper);
|
|
138
|
-
}
|
|
139
|
-
function removeBadge() {
|
|
140
|
-
var _a;
|
|
141
|
-
if (typeof document === "undefined") return;
|
|
142
|
-
(_a = document.getElementById(BADGE_ELEMENT_ID)) == null ? void 0 : _a.remove();
|
|
143
|
-
}
|
|
144
|
-
function cacheToken(apiKey, token, badgeExemptUntil, configVersion) {
|
|
145
|
-
try {
|
|
146
|
-
localStorage.setItem(`${BADGE_CACHE_KEY}_${apiKey}`, JSON.stringify({ token, badgeExemptUntil, configVersion, cachedAt: Date.now() }));
|
|
147
|
-
} catch {
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
function getCachedToken(apiKey) {
|
|
151
|
-
try {
|
|
152
|
-
const raw = localStorage.getItem(`${BADGE_CACHE_KEY}_${apiKey}`);
|
|
153
|
-
return raw ? JSON.parse(raw) : null;
|
|
154
|
-
} catch {
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
var _initialized = false;
|
|
159
|
-
var _routeWatcherInstalled = false;
|
|
160
|
-
var _rafHandle = null;
|
|
161
|
-
var _anchorObserver = null;
|
|
162
|
-
var _anchorTimeout = null;
|
|
163
|
-
var ANCHOR_WAIT_MS = 3e3;
|
|
164
|
-
function normalizePath(p) {
|
|
165
|
-
return p.replace(/\/$/, "").split("?")[0];
|
|
166
|
-
}
|
|
167
|
-
function pathMatches(current, careersPath) {
|
|
168
|
-
const c = normalizePath(current);
|
|
169
|
-
const target = normalizePath(careersPath);
|
|
170
|
-
return c === target || c.startsWith(target + "/");
|
|
171
|
-
}
|
|
172
|
-
function cancelPending() {
|
|
173
|
-
if (_rafHandle !== null) {
|
|
174
|
-
cancelAnimationFrame(_rafHandle);
|
|
175
|
-
_rafHandle = null;
|
|
176
|
-
}
|
|
177
|
-
if (_anchorObserver !== null) {
|
|
178
|
-
_anchorObserver.disconnect();
|
|
179
|
-
_anchorObserver = null;
|
|
180
|
-
}
|
|
181
|
-
if (_anchorTimeout !== null) {
|
|
182
|
-
clearTimeout(_anchorTimeout);
|
|
183
|
-
_anchorTimeout = null;
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
function waitForAnchor(badgeContainer, onFound) {
|
|
187
|
-
_anchorObserver = new MutationObserver(() => {
|
|
188
|
-
if (findBadgeAnchor(badgeContainer)) {
|
|
189
|
-
cancelPending();
|
|
190
|
-
onFound();
|
|
38
|
+
var _runtimePromise = null;
|
|
39
|
+
function ensureRuntime() {
|
|
40
|
+
if (_runtimePromise) return _runtimePromise;
|
|
41
|
+
_runtimePromise = new Promise((resolve, reject) => {
|
|
42
|
+
var _a;
|
|
43
|
+
if (typeof window === "undefined") {
|
|
44
|
+
resolve();
|
|
45
|
+
return;
|
|
191
46
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
cancelPending();
|
|
196
|
-
if (process.env.NODE_ENV !== "production") {
|
|
197
|
-
console.warn("[Prodigio] Badge anchor not found within 3s. Add <div data-prodigio-badge-anchor></div> to your page.");
|
|
47
|
+
if ((_a = window.Prodigio) == null ? void 0 : _a.__cdnLoaded) {
|
|
48
|
+
resolve();
|
|
49
|
+
return;
|
|
198
50
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (anchor) return anchor;
|
|
208
|
-
return null;
|
|
209
|
-
}
|
|
210
|
-
function findBadgeContainer(badgeContainer) {
|
|
211
|
-
const anchor = findBadgeAnchor(badgeContainer);
|
|
212
|
-
if (anchor) return anchor;
|
|
213
|
-
const selectors = ["main", '[role="main"]', "#root", "#__next", "#app"];
|
|
214
|
-
for (const sel of selectors) {
|
|
215
|
-
const el = document.querySelector(sel);
|
|
216
|
-
if (el) return el;
|
|
217
|
-
}
|
|
218
|
-
return document.body;
|
|
219
|
-
}
|
|
220
|
-
function installRouteWatcher() {
|
|
221
|
-
if (_routeWatcherInstalled || typeof window === "undefined") return;
|
|
222
|
-
_routeWatcherInstalled = true;
|
|
223
|
-
const orig = {
|
|
224
|
-
push: history.pushState.bind(history),
|
|
225
|
-
replace: history.replaceState.bind(history)
|
|
226
|
-
};
|
|
227
|
-
const dispatch = () => {
|
|
228
|
-
_routeChangeCallbacks.forEach((cb) => cb());
|
|
229
|
-
};
|
|
230
|
-
history.pushState = (...args) => {
|
|
231
|
-
orig.push(...args);
|
|
232
|
-
dispatch();
|
|
233
|
-
};
|
|
234
|
-
history.replaceState = (...args) => {
|
|
235
|
-
orig.replace(...args);
|
|
236
|
-
dispatch();
|
|
237
|
-
};
|
|
238
|
-
window.addEventListener("popstate", dispatch);
|
|
239
|
-
window.addEventListener("hashchange", dispatch);
|
|
51
|
+
const script = document.createElement("script");
|
|
52
|
+
script.src = CDN_URL;
|
|
53
|
+
script.async = true;
|
|
54
|
+
script.onload = () => resolve();
|
|
55
|
+
script.onerror = () => reject(new Error("[Prodigio] Failed to load SDK runtime from CDN"));
|
|
56
|
+
document.head.appendChild(script);
|
|
57
|
+
});
|
|
58
|
+
return _runtimePromise;
|
|
240
59
|
}
|
|
241
|
-
var _routeChangeCallbacks = [];
|
|
242
60
|
var _Prodigio = class _Prodigio {
|
|
243
61
|
constructor(config) {
|
|
244
|
-
// ── Jobs ──────────────────────────────────────────────────────────────────
|
|
245
62
|
this.jobs = {
|
|
246
63
|
list: (params) => {
|
|
247
64
|
const p = {};
|
|
@@ -251,7 +68,6 @@ var _Prodigio = class _Prodigio {
|
|
|
251
68
|
},
|
|
252
69
|
get: (jobId) => this.get(`/api/jobs/${jobId}`)
|
|
253
70
|
};
|
|
254
|
-
// ── Uploads ───────────────────────────────────────────────────────────────
|
|
255
71
|
this.upload = {
|
|
256
72
|
cv: (file, fileName) => {
|
|
257
73
|
const form = new FormData();
|
|
@@ -264,7 +80,6 @@ var _Prodigio = class _Prodigio {
|
|
|
264
80
|
return this.postForm("/api/upload/achievement", form);
|
|
265
81
|
}
|
|
266
82
|
};
|
|
267
|
-
// ── Applications ──────────────────────────────────────────────────────────
|
|
268
83
|
this.applications = {
|
|
269
84
|
submit: (params) => this.post("/api/applications", params)
|
|
270
85
|
};
|
|
@@ -315,120 +130,27 @@ var _Prodigio = class _Prodigio {
|
|
|
315
130
|
}
|
|
316
131
|
return res.json();
|
|
317
132
|
}
|
|
133
|
+
// ── Static methods — delegate to CDN runtime ──────────────────────────────
|
|
134
|
+
static async init(config) {
|
|
135
|
+
await ensureRuntime();
|
|
136
|
+
return window.Prodigio.init(config);
|
|
137
|
+
}
|
|
138
|
+
static destroy() {
|
|
139
|
+
var _a;
|
|
140
|
+
(_a = window.Prodigio) == null ? void 0 : _a.destroy();
|
|
141
|
+
}
|
|
318
142
|
static badge(poweredBy) {
|
|
143
|
+
var _a;
|
|
144
|
+
if ((_a = window.Prodigio) == null ? void 0 : _a.badge) {
|
|
145
|
+
return window.Prodigio.badge(poweredBy);
|
|
146
|
+
}
|
|
319
147
|
const pb = poweredBy != null ? poweredBy : _Prodigio.POWERED_BY;
|
|
320
148
|
return { href: pb.url, "data-prodigio-badge": "true", target: "_blank", rel: "noopener noreferrer", text: pb.text };
|
|
321
149
|
}
|
|
322
150
|
static meta() {
|
|
323
151
|
return { name: "prodigio-badge", content: "true" };
|
|
324
152
|
}
|
|
325
|
-
// ── init() ────────────────────────────────────────────────────────────────
|
|
326
|
-
static async init(config) {
|
|
327
|
-
var _a;
|
|
328
|
-
if (typeof window === "undefined") return;
|
|
329
|
-
if (_initialized) return;
|
|
330
|
-
_initialized = true;
|
|
331
|
-
if (process.env.NODE_ENV !== "production" && !document.querySelector('meta[name="prodigio-badge"]')) {
|
|
332
|
-
console.warn('[Prodigio] Missing <meta name="prodigio-badge" content="true"> in your page <head>. This is required for compliance detection. See docs.prodigio.io');
|
|
333
|
-
}
|
|
334
|
-
const { key, badgeToken, baseUrl = DEFAULT_BASE_URL, badge: badgeConfig, badgeContainer } = config;
|
|
335
|
-
const position = (_a = badgeConfig == null ? void 0 : badgeConfig.position) != null ? _a : "bottom-right";
|
|
336
|
-
const cached = getCachedToken(key);
|
|
337
|
-
const [initClaims, cachedClaims] = await Promise.all([
|
|
338
|
-
badgeToken ? verifyBadgeToken(badgeToken) : Promise.resolve(null),
|
|
339
|
-
cached ? verifyBadgeToken(cached.token) : Promise.resolve(null)
|
|
340
|
-
]);
|
|
341
|
-
let bestToken = null;
|
|
342
|
-
if (initClaims && cachedClaims) {
|
|
343
|
-
bestToken = new Date(initClaims.badgeExemptUntil) >= new Date(cachedClaims.badgeExemptUntil) ? initClaims : cachedClaims;
|
|
344
|
-
} else {
|
|
345
|
-
bestToken = initClaims != null ? initClaims : cachedClaims;
|
|
346
|
-
}
|
|
347
|
-
const hostname = window.location.hostname;
|
|
348
|
-
const domainAllowed = bestToken ? bestToken.allowedDomains.length === 0 || bestToken.allowedDomains.includes(hostname) : true;
|
|
349
|
-
const isExempt = bestToken !== null && !bestToken.badgeRequired && domainAllowed;
|
|
350
|
-
let configState = { status: "loading" };
|
|
351
|
-
function reconcile() {
|
|
352
|
-
cancelPending();
|
|
353
|
-
if (isExempt) {
|
|
354
|
-
removeBadge();
|
|
355
|
-
return;
|
|
356
|
-
}
|
|
357
|
-
if (configState.status === "loading" || configState.status === "error") {
|
|
358
|
-
return;
|
|
359
|
-
}
|
|
360
|
-
const { careersPath } = configState;
|
|
361
|
-
if (!careersPath) {
|
|
362
|
-
if (bestToken && cached) {
|
|
363
|
-
const cacheAge = Date.now() - cached.cachedAt;
|
|
364
|
-
if (cacheAge < GRACE_PERIOD_MS) {
|
|
365
|
-
removeBadge();
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) {
|
|
370
|
-
injectBadge(position, badgeContainer);
|
|
371
|
-
}
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const routeMatches = pathMatches(window.location.pathname, careersPath);
|
|
375
|
-
if (!routeMatches) {
|
|
376
|
-
removeBadge();
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
queueMicrotask(() => {
|
|
380
|
-
_rafHandle = requestAnimationFrame(() => {
|
|
381
|
-
_rafHandle = null;
|
|
382
|
-
const anchor = findBadgeAnchor(badgeContainer);
|
|
383
|
-
if (anchor) {
|
|
384
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) injectBadge(position, badgeContainer);
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
waitForAnchor(badgeContainer, () => {
|
|
388
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) injectBadge(position, badgeContainer);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
}
|
|
393
|
-
reconcile();
|
|
394
|
-
installRouteWatcher();
|
|
395
|
-
_routeChangeCallbacks.push(reconcile);
|
|
396
|
-
setTimeout(async () => {
|
|
397
|
-
var _a2, _b, _c;
|
|
398
|
-
try {
|
|
399
|
-
const res = await fetch(`${baseUrl}/api/sdk/config?key=${encodeURIComponent(key)}`);
|
|
400
|
-
if (!res.ok) return;
|
|
401
|
-
const data = await res.json();
|
|
402
|
-
configState = {
|
|
403
|
-
status: "loaded",
|
|
404
|
-
careersPath: (_a2 = data.careersPath) != null ? _a2 : null,
|
|
405
|
-
badgeRequired: data.badgeRequired
|
|
406
|
-
};
|
|
407
|
-
if (data.badgeRequired) {
|
|
408
|
-
reconcile();
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
if (data.badgeToken) {
|
|
412
|
-
const refreshedClaims = await verifyBadgeToken(data.badgeToken);
|
|
413
|
-
if (refreshedClaims && !refreshedClaims.badgeRequired) {
|
|
414
|
-
cacheToken(key, data.badgeToken, (_b = data.badgeExemptUntil) != null ? _b : "", (_c = data.configVersion) != null ? _c : 1);
|
|
415
|
-
removeBadge();
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
reconcile();
|
|
420
|
-
} catch {
|
|
421
|
-
configState = { status: "error" };
|
|
422
|
-
}
|
|
423
|
-
}, 0);
|
|
424
|
-
}
|
|
425
|
-
static destroy() {
|
|
426
|
-
cancelPending();
|
|
427
|
-
removeBadge();
|
|
428
|
-
_initialized = false;
|
|
429
|
-
}
|
|
430
153
|
};
|
|
431
|
-
// ── Badge static helpers ──────────────────────────────────────────────────
|
|
432
154
|
_Prodigio.POWERED_BY = {
|
|
433
155
|
text: "Hiring powered by Prodigio",
|
|
434
156
|
url: "https://prodigio.io"
|
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
var DEFAULT_BASE_URL = "https://hire.prodigio.io";
|
|
3
|
-
var
|
|
4
|
-
var GRACE_PERIOD_MS = 5 * 60 * 1e3;
|
|
5
|
-
var PRODIGIO_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
6
|
-
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy85BNWaJVQQA/AFsz612
|
|
7
|
-
I+3K94s6P7r9zoSUvxDhn2J1INyuc27EIcMOHHPDxChrzJGv6bozGbpexYSIIgQd
|
|
8
|
-
ge9Ge9P/J+THQMdUmAbidfp/mR1i0vISaaBvKfFQfIGkuXpzbQB8eEV1s0jACMSd
|
|
9
|
-
qRSKeJEKSKPf3OkWVhaWi4KxT9H14W6lJMBrE0ZaGbAog2HmG69f5+5JjvxU6TWR
|
|
10
|
-
BojS5CYGvSvAIQGnsWm3Rz/HfZoPg1VRMRkGYCbLIVyV3XjLPo/VqBGuvjZSRTk+
|
|
11
|
-
HW72H1ZvBsBnNSEKkOSp5r43Du3x2KUQdYyV7p0iIwMRnMq2enBEEb2qrrj7huln
|
|
12
|
-
BQIDAQAB
|
|
13
|
-
-----END PUBLIC KEY-----`;
|
|
3
|
+
var CDN_URL = "https://cdn.prodigio.io/sdk/v2/sdk.js";
|
|
14
4
|
var ProdigioError = class extends Error {
|
|
15
5
|
constructor(message, status, code) {
|
|
16
6
|
super(message);
|
|
@@ -19,203 +9,30 @@ var ProdigioError = class extends Error {
|
|
|
19
9
|
this.name = "ProdigioError";
|
|
20
10
|
}
|
|
21
11
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const b64 = b64url.replace(/-/g, "+").replace(/_/g, "/").padEnd(
|
|
31
|
-
b64url.length + (4 - b64url.length % 4) % 4,
|
|
32
|
-
"="
|
|
33
|
-
);
|
|
34
|
-
const binary = atob(b64);
|
|
35
|
-
const buf = new Uint8Array(binary.length);
|
|
36
|
-
for (let i = 0; i < binary.length; i++) buf[i] = binary.charCodeAt(i);
|
|
37
|
-
return buf.buffer;
|
|
38
|
-
}
|
|
39
|
-
async function verifyBadgeToken(token) {
|
|
40
|
-
try {
|
|
41
|
-
if (typeof crypto === "undefined" || !crypto.subtle) return null;
|
|
42
|
-
const parts = token.split(".");
|
|
43
|
-
if (parts.length !== 3) return null;
|
|
44
|
-
const [headerB64, payloadB64, sigB64] = parts;
|
|
45
|
-
const signature = base64urlToArrayBuffer(sigB64);
|
|
46
|
-
const keyData = pemToArrayBuffer(PRODIGIO_PUBLIC_KEY_PEM);
|
|
47
|
-
const publicKey = await crypto.subtle.importKey(
|
|
48
|
-
"spki",
|
|
49
|
-
keyData,
|
|
50
|
-
{ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
|
|
51
|
-
false,
|
|
52
|
-
["verify"]
|
|
53
|
-
);
|
|
54
|
-
const valid = await crypto.subtle.verify(
|
|
55
|
-
"RSASSA-PKCS1-v1_5",
|
|
56
|
-
publicKey,
|
|
57
|
-
signature,
|
|
58
|
-
new TextEncoder().encode(`${headerB64}.${payloadB64}`)
|
|
59
|
-
);
|
|
60
|
-
if (!valid) return null;
|
|
61
|
-
const claims = JSON.parse(atob(payloadB64.replace(/-/g, "+").replace(/_/g, "/")));
|
|
62
|
-
if (claims.exp < Math.floor(Date.now() / 1e3)) return null;
|
|
63
|
-
return claims;
|
|
64
|
-
} catch {
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
var BADGE_ELEMENT_ID = "prodigio-badge-widget";
|
|
69
|
-
function injectBadge(_position, badgeContainer) {
|
|
70
|
-
if (typeof document === "undefined") return;
|
|
71
|
-
if (document.getElementById(BADGE_ELEMENT_ID)) return;
|
|
72
|
-
const wrapper = document.createElement("div");
|
|
73
|
-
wrapper.id = BADGE_ELEMENT_ID;
|
|
74
|
-
wrapper.style.cssText = `
|
|
75
|
-
width: 100%; display: flex; justify-content: flex-end;
|
|
76
|
-
padding: 16px 20px; box-sizing: border-box;
|
|
77
|
-
`;
|
|
78
|
-
const el = document.createElement("a");
|
|
79
|
-
el.href = "https://prodigio.io";
|
|
80
|
-
el.target = "_blank";
|
|
81
|
-
el.rel = "noopener noreferrer";
|
|
82
|
-
el.setAttribute("data-prodigio-badge", "true");
|
|
83
|
-
el.setAttribute("aria-label", "Hiring powered by Prodigio");
|
|
84
|
-
el.style.cssText = `
|
|
85
|
-
display: inline-flex; align-items: center; gap: 7px;
|
|
86
|
-
padding: 7px 14px; background: #ffffff; border: 1px solid #e5e5e5;
|
|
87
|
-
border-radius: 24px; box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
88
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
89
|
-
font-size: 12px; font-weight: 400; color: #555555;
|
|
90
|
-
text-decoration: none; cursor: pointer; transition: box-shadow 0.15s ease;
|
|
91
|
-
white-space: nowrap;
|
|
92
|
-
`;
|
|
93
|
-
el.innerHTML = `
|
|
94
|
-
<span style="color:#555555;font-weight:400;">Hiring powered by</span>
|
|
95
|
-
<span style="display:inline-flex;align-items:center;gap:5px;">
|
|
96
|
-
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
97
|
-
<rect width="24" height="24" rx="6" fill="#3730A3"/>
|
|
98
|
-
<path d="M7 7h5.5a3.5 3.5 0 0 1 0 7H7V7z" fill="#fff"/>
|
|
99
|
-
<path d="M7 14h6a3 3 0 0 1 0 6H7v-6z" fill="#fff" opacity="0.6"/>
|
|
100
|
-
</svg>
|
|
101
|
-
<span style="color:#111111;font-weight:600;font-size:12px;">Prodigio</span>
|
|
102
|
-
</span>
|
|
103
|
-
`;
|
|
104
|
-
el.addEventListener("mouseenter", () => {
|
|
105
|
-
el.style.boxShadow = "0 4px 12px rgba(0,0,0,0.12)";
|
|
106
|
-
});
|
|
107
|
-
el.addEventListener("mouseleave", () => {
|
|
108
|
-
el.style.boxShadow = "0 2px 8px rgba(0,0,0,0.08)";
|
|
109
|
-
});
|
|
110
|
-
wrapper.appendChild(el);
|
|
111
|
-
findBadgeContainer(badgeContainer).appendChild(wrapper);
|
|
112
|
-
}
|
|
113
|
-
function removeBadge() {
|
|
114
|
-
var _a;
|
|
115
|
-
if (typeof document === "undefined") return;
|
|
116
|
-
(_a = document.getElementById(BADGE_ELEMENT_ID)) == null ? void 0 : _a.remove();
|
|
117
|
-
}
|
|
118
|
-
function cacheToken(apiKey, token, badgeExemptUntil, configVersion) {
|
|
119
|
-
try {
|
|
120
|
-
localStorage.setItem(`${BADGE_CACHE_KEY}_${apiKey}`, JSON.stringify({ token, badgeExemptUntil, configVersion, cachedAt: Date.now() }));
|
|
121
|
-
} catch {
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
function getCachedToken(apiKey) {
|
|
125
|
-
try {
|
|
126
|
-
const raw = localStorage.getItem(`${BADGE_CACHE_KEY}_${apiKey}`);
|
|
127
|
-
return raw ? JSON.parse(raw) : null;
|
|
128
|
-
} catch {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
var _initialized = false;
|
|
133
|
-
var _routeWatcherInstalled = false;
|
|
134
|
-
var _rafHandle = null;
|
|
135
|
-
var _anchorObserver = null;
|
|
136
|
-
var _anchorTimeout = null;
|
|
137
|
-
var ANCHOR_WAIT_MS = 3e3;
|
|
138
|
-
function normalizePath(p) {
|
|
139
|
-
return p.replace(/\/$/, "").split("?")[0];
|
|
140
|
-
}
|
|
141
|
-
function pathMatches(current, careersPath) {
|
|
142
|
-
const c = normalizePath(current);
|
|
143
|
-
const target = normalizePath(careersPath);
|
|
144
|
-
return c === target || c.startsWith(target + "/");
|
|
145
|
-
}
|
|
146
|
-
function cancelPending() {
|
|
147
|
-
if (_rafHandle !== null) {
|
|
148
|
-
cancelAnimationFrame(_rafHandle);
|
|
149
|
-
_rafHandle = null;
|
|
150
|
-
}
|
|
151
|
-
if (_anchorObserver !== null) {
|
|
152
|
-
_anchorObserver.disconnect();
|
|
153
|
-
_anchorObserver = null;
|
|
154
|
-
}
|
|
155
|
-
if (_anchorTimeout !== null) {
|
|
156
|
-
clearTimeout(_anchorTimeout);
|
|
157
|
-
_anchorTimeout = null;
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
function waitForAnchor(badgeContainer, onFound) {
|
|
161
|
-
_anchorObserver = new MutationObserver(() => {
|
|
162
|
-
if (findBadgeAnchor(badgeContainer)) {
|
|
163
|
-
cancelPending();
|
|
164
|
-
onFound();
|
|
12
|
+
var _runtimePromise = null;
|
|
13
|
+
function ensureRuntime() {
|
|
14
|
+
if (_runtimePromise) return _runtimePromise;
|
|
15
|
+
_runtimePromise = new Promise((resolve, reject) => {
|
|
16
|
+
var _a;
|
|
17
|
+
if (typeof window === "undefined") {
|
|
18
|
+
resolve();
|
|
19
|
+
return;
|
|
165
20
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
cancelPending();
|
|
170
|
-
if (process.env.NODE_ENV !== "production") {
|
|
171
|
-
console.warn("[Prodigio] Badge anchor not found within 3s. Add <div data-prodigio-badge-anchor></div> to your page.");
|
|
21
|
+
if ((_a = window.Prodigio) == null ? void 0 : _a.__cdnLoaded) {
|
|
22
|
+
resolve();
|
|
23
|
+
return;
|
|
172
24
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (anchor) return anchor;
|
|
182
|
-
return null;
|
|
183
|
-
}
|
|
184
|
-
function findBadgeContainer(badgeContainer) {
|
|
185
|
-
const anchor = findBadgeAnchor(badgeContainer);
|
|
186
|
-
if (anchor) return anchor;
|
|
187
|
-
const selectors = ["main", '[role="main"]', "#root", "#__next", "#app"];
|
|
188
|
-
for (const sel of selectors) {
|
|
189
|
-
const el = document.querySelector(sel);
|
|
190
|
-
if (el) return el;
|
|
191
|
-
}
|
|
192
|
-
return document.body;
|
|
193
|
-
}
|
|
194
|
-
function installRouteWatcher() {
|
|
195
|
-
if (_routeWatcherInstalled || typeof window === "undefined") return;
|
|
196
|
-
_routeWatcherInstalled = true;
|
|
197
|
-
const orig = {
|
|
198
|
-
push: history.pushState.bind(history),
|
|
199
|
-
replace: history.replaceState.bind(history)
|
|
200
|
-
};
|
|
201
|
-
const dispatch = () => {
|
|
202
|
-
_routeChangeCallbacks.forEach((cb) => cb());
|
|
203
|
-
};
|
|
204
|
-
history.pushState = (...args) => {
|
|
205
|
-
orig.push(...args);
|
|
206
|
-
dispatch();
|
|
207
|
-
};
|
|
208
|
-
history.replaceState = (...args) => {
|
|
209
|
-
orig.replace(...args);
|
|
210
|
-
dispatch();
|
|
211
|
-
};
|
|
212
|
-
window.addEventListener("popstate", dispatch);
|
|
213
|
-
window.addEventListener("hashchange", dispatch);
|
|
25
|
+
const script = document.createElement("script");
|
|
26
|
+
script.src = CDN_URL;
|
|
27
|
+
script.async = true;
|
|
28
|
+
script.onload = () => resolve();
|
|
29
|
+
script.onerror = () => reject(new Error("[Prodigio] Failed to load SDK runtime from CDN"));
|
|
30
|
+
document.head.appendChild(script);
|
|
31
|
+
});
|
|
32
|
+
return _runtimePromise;
|
|
214
33
|
}
|
|
215
|
-
var _routeChangeCallbacks = [];
|
|
216
34
|
var _Prodigio = class _Prodigio {
|
|
217
35
|
constructor(config) {
|
|
218
|
-
// ── Jobs ──────────────────────────────────────────────────────────────────
|
|
219
36
|
this.jobs = {
|
|
220
37
|
list: (params) => {
|
|
221
38
|
const p = {};
|
|
@@ -225,7 +42,6 @@ var _Prodigio = class _Prodigio {
|
|
|
225
42
|
},
|
|
226
43
|
get: (jobId) => this.get(`/api/jobs/${jobId}`)
|
|
227
44
|
};
|
|
228
|
-
// ── Uploads ───────────────────────────────────────────────────────────────
|
|
229
45
|
this.upload = {
|
|
230
46
|
cv: (file, fileName) => {
|
|
231
47
|
const form = new FormData();
|
|
@@ -238,7 +54,6 @@ var _Prodigio = class _Prodigio {
|
|
|
238
54
|
return this.postForm("/api/upload/achievement", form);
|
|
239
55
|
}
|
|
240
56
|
};
|
|
241
|
-
// ── Applications ──────────────────────────────────────────────────────────
|
|
242
57
|
this.applications = {
|
|
243
58
|
submit: (params) => this.post("/api/applications", params)
|
|
244
59
|
};
|
|
@@ -289,120 +104,27 @@ var _Prodigio = class _Prodigio {
|
|
|
289
104
|
}
|
|
290
105
|
return res.json();
|
|
291
106
|
}
|
|
107
|
+
// ── Static methods — delegate to CDN runtime ──────────────────────────────
|
|
108
|
+
static async init(config) {
|
|
109
|
+
await ensureRuntime();
|
|
110
|
+
return window.Prodigio.init(config);
|
|
111
|
+
}
|
|
112
|
+
static destroy() {
|
|
113
|
+
var _a;
|
|
114
|
+
(_a = window.Prodigio) == null ? void 0 : _a.destroy();
|
|
115
|
+
}
|
|
292
116
|
static badge(poweredBy) {
|
|
117
|
+
var _a;
|
|
118
|
+
if ((_a = window.Prodigio) == null ? void 0 : _a.badge) {
|
|
119
|
+
return window.Prodigio.badge(poweredBy);
|
|
120
|
+
}
|
|
293
121
|
const pb = poweredBy != null ? poweredBy : _Prodigio.POWERED_BY;
|
|
294
122
|
return { href: pb.url, "data-prodigio-badge": "true", target: "_blank", rel: "noopener noreferrer", text: pb.text };
|
|
295
123
|
}
|
|
296
124
|
static meta() {
|
|
297
125
|
return { name: "prodigio-badge", content: "true" };
|
|
298
126
|
}
|
|
299
|
-
// ── init() ────────────────────────────────────────────────────────────────
|
|
300
|
-
static async init(config) {
|
|
301
|
-
var _a;
|
|
302
|
-
if (typeof window === "undefined") return;
|
|
303
|
-
if (_initialized) return;
|
|
304
|
-
_initialized = true;
|
|
305
|
-
if (process.env.NODE_ENV !== "production" && !document.querySelector('meta[name="prodigio-badge"]')) {
|
|
306
|
-
console.warn('[Prodigio] Missing <meta name="prodigio-badge" content="true"> in your page <head>. This is required for compliance detection. See docs.prodigio.io');
|
|
307
|
-
}
|
|
308
|
-
const { key, badgeToken, baseUrl = DEFAULT_BASE_URL, badge: badgeConfig, badgeContainer } = config;
|
|
309
|
-
const position = (_a = badgeConfig == null ? void 0 : badgeConfig.position) != null ? _a : "bottom-right";
|
|
310
|
-
const cached = getCachedToken(key);
|
|
311
|
-
const [initClaims, cachedClaims] = await Promise.all([
|
|
312
|
-
badgeToken ? verifyBadgeToken(badgeToken) : Promise.resolve(null),
|
|
313
|
-
cached ? verifyBadgeToken(cached.token) : Promise.resolve(null)
|
|
314
|
-
]);
|
|
315
|
-
let bestToken = null;
|
|
316
|
-
if (initClaims && cachedClaims) {
|
|
317
|
-
bestToken = new Date(initClaims.badgeExemptUntil) >= new Date(cachedClaims.badgeExemptUntil) ? initClaims : cachedClaims;
|
|
318
|
-
} else {
|
|
319
|
-
bestToken = initClaims != null ? initClaims : cachedClaims;
|
|
320
|
-
}
|
|
321
|
-
const hostname = window.location.hostname;
|
|
322
|
-
const domainAllowed = bestToken ? bestToken.allowedDomains.length === 0 || bestToken.allowedDomains.includes(hostname) : true;
|
|
323
|
-
const isExempt = bestToken !== null && !bestToken.badgeRequired && domainAllowed;
|
|
324
|
-
let configState = { status: "loading" };
|
|
325
|
-
function reconcile() {
|
|
326
|
-
cancelPending();
|
|
327
|
-
if (isExempt) {
|
|
328
|
-
removeBadge();
|
|
329
|
-
return;
|
|
330
|
-
}
|
|
331
|
-
if (configState.status === "loading" || configState.status === "error") {
|
|
332
|
-
return;
|
|
333
|
-
}
|
|
334
|
-
const { careersPath } = configState;
|
|
335
|
-
if (!careersPath) {
|
|
336
|
-
if (bestToken && cached) {
|
|
337
|
-
const cacheAge = Date.now() - cached.cachedAt;
|
|
338
|
-
if (cacheAge < GRACE_PERIOD_MS) {
|
|
339
|
-
removeBadge();
|
|
340
|
-
return;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) {
|
|
344
|
-
injectBadge(position, badgeContainer);
|
|
345
|
-
}
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
const routeMatches = pathMatches(window.location.pathname, careersPath);
|
|
349
|
-
if (!routeMatches) {
|
|
350
|
-
removeBadge();
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
queueMicrotask(() => {
|
|
354
|
-
_rafHandle = requestAnimationFrame(() => {
|
|
355
|
-
_rafHandle = null;
|
|
356
|
-
const anchor = findBadgeAnchor(badgeContainer);
|
|
357
|
-
if (anchor) {
|
|
358
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) injectBadge(position, badgeContainer);
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
waitForAnchor(badgeContainer, () => {
|
|
362
|
-
if (!document.getElementById(BADGE_ELEMENT_ID)) injectBadge(position, badgeContainer);
|
|
363
|
-
});
|
|
364
|
-
});
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
reconcile();
|
|
368
|
-
installRouteWatcher();
|
|
369
|
-
_routeChangeCallbacks.push(reconcile);
|
|
370
|
-
setTimeout(async () => {
|
|
371
|
-
var _a2, _b, _c;
|
|
372
|
-
try {
|
|
373
|
-
const res = await fetch(`${baseUrl}/api/sdk/config?key=${encodeURIComponent(key)}`);
|
|
374
|
-
if (!res.ok) return;
|
|
375
|
-
const data = await res.json();
|
|
376
|
-
configState = {
|
|
377
|
-
status: "loaded",
|
|
378
|
-
careersPath: (_a2 = data.careersPath) != null ? _a2 : null,
|
|
379
|
-
badgeRequired: data.badgeRequired
|
|
380
|
-
};
|
|
381
|
-
if (data.badgeRequired) {
|
|
382
|
-
reconcile();
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
if (data.badgeToken) {
|
|
386
|
-
const refreshedClaims = await verifyBadgeToken(data.badgeToken);
|
|
387
|
-
if (refreshedClaims && !refreshedClaims.badgeRequired) {
|
|
388
|
-
cacheToken(key, data.badgeToken, (_b = data.badgeExemptUntil) != null ? _b : "", (_c = data.configVersion) != null ? _c : 1);
|
|
389
|
-
removeBadge();
|
|
390
|
-
return;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
reconcile();
|
|
394
|
-
} catch {
|
|
395
|
-
configState = { status: "error" };
|
|
396
|
-
}
|
|
397
|
-
}, 0);
|
|
398
|
-
}
|
|
399
|
-
static destroy() {
|
|
400
|
-
cancelPending();
|
|
401
|
-
removeBadge();
|
|
402
|
-
_initialized = false;
|
|
403
|
-
}
|
|
404
127
|
};
|
|
405
|
-
// ── Badge static helpers ──────────────────────────────────────────────────
|
|
406
128
|
_Prodigio.POWERED_BY = {
|
|
407
129
|
text: "Hiring powered by Prodigio",
|
|
408
130
|
url: "https://prodigio.io"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prodigio-io/sdk",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Official JavaScript SDK for the Prodigio hiring API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean",
|
|
20
|
-
"
|
|
20
|
+
"build:cdn": "tsup src/cdn.ts --format iife --no-dts --minify --out-dir dist-cdn --clean",
|
|
21
|
+
"dev": "tsup src/index.ts --format esm,cjs --dts --watch",
|
|
22
|
+
"publish:cdn": "node scripts/publish-cdn.js"
|
|
21
23
|
},
|
|
22
24
|
"keywords": [
|
|
23
25
|
"prodigio",
|