@hirely/sdk 1.0.1 → 1.0.3

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.
@@ -0,0 +1,26 @@
1
+ /** @internal */
2
+ export class MemoryCache {
3
+ store = new Map();
4
+ get(key) {
5
+ const entry = this.store.get(key);
6
+ if (!entry)
7
+ return undefined;
8
+ if (Date.now() > entry.expiresAt) {
9
+ this.store.delete(key);
10
+ return undefined;
11
+ }
12
+ return entry.value;
13
+ }
14
+ set(key, value, ttlSeconds) {
15
+ this.store.set(key, {
16
+ value,
17
+ expiresAt: Date.now() + ttlSeconds * 1000,
18
+ });
19
+ }
20
+ delete(key) {
21
+ this.store.delete(key);
22
+ }
23
+ clear() {
24
+ this.store.clear();
25
+ }
26
+ }
package/dist/client.js ADDED
@@ -0,0 +1,183 @@
1
+ import { RequestClient } from "./http/request.js";
2
+ import { API_KEY_PREFIX, DEFAULT_TIMEOUT_MS, DEFAULT_RETRIES } from "./constants.js";
3
+ import { HirelyValidationError } from "./errors.js";
4
+ import { createProjectsResource } from "./resources/projects.js";
5
+ import { createWorkResource } from "./resources/work.js";
6
+ import { createEducationResource } from "./resources/education.js";
7
+ import { createSkillsResource } from "./resources/skills.js";
8
+ import { createCertificatesResource } from "./resources/certificates.js";
9
+ import { createServicesResource } from "./resources/services.js";
10
+ import { createTestimonialsResource } from "./resources/testimonials.js";
11
+ import { createFaqsResource } from "./resources/faqs.js";
12
+ import { createContactsResource } from "./resources/contacts.js";
13
+ import { createCvResource } from "./resources/cv.js";
14
+ /**
15
+ * The Hirely SDK client.
16
+ *
17
+ * Instantiate once with your public API key and use any method or
18
+ * resource to fetch your portfolio data from the Hirely API.
19
+ *
20
+ * @example Basic usage
21
+ * ```ts
22
+ * import Hirely from "@hirely/sdk";
23
+ *
24
+ * const hirely = new Hirely({
25
+ * apiKey: process.env.HIRELY_API_KEY!,
26
+ * });
27
+ *
28
+ * const portfolio = await hirely.get();
29
+ * const me = await hirely.me();
30
+ * const project = await hirely.projects.getBySlug("my-app");
31
+ * ```
32
+ *
33
+ * @example With caching and retries
34
+ * ```ts
35
+ * const hirely = new Hirely({
36
+ * apiKey: process.env.HIRELY_API_KEY!,
37
+ * timeout: 10_000,
38
+ * retries: 2,
39
+ * cache: { enabled: true, ttl: 300 },
40
+ * });
41
+ * ```
42
+ */
43
+ export default class Hirely {
44
+ /** @internal */
45
+ http;
46
+ /**
47
+ * Projects resource.
48
+ * - `hirely.projects()` — all public projects
49
+ * - `hirely.projects.getById(id)` — fetch by MongoDB ID
50
+ * - `hirely.projects.getBySlug(slug)` — fetch by URL slug
51
+ */
52
+ projects;
53
+ /**
54
+ * Work experience resource.
55
+ * - `hirely.work()` — all work experience entries
56
+ * - `hirely.work.getById(id)` — fetch a single entry
57
+ */
58
+ work;
59
+ /**
60
+ * Education resource.
61
+ * - `hirely.education()` — all education entries
62
+ * - `hirely.education.getById(id)` — fetch a single entry
63
+ */
64
+ education;
65
+ /**
66
+ * Skills resource.
67
+ * - `hirely.skills()` — all skills
68
+ */
69
+ skills;
70
+ /**
71
+ * Certificates resource.
72
+ * - `hirely.certificates()` — all certificates
73
+ * - `hirely.certificates.getById(id)` — fetch a single certificate
74
+ */
75
+ certificates;
76
+ /**
77
+ * Services resource.
78
+ * - `hirely.services()` — all public services
79
+ * - `hirely.services.getById(id)` — fetch a single service
80
+ */
81
+ services;
82
+ /**
83
+ * Testimonials resource (approved and public only).
84
+ * - `hirely.testimonials()` — all testimonials
85
+ * - `hirely.testimonials.getById(id)` — fetch a single testimonial
86
+ */
87
+ testimonials;
88
+ /**
89
+ * FAQ resource.
90
+ * - `hirely.faqs()` — all FAQ entries
91
+ * - `hirely.faqs.getById(id)` — fetch a single FAQ
92
+ */
93
+ faqs;
94
+ /**
95
+ * Contacts resource.
96
+ * - `hirely.contacts()` — public social links
97
+ */
98
+ contacts;
99
+ /**
100
+ * CV resource.
101
+ * - `hirely.cv()` — most recent public CV
102
+ */
103
+ cv;
104
+ constructor(config) {
105
+ if (!config.apiKey) {
106
+ throw new HirelyValidationError("Hirely API key is required. Pass it as `apiKey` in the constructor.", 400);
107
+ }
108
+ if (!config.apiKey.startsWith(API_KEY_PREFIX)) {
109
+ throw new HirelyValidationError(`Invalid Hirely API key. Keys must start with "${API_KEY_PREFIX}".`, 400);
110
+ }
111
+ this.http = new RequestClient({
112
+ apiKey: config.apiKey,
113
+ timeout: config.timeout ?? DEFAULT_TIMEOUT_MS,
114
+ retries: config.retries ?? DEFAULT_RETRIES,
115
+ fetchFn: config.fetch ?? globalThis.fetch.bind(globalThis),
116
+ cacheConfig: config.cache, // ← can be `undefined`
117
+ });
118
+ this.projects = createProjectsResource(this.http);
119
+ this.work = createWorkResource(this.http);
120
+ this.education = createEducationResource(this.http);
121
+ this.skills = createSkillsResource(this.http);
122
+ this.certificates = createCertificatesResource(this.http);
123
+ this.services = createServicesResource(this.http);
124
+ this.testimonials = createTestimonialsResource(this.http);
125
+ this.faqs = createFaqsResource(this.http);
126
+ this.contacts = createContactsResource(this.http);
127
+ this.cv = createCvResource(this.http);
128
+ }
129
+ /**
130
+ * Fetches the complete public portfolio in a single request.
131
+ *
132
+ * Returns profile, projects, work, education, skills, certificates,
133
+ * services, testimonials, FAQs, contacts, and CV.
134
+ *
135
+ * @param options - Optional per-request options.
136
+ *
137
+ * @example
138
+ * ```ts
139
+ * const portfolio = await hirely.get();
140
+ * console.log(portfolio.profile?.firstName);
141
+ * console.log(portfolio.projects.length);
142
+ * ```
143
+ *
144
+ * @example Next.js Server Component
145
+ * ```tsx
146
+ * export default async function Page() {
147
+ * const portfolio = await hirely.get();
148
+ * return (
149
+ * <main>
150
+ * <h1>{portfolio.profile?.firstName} {portfolio.profile?.lastName}</h1>
151
+ * {portfolio.projects.map((p) => (
152
+ * <article key={p._id}><h2>{p.title}</h2></article>
153
+ * ))}
154
+ * </main>
155
+ * );
156
+ * }
157
+ * ```
158
+ */
159
+ get(options) {
160
+ return this.http.request("/all", options);
161
+ }
162
+ /**
163
+ * Fetches account information and the full public profile.
164
+ *
165
+ * Returns account-level data (username, email, role, plan) plus the
166
+ * complete profile (name, bio, avatar, location, birthday, etc.).
167
+ *
168
+ * @param options - Optional per-request options.
169
+ *
170
+ * @example
171
+ * ```ts
172
+ * const me = await hirely.me();
173
+ * console.log(me.userName); // "mahmoud"
174
+ * console.log(me.plan); // "pro"
175
+ * console.log(me.profile?.firstName); // "Mahmoud"
176
+ * console.log(me.profile?.positionName); // "Full-Stack Developer"
177
+ * console.log(me.profile?.avatar?.url); // "https://..."
178
+ * ```
179
+ */
180
+ me(options) {
181
+ return this.http.request("/me", options);
182
+ }
183
+ }
@@ -0,0 +1,12 @@
1
+ /** @internal Base URL for the Hirely public API. Not configurable by consumers. */
2
+ export const BASE_URL = "https://api.hirely.cc/api/v1/sdk";
3
+ /** @internal Required prefix for all Hirely public API keys. */
4
+ export const API_KEY_PREFIX = "hk_pub_";
5
+ /** Default request timeout in milliseconds. */
6
+ export const DEFAULT_TIMEOUT_MS = 30_000;
7
+ /** Default number of retry attempts for transient errors. */
8
+ export const DEFAULT_RETRIES = 2;
9
+ /** HTTP status codes that trigger a retry. */
10
+ export const RETRYABLE_STATUS_CODES = new Set([408, 425, 429, 500, 502, 503, 504]);
11
+ /** Maximum backoff delay between retries in milliseconds. */
12
+ export const MAX_BACKOFF_MS = 30_000;
package/dist/errors.d.ts CHANGED
@@ -15,12 +15,9 @@
15
15
  * ```
16
16
  */
17
17
  export declare class HirelyError extends Error {
18
- /** HTTP status code (0 for network/timeout errors). */
19
18
  readonly status: number;
20
- /** Machine-readable error code. */
21
19
  readonly code: string;
22
- /** The request ID from the server, if available. */
23
- readonly requestId?: string;
20
+ readonly requestId: string | undefined;
24
21
  constructor(message: string, status: number, code?: string, requestId?: string);
25
22
  }
26
23
  /**
@@ -84,8 +81,7 @@ export declare class HirelyValidationError extends HirelyError {
84
81
  * ```
85
82
  */
86
83
  export declare class HirelyRateLimitError extends HirelyError {
87
- /** Seconds until the rate limit resets (from `Retry-After` header). */
88
- readonly retryAfter?: number;
84
+ readonly retryAfter: number | undefined;
89
85
  constructor(message?: string, retryAfter?: number, requestId?: string);
90
86
  }
91
87
  /**
package/dist/errors.js ADDED
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Base class for all Hirely SDK errors.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import { HirelyError } from "@hirely/sdk";
7
+ *
8
+ * try {
9
+ * await hirely.get();
10
+ * } catch (error) {
11
+ * if (error instanceof HirelyError) {
12
+ * console.error(error.status, error.message);
13
+ * }
14
+ * }
15
+ * ```
16
+ */
17
+ export class HirelyError extends Error {
18
+ status;
19
+ code;
20
+ requestId;
21
+ constructor(message, status, code = "HIRELY_ERROR", requestId) {
22
+ super(message);
23
+ this.name = "HirelyError";
24
+ this.status = status;
25
+ this.code = code;
26
+ this.requestId = requestId;
27
+ Object.setPrototypeOf(this, new.target.prototype);
28
+ }
29
+ }
30
+ /**
31
+ * Thrown when the API key is missing, invalid, or revoked (HTTP 401/403).
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { HirelyAuthenticationError } from "@hirely/sdk";
36
+ *
37
+ * try {
38
+ * await hirely.get();
39
+ * } catch (error) {
40
+ * if (error instanceof HirelyAuthenticationError) {
41
+ * console.error("Check your HIRELY_API_KEY.");
42
+ * }
43
+ * }
44
+ * ```
45
+ */
46
+ export class HirelyAuthenticationError extends HirelyError {
47
+ constructor(message = "Invalid or missing API key", status = 401, requestId) {
48
+ super(message, status, "AUTHENTICATION_ERROR", requestId);
49
+ this.name = "HirelyAuthenticationError";
50
+ }
51
+ }
52
+ /**
53
+ * Thrown when a requested resource does not exist (HTTP 404).
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { HirelyNotFoundError } from "@hirely/sdk";
58
+ *
59
+ * try {
60
+ * const project = await hirely.projects.getBySlug("nonexistent");
61
+ * } catch (error) {
62
+ * if (error instanceof HirelyNotFoundError) {
63
+ * console.log("Project not found");
64
+ * }
65
+ * }
66
+ * ```
67
+ */
68
+ export class HirelyNotFoundError extends HirelyError {
69
+ constructor(message = "Resource not found", requestId) {
70
+ super(message, 404, "NOT_FOUND", requestId);
71
+ this.name = "HirelyNotFoundError";
72
+ }
73
+ }
74
+ /**
75
+ * Thrown when a request fails validation (HTTP 400/422).
76
+ */
77
+ export class HirelyValidationError extends HirelyError {
78
+ constructor(message = "Validation error", status = 422, requestId) {
79
+ super(message, status, "VALIDATION_ERROR", requestId);
80
+ this.name = "HirelyValidationError";
81
+ }
82
+ }
83
+ /**
84
+ * Thrown when the API rate limit has been exceeded (HTTP 429).
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * import { HirelyRateLimitError } from "@hirely/sdk";
89
+ *
90
+ * try {
91
+ * await hirely.get();
92
+ * } catch (error) {
93
+ * if (error instanceof HirelyRateLimitError) {
94
+ * console.log(`Retry after ${error.retryAfter}s`);
95
+ * }
96
+ * }
97
+ * ```
98
+ */
99
+ export class HirelyRateLimitError extends HirelyError {
100
+ retryAfter; // ← was `?: number`
101
+ constructor(message = "Rate limit exceeded", retryAfter, requestId) {
102
+ super(message, 429, "RATE_LIMIT_EXCEEDED", requestId);
103
+ this.name = "HirelyRateLimitError";
104
+ this.retryAfter = retryAfter;
105
+ }
106
+ }
107
+ /**
108
+ * Thrown when a request exceeds the configured timeout.
109
+ *
110
+ * @example
111
+ * ```ts
112
+ * const hirely = new Hirely({ apiKey, timeout: 5000 });
113
+ *
114
+ * try {
115
+ * await hirely.get();
116
+ * } catch (error) {
117
+ * if (error instanceof HirelyTimeoutError) {
118
+ * console.error("Request timed out after 5s");
119
+ * }
120
+ * }
121
+ * ```
122
+ */
123
+ export class HirelyTimeoutError extends HirelyError {
124
+ constructor(message = "Request timed out") {
125
+ super(message, 0, "TIMEOUT");
126
+ this.name = "HirelyTimeoutError";
127
+ }
128
+ }
129
+ /**
130
+ * Thrown when the Hirely API returns a server-side error (HTTP 5xx).
131
+ */
132
+ export class HirelyServerError extends HirelyError {
133
+ constructor(message = "Internal server error", status = 500, requestId) {
134
+ super(message, status, "SERVER_ERROR", requestId);
135
+ this.name = "HirelyServerError";
136
+ }
137
+ }
@@ -0,0 +1,138 @@
1
+ import { HirelyError, HirelyAuthenticationError, HirelyNotFoundError, HirelyValidationError, HirelyRateLimitError, HirelyTimeoutError, HirelyServerError, } from "../errors.js";
2
+ import { MemoryCache } from "../cache/memory-cache.js";
3
+ import { BASE_URL, DEFAULT_TIMEOUT_MS, DEFAULT_RETRIES, RETRYABLE_STATUS_CODES, MAX_BACKOFF_MS, } from "../constants.js";
4
+ /** @internal */
5
+ export class RequestClient {
6
+ apiKey;
7
+ timeout;
8
+ retries;
9
+ fetchFn;
10
+ cache = null;
11
+ cacheTtl;
12
+ constructor(config) {
13
+ this.apiKey = config.apiKey;
14
+ this.timeout = config.timeout;
15
+ this.retries = config.retries;
16
+ this.fetchFn = config.fetchFn;
17
+ this.cacheTtl = config.cacheConfig?.ttl ?? 300;
18
+ if (config.cacheConfig?.enabled) {
19
+ this.cache = config.cacheConfig.store ?? new MemoryCache();
20
+ }
21
+ }
22
+ buildCacheKey(endpoint) {
23
+ const keyScope = this.apiKey.slice(-8);
24
+ return `${keyScope}:${BASE_URL}${endpoint}`;
25
+ }
26
+ async fetchWithTimeout(url, init) {
27
+ if (this.timeout === 0) {
28
+ return this.fetchFn(url, init);
29
+ }
30
+ const controller = new AbortController();
31
+ const timer = setTimeout(() => controller.abort(), this.timeout);
32
+ try {
33
+ return await this.fetchFn(url, { ...init, signal: controller.signal });
34
+ }
35
+ catch (error) {
36
+ if (error instanceof Error && error.name === "AbortError") {
37
+ throw new HirelyTimeoutError(`Request timed out after ${this.timeout}ms`);
38
+ }
39
+ throw error;
40
+ }
41
+ finally {
42
+ clearTimeout(timer);
43
+ }
44
+ }
45
+ throwForStatus(status, message, requestId) {
46
+ switch (true) {
47
+ case status === 401 || status === 403:
48
+ throw new HirelyAuthenticationError(message, status, requestId);
49
+ case status === 404:
50
+ throw new HirelyNotFoundError(message, requestId);
51
+ case status === 400 || status === 422:
52
+ throw new HirelyValidationError(message, status, requestId);
53
+ case status === 429:
54
+ throw new HirelyRateLimitError(message, undefined, requestId);
55
+ case status >= 500:
56
+ throw new HirelyServerError(message, status, requestId);
57
+ default:
58
+ throw new HirelyError(message, status, "REQUEST_FAILED", requestId);
59
+ }
60
+ }
61
+ getRetryAfter(headers) {
62
+ const value = headers.get("retry-after");
63
+ if (!value)
64
+ return undefined;
65
+ const seconds = Number(value);
66
+ return Number.isFinite(seconds) ? seconds : undefined;
67
+ }
68
+ computeBackoff(attempt, retryAfterSeconds) {
69
+ if (retryAfterSeconds != null) {
70
+ return Math.min(retryAfterSeconds * 1000, MAX_BACKOFF_MS);
71
+ }
72
+ return Math.min(1000 * Math.pow(2, attempt), MAX_BACKOFF_MS);
73
+ }
74
+ sleep(ms) {
75
+ return new Promise((resolve) => setTimeout(resolve, ms));
76
+ }
77
+ async request(endpoint, options) {
78
+ const bypassCache = options?.cache === false;
79
+ const cacheKey = this.buildCacheKey(endpoint);
80
+ if (this.cache && !bypassCache) {
81
+ const cached = await this.cache.get(cacheKey);
82
+ if (cached !== undefined)
83
+ return cached;
84
+ }
85
+ const url = `${BASE_URL}${endpoint}`;
86
+ const headers = {
87
+ Authorization: `Bearer ${this.apiKey}`,
88
+ Accept: "application/json",
89
+ "Content-Type": "application/json",
90
+ };
91
+ let lastError;
92
+ for (let attempt = 0; attempt <= this.retries; attempt++) {
93
+ let response;
94
+ try {
95
+ response = await this.fetchWithTimeout(url, { method: "GET", headers });
96
+ }
97
+ catch (error) {
98
+ if (error instanceof HirelyTimeoutError)
99
+ throw error;
100
+ lastError = error;
101
+ if (attempt < this.retries) {
102
+ await this.sleep(this.computeBackoff(attempt));
103
+ continue;
104
+ }
105
+ throw new HirelyError(error instanceof Error ? error.message : "Network request failed", 0, "NETWORK_ERROR");
106
+ }
107
+ const requestId = response.headers.get("x-request-id") ?? undefined;
108
+ if (response.status === 429 && attempt < this.retries) {
109
+ const retryAfter = this.getRetryAfter(response.headers);
110
+ await this.sleep(this.computeBackoff(attempt, retryAfter));
111
+ continue;
112
+ }
113
+ if (RETRYABLE_STATUS_CODES.has(response.status) && response.status !== 429 && attempt < this.retries) {
114
+ await this.sleep(this.computeBackoff(attempt));
115
+ continue;
116
+ }
117
+ let body;
118
+ try {
119
+ body = (await response.json());
120
+ }
121
+ catch {
122
+ if (!response.ok) {
123
+ this.throwForStatus(response.status, "Request failed", requestId);
124
+ }
125
+ throw new HirelyError("Invalid response from Hirely API", response.status, "PARSE_ERROR", requestId);
126
+ }
127
+ if (!response.ok || !body.success) {
128
+ this.throwForStatus(response.status, body?.message ?? "Request failed", requestId);
129
+ }
130
+ const data = body.data;
131
+ if (this.cache && !bypassCache) {
132
+ await this.cache.set(cacheKey, data, this.cacheTtl);
133
+ }
134
+ return data;
135
+ }
136
+ throw lastError ?? new HirelyError("Request failed after retries", 0, "REQUEST_FAILED");
137
+ }
138
+ }
package/dist/index.d.ts CHANGED
@@ -14,10 +14,9 @@
14
14
  *
15
15
  * @module
16
16
  */
17
- export { default } from "./client.js";
18
- export { default as Hirely } from "./client.js";
17
+ export { default, default as Hirely } from "./client.js";
19
18
  export { HirelyError, HirelyAuthenticationError, HirelyNotFoundError, HirelyValidationError, HirelyRateLimitError, HirelyTimeoutError, HirelyServerError, } from "./errors.js";
20
- export type { HirelyConfig, HirelyCacheConfig, HirelyCache, HirelyRequestOptions, HirelyPortfolio, HirelyMe, HirelyProfile, HirelyProject, HirelyProjectMedia, HirelyWork, HirelyEducation, HirelySkill, HirelyCertificate, HirelyService, HirelyTestimonial, HirelyTestimonialClient, HirelyFaq, HirelyContact, HirелySocialLink, HirelyCV, } from "./types.js";
19
+ export type { HirelyConfig, HirelyCacheConfig, HirelyCache, HirelyRequestOptions, HirelyPortfolio, HirelyMe, HirelyProfile, HirelyProject, HirelyProjectMedia, HirelyWork, HirelyEducation, HirelySkill, HirelyCertificate, HirelyService, HirelyTestimonial, HirelyTestimonialClient, HirelyFaq, HirelyContact, HirelySocialLink, HirelyCV, } from "./types.js";
21
20
  export type { ProjectsResource } from "./resources/projects.js";
22
21
  export type { WorkResource } from "./resources/work.js";
23
22
  export type { EducationResource } from "./resources/education.js";
package/dist/index.js CHANGED
@@ -1 +1,18 @@
1
- export{s as Hirely,c as HirelyAuthenticationError,l as HirelyError,y as HirelyNotFoundError,p as HirelyRateLimitError,a as HirelyServerError,H as HirelyTimeoutError,u as HirelyValidationError,o as default};
1
+ /**
2
+ * @hirely/sdk — Official JavaScript & TypeScript SDK for Hirely.
3
+ *
4
+ * @example
5
+ * ```ts
6
+ * import Hirely from "@hirely/sdk";
7
+ *
8
+ * const hirely = new Hirely({ apiKey: process.env.HIRELY_API_KEY! });
9
+ *
10
+ * const portfolio = await hirely.get();
11
+ * const me = await hirely.me();
12
+ * const project = await hirely.projects.getBySlug("my-app");
13
+ * ```
14
+ *
15
+ * @module
16
+ */
17
+ export { default, default as Hirely } from "./client.js";
18
+ export { HirelyError, HirelyAuthenticationError, HirelyNotFoundError, HirelyValidationError, HirelyRateLimitError, HirelyTimeoutError, HirelyServerError, } from "./errors.js";
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createCertificatesResource(http) {
3
+ const fn = (options) => http.request("/certificates", options);
4
+ fn.getById = (id, options) => http.request(`/certificates/${id}`, options);
5
+ return fn;
6
+ }
@@ -0,0 +1,4 @@
1
+ /** @internal */
2
+ export function createContactsResource(http) {
3
+ return (options) => http.request("/contacts", options);
4
+ }
@@ -0,0 +1,4 @@
1
+ /** @internal */
2
+ export function createCvResource(http) {
3
+ return (options) => http.request("/cv", options);
4
+ }
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createEducationResource(http) {
3
+ const fn = (options) => http.request("/educations", options);
4
+ fn.getById = (id, options) => http.request(`/educations/${id}`, options);
5
+ return fn;
6
+ }
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createFaqsResource(http) {
3
+ const fn = (options) => http.request("/faq", options);
4
+ fn.getById = (id, options) => http.request(`/faq/${id}`, options);
5
+ return fn;
6
+ }
@@ -0,0 +1,7 @@
1
+ /** @internal */
2
+ export function createProjectsResource(http) {
3
+ const fn = (options) => http.request("/projects", options);
4
+ fn.getById = (id, options) => http.request(`/projects/${id}`, options);
5
+ fn.getBySlug = (slug, options) => http.request(`/projects/slug/${slug}`, options);
6
+ return fn;
7
+ }
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createServicesResource(http) {
3
+ const fn = (options) => http.request("/services", options);
4
+ fn.getById = (id, options) => http.request(`/services/${id}`, options);
5
+ return fn;
6
+ }
@@ -0,0 +1,4 @@
1
+ /** @internal */
2
+ export function createSkillsResource(http) {
3
+ return (options) => http.request("/skills", options);
4
+ }
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createTestimonialsResource(http) {
3
+ const fn = (options) => http.request("/testimonials", options);
4
+ fn.getById = (id, options) => http.request(`/testimonials/${id}`, options);
5
+ return fn;
6
+ }
@@ -0,0 +1,6 @@
1
+ /** @internal */
2
+ export function createWorkResource(http) {
3
+ const fn = (options) => http.request("/works", options);
4
+ fn.getById = (id, options) => http.request(`/works/${id}`, options);
5
+ return fn;
6
+ }
package/dist/types.d.ts CHANGED
@@ -434,10 +434,10 @@ export interface HirelyContact {
434
434
  /** MongoDB document ID. */
435
435
  _id: string;
436
436
  /** List of social/contact links. */
437
- socialLinks?: HirелySocialLink[];
437
+ socialLinks?: HirelySocialLink[];
438
438
  }
439
439
  /** A single social or contact link. */
440
- export interface HirелySocialLink {
440
+ export interface HirelySocialLink {
441
441
  /** Social platform name (e.g. "github", "linkedIn"). */
442
442
  platform: string;
443
443
  /** The profile URL. */
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hirely/sdk",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Official JavaScript and TypeScript SDK for connecting your Hirely portfolio to any website or application.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -28,13 +28,12 @@
28
28
  "CHANGELOG.md"
29
29
  ],
30
30
  "scripts": {
31
- "build:js": "bun build src/index.ts --outdir dist --target node --format esm --minify",
32
- "build:types": "tsc -p tsconfig.build.json",
33
31
  "build": "bun scripts/build.ts",
34
32
  "typecheck": "bunx tsgo --noEmit",
35
33
  "test": "bun test",
34
+ "smoke": "bun scripts/smoke.ts",
36
35
  "clean": "rm -rf dist",
37
- "prepublishOnly": "bun run clean && bun run typecheck && bun run build && bun test",
36
+ "prepublishOnly": "bun run clean && bun run typecheck && bun run build && bun run smoke && bun test",
38
37
  "release:patch": "npm version patch && git push --follow-tags && npm publish",
39
38
  "release:minor": "npm version minor && git push --follow-tags && npm publish",
40
39
  "release:major": "npm version major && git push --follow-tags && npm publish"