@geekapps/post-fastify 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/client.d.ts +31 -0
  2. package/dist/client.d.ts.map +1 -0
  3. package/dist/client.js +29 -0
  4. package/dist/client.js.map +1 -0
  5. package/dist/errors.d.ts +11 -0
  6. package/dist/errors.d.ts.map +1 -0
  7. package/dist/errors.js +24 -0
  8. package/dist/errors.js.map +1 -0
  9. package/dist/http.d.ts +21 -0
  10. package/dist/http.d.ts.map +1 -0
  11. package/dist/http.js +56 -0
  12. package/dist/http.js.map +1 -0
  13. package/dist/index.d.ts +21 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +17 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/nextjs.d.ts +22 -0
  18. package/dist/nextjs.d.ts.map +1 -0
  19. package/dist/nextjs.js +15 -0
  20. package/dist/nextjs.js.map +1 -0
  21. package/dist/plugin.d.ts +19 -0
  22. package/dist/plugin.d.ts.map +1 -0
  23. package/dist/plugin.js +17 -0
  24. package/dist/plugin.js.map +1 -0
  25. package/dist/resources/domains.d.ts +14 -0
  26. package/dist/resources/domains.d.ts.map +1 -0
  27. package/dist/resources/domains.js +21 -0
  28. package/dist/resources/domains.js.map +1 -0
  29. package/dist/resources/history.d.ts +9 -0
  30. package/dist/resources/history.d.ts.map +1 -0
  31. package/dist/resources/history.js +26 -0
  32. package/dist/resources/history.js.map +1 -0
  33. package/dist/resources/managed-numbers.d.ts +28 -0
  34. package/dist/resources/managed-numbers.d.ts.map +1 -0
  35. package/dist/resources/managed-numbers.js +24 -0
  36. package/dist/resources/managed-numbers.js.map +1 -0
  37. package/dist/resources/messages.d.ts +8 -0
  38. package/dist/resources/messages.d.ts.map +1 -0
  39. package/dist/resources/messages.js +9 -0
  40. package/dist/resources/messages.js.map +1 -0
  41. package/dist/resources/plans.d.ts +10 -0
  42. package/dist/resources/plans.d.ts.map +1 -0
  43. package/dist/resources/plans.js +15 -0
  44. package/dist/resources/plans.js.map +1 -0
  45. package/dist/resources/smtp.d.ts +14 -0
  46. package/dist/resources/smtp.d.ts.map +1 -0
  47. package/dist/resources/smtp.js +18 -0
  48. package/dist/resources/smtp.js.map +1 -0
  49. package/dist/resources/statistics.d.ts +8 -0
  50. package/dist/resources/statistics.d.ts.map +1 -0
  51. package/dist/resources/statistics.js +17 -0
  52. package/dist/resources/statistics.js.map +1 -0
  53. package/dist/resources/templates.d.ts +17 -0
  54. package/dist/resources/templates.d.ts.map +1 -0
  55. package/dist/resources/templates.js +33 -0
  56. package/dist/resources/templates.js.map +1 -0
  57. package/dist/resources/webhooks.d.ts +13 -0
  58. package/dist/resources/webhooks.d.ts.map +1 -0
  59. package/dist/resources/webhooks.js +24 -0
  60. package/dist/resources/webhooks.js.map +1 -0
  61. package/dist/resources/whatsapp-numbers.d.ts +23 -0
  62. package/dist/resources/whatsapp-numbers.d.ts.map +1 -0
  63. package/dist/resources/whatsapp-numbers.js +56 -0
  64. package/dist/resources/whatsapp-numbers.js.map +1 -0
  65. package/dist/resources/whatsapp-templates.d.ts +12 -0
  66. package/dist/resources/whatsapp-templates.d.ts.map +1 -0
  67. package/dist/resources/whatsapp-templates.js +21 -0
  68. package/dist/resources/whatsapp-templates.js.map +1 -0
  69. package/dist/service-account.d.ts +47 -0
  70. package/dist/service-account.d.ts.map +1 -0
  71. package/dist/service-account.js +76 -0
  72. package/dist/service-account.js.map +1 -0
  73. package/dist/types.d.ts +346 -0
  74. package/dist/types.d.ts.map +1 -0
  75. package/dist/types.js +3 -0
  76. package/dist/types.js.map +1 -0
  77. package/package.json +27 -0
  78. package/src/client.ts +49 -0
  79. package/src/errors.ts +30 -0
  80. package/src/http.ts +88 -0
  81. package/src/index.ts +79 -0
  82. package/src/plugin.ts +39 -0
  83. package/src/resources/domains.ts +26 -0
  84. package/src/resources/history.ts +22 -0
  85. package/src/resources/managed-numbers.ts +47 -0
  86. package/src/resources/messages.ts +10 -0
  87. package/src/resources/plans.ts +18 -0
  88. package/src/resources/smtp.ts +22 -0
  89. package/src/resources/statistics.ts +15 -0
  90. package/src/resources/templates.ts +44 -0
  91. package/src/resources/webhooks.ts +37 -0
  92. package/src/resources/whatsapp-numbers.ts +84 -0
  93. package/src/resources/whatsapp-templates.ts +31 -0
  94. package/src/service-account.ts +112 -0
  95. package/src/types.ts +418 -0
  96. package/tsconfig.json +18 -0
@@ -0,0 +1,26 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { CreateDomainInput, CreateDomainResult, OrgDomain } from "../types.js";
3
+
4
+ export class DomainsResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ list(): Promise<OrgDomain[]> {
8
+ return this.http.get<OrgDomain[]>("/domains");
9
+ }
10
+
11
+ get(id: string): Promise<OrgDomain> {
12
+ return this.http.get<OrgDomain>(`/domains/${id}`);
13
+ }
14
+
15
+ create(input: CreateDomainInput): Promise<CreateDomainResult> {
16
+ return this.http.post<CreateDomainResult>("/domains", input);
17
+ }
18
+
19
+ verify(id: string): Promise<{ status: "verified" | "failed" }> {
20
+ return this.http.post<{ status: "verified" | "failed" }>(`/domains/${id}/verify`);
21
+ }
22
+
23
+ delete(id: string): Promise<void> {
24
+ return this.http.delete(`/domains/${id}`);
25
+ }
26
+ }
@@ -0,0 +1,22 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { ListHistoryParams, MessageLog, MessageLogDetail, PaginatedResult } from "../types.js";
3
+
4
+ export class HistoryResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ list(params?: ListHistoryParams): Promise<PaginatedResult<MessageLog>> {
8
+ const qs = new URLSearchParams();
9
+ if (params?.type) qs.set("type", params.type);
10
+ if (params?.status) qs.set("status", params.status);
11
+ if (params?.from) qs.set("from", params.from);
12
+ if (params?.to) qs.set("to", params.to);
13
+ if (params?.page !== undefined) qs.set("page", String(params.page));
14
+ if (params?.limit !== undefined) qs.set("limit", String(params.limit));
15
+ const query = qs.toString();
16
+ return this.http.get<PaginatedResult<MessageLog>>(`/history${query ? `?${query}` : ""}`);
17
+ }
18
+
19
+ get(id: string): Promise<MessageLogDetail> {
20
+ return this.http.get<MessageLogDetail>(`/history/${id}`);
21
+ }
22
+ }
@@ -0,0 +1,47 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { AreaCode, ManagedNumber } from "../types.js";
3
+
4
+ export interface ProvisionManagedNumberInput {
5
+ areaCode: number;
6
+ name?: string;
7
+ displayName: string;
8
+ otpMethod?: "SMS" | "VOICE";
9
+ otpLanguage?: string;
10
+ pin?: string;
11
+ orgWabaId?: string;
12
+ wabaId?: string;
13
+ accessToken?: string;
14
+ }
15
+
16
+ export interface RetryVerificationInput {
17
+ otpMethod?: "SMS" | "VOICE";
18
+ otpLanguage?: string;
19
+ }
20
+
21
+ export class ManagedNumbersResource {
22
+ constructor(private readonly http: HttpClient) {}
23
+
24
+ listAreaCodes(): Promise<AreaCode[]> {
25
+ return this.http.get<AreaCode[]>("/managed-numbers/area-codes");
26
+ }
27
+
28
+ list(): Promise<ManagedNumber[]> {
29
+ return this.http.get<ManagedNumber[]>("/managed-numbers");
30
+ }
31
+
32
+ get(id: string): Promise<ManagedNumber> {
33
+ return this.http.get<ManagedNumber>(`/managed-numbers/${id}`);
34
+ }
35
+
36
+ provision(input: ProvisionManagedNumberInput): Promise<ManagedNumber> {
37
+ return this.http.post<ManagedNumber>("/managed-numbers", input);
38
+ }
39
+
40
+ retryVerification(id: string, input?: RetryVerificationInput): Promise<ManagedNumber> {
41
+ return this.http.post<ManagedNumber>(`/managed-numbers/${id}/retry-verification`, input);
42
+ }
43
+
44
+ cancel(id: string): Promise<ManagedNumber> {
45
+ return this.http.post<ManagedNumber>(`/managed-numbers/${id}/cancel`);
46
+ }
47
+ }
@@ -0,0 +1,10 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { SendMessageInput, SendMessageResult } from "../types.js";
3
+
4
+ export class MessagesResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ send(input: SendMessageInput): Promise<SendMessageResult> {
8
+ return this.http.post<SendMessageResult>("/messages", input);
9
+ }
10
+ }
@@ -0,0 +1,18 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { AvailablePlan, OrgPlan, PlansResult, UpdatePlanInput } from "../types.js";
3
+
4
+ export class PlansResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ get(): Promise<PlansResult> {
8
+ return this.http.get<PlansResult>("/plans");
9
+ }
10
+
11
+ update(input: UpdatePlanInput): Promise<OrgPlan> {
12
+ return this.http.put<OrgPlan>("/plans", input);
13
+ }
14
+
15
+ listAvailable(): Promise<AvailablePlan[]> {
16
+ return this.http.get<AvailablePlan[]>("/plans/available");
17
+ }
18
+ }
@@ -0,0 +1,22 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { SmtpConfig, UpsertSmtpConfigInput } from "../types.js";
3
+
4
+ export class SmtpResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ get(): Promise<SmtpConfig> {
8
+ return this.http.get<SmtpConfig>("/smtp-config");
9
+ }
10
+
11
+ upsert(input: UpsertSmtpConfigInput): Promise<SmtpConfig> {
12
+ return this.http.put<SmtpConfig>("/smtp-config", input);
13
+ }
14
+
15
+ delete(): Promise<void> {
16
+ return this.http.delete("/smtp-config");
17
+ }
18
+
19
+ test(to: string): Promise<{ success: boolean; error?: string }> {
20
+ return this.http.post<{ success: boolean; error?: string }>("/smtp-config/test", { to });
21
+ }
22
+ }
@@ -0,0 +1,15 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type { StatisticsParams, StatisticsResult } from "../types.js";
3
+
4
+ export class StatisticsResource {
5
+ constructor(private readonly http: HttpClient) {}
6
+
7
+ get(params?: StatisticsParams): Promise<StatisticsResult> {
8
+ const qs = new URLSearchParams();
9
+ if (params?.from) qs.set("from", params.from);
10
+ if (params?.to) qs.set("to", params.to);
11
+ if (params?.groupBy) qs.set("groupBy", params.groupBy);
12
+ const query = qs.toString();
13
+ return this.http.get<StatisticsResult>(`/statistics${query ? `?${query}` : ""}`);
14
+ }
15
+ }
@@ -0,0 +1,44 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type {
3
+ CreateTemplateInput,
4
+ MessageTemplate,
5
+ MessageType,
6
+ SaveDraftInput,
7
+ UpdateTemplateInput,
8
+ } from "../types.js";
9
+
10
+ export class TemplatesResource {
11
+ constructor(private readonly http: HttpClient) {}
12
+
13
+ list(params?: { type?: MessageType; isActive?: boolean }): Promise<MessageTemplate[]> {
14
+ const qs = new URLSearchParams();
15
+ if (params?.type) qs.set("type", params.type);
16
+ if (params?.isActive !== undefined) qs.set("isActive", String(params.isActive));
17
+ const query = qs.toString();
18
+ return this.http.get<MessageTemplate[]>(`/templates${query ? `?${query}` : ""}`);
19
+ }
20
+
21
+ get(id: string): Promise<MessageTemplate> {
22
+ return this.http.get<MessageTemplate>(`/templates/${id}`);
23
+ }
24
+
25
+ create(input: CreateTemplateInput): Promise<MessageTemplate> {
26
+ return this.http.post<MessageTemplate>("/templates", input);
27
+ }
28
+
29
+ update(id: string, input: UpdateTemplateInput): Promise<MessageTemplate> {
30
+ return this.http.put<MessageTemplate>(`/templates/${id}`, input);
31
+ }
32
+
33
+ saveDraft(id: string, input: SaveDraftInput): Promise<MessageTemplate> {
34
+ return this.http.patch<MessageTemplate>(`/templates/${id}/draft`, input);
35
+ }
36
+
37
+ publish(id: string): Promise<MessageTemplate> {
38
+ return this.http.post<MessageTemplate>(`/templates/${id}/publish`);
39
+ }
40
+
41
+ delete(id: string): Promise<void> {
42
+ return this.http.delete(`/templates/${id}`);
43
+ }
44
+ }
@@ -0,0 +1,37 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type {
3
+ CreateWebhookInput,
4
+ OrgWebhook,
5
+ OrgWebhookWithSecret,
6
+ RotateSecretResult,
7
+ UpdateWebhookInput,
8
+ WebhookDelivery,
9
+ } from "../types.js";
10
+
11
+ export class WebhooksResource {
12
+ constructor(private readonly http: HttpClient) {}
13
+
14
+ list(): Promise<OrgWebhook[]> {
15
+ return this.http.get<OrgWebhook[]>("/webhooks");
16
+ }
17
+
18
+ create(input: CreateWebhookInput): Promise<OrgWebhookWithSecret> {
19
+ return this.http.post<OrgWebhookWithSecret>("/webhooks", input);
20
+ }
21
+
22
+ update(id: string, input: UpdateWebhookInput): Promise<OrgWebhook> {
23
+ return this.http.put<OrgWebhook>(`/webhooks/${id}`, input);
24
+ }
25
+
26
+ delete(id: string): Promise<void> {
27
+ return this.http.delete(`/webhooks/${id}`);
28
+ }
29
+
30
+ listDeliveries(id: string): Promise<WebhookDelivery[]> {
31
+ return this.http.get<WebhookDelivery[]>(`/webhooks/${id}/deliveries`);
32
+ }
33
+
34
+ rotateSecret(id: string): Promise<RotateSecretResult> {
35
+ return this.http.post<RotateSecretResult>(`/webhooks/${id}/rotate-secret`);
36
+ }
37
+ }
@@ -0,0 +1,84 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type {
3
+ ConnectWabaInput,
4
+ ConnectWhatsappNumberInput,
5
+ OrgWaba,
6
+ PhoneNumberStatusResult,
7
+ RegisterWhatsappNumberInput,
8
+ UpdateWhatsappProfileInput,
9
+ WabaHealthResult,
10
+ WhatsappNumber,
11
+ WhatsappNumberProfile,
12
+ } from "../types.js";
13
+
14
+ export class WhatsappNumbersResource {
15
+ constructor(private readonly http: HttpClient) {}
16
+
17
+ // ── WABAs ────────────────────────────────────────────────────────────────
18
+
19
+ listWabas(): Promise<OrgWaba[]> {
20
+ return this.http.get<OrgWaba[]>("/whatsapp/wabas");
21
+ }
22
+
23
+ connectWaba(input: ConnectWabaInput): Promise<OrgWaba> {
24
+ return this.http.post<OrgWaba>("/whatsapp/wabas/connect", input);
25
+ }
26
+
27
+ reconnectWaba(id: string): Promise<OrgWaba> {
28
+ return this.http.post<OrgWaba>(`/whatsapp/wabas/${id}/reconnect`);
29
+ }
30
+
31
+ disconnectWaba(id: string): Promise<void> {
32
+ return this.http.delete(`/whatsapp/wabas/${id}`);
33
+ }
34
+
35
+ getWabaHealth(id: string): Promise<WabaHealthResult> {
36
+ return this.http.get<WabaHealthResult>(`/whatsapp/wabas/${id}/health`);
37
+ }
38
+
39
+ // ── Numbers ──────────────────────────────────────────────────────────────
40
+
41
+ listNumbers(): Promise<WhatsappNumber[]> {
42
+ return this.http.get<WhatsappNumber[]>("/whatsapp/numbers");
43
+ }
44
+
45
+ connectNumber(input: ConnectWhatsappNumberInput): Promise<WhatsappNumber> {
46
+ return this.http.post<WhatsappNumber>("/whatsapp/numbers/connect", input);
47
+ }
48
+
49
+ registerNumber(input: RegisterWhatsappNumberInput): Promise<WhatsappNumber> {
50
+ return this.http.post<WhatsappNumber>("/whatsapp/numbers", input);
51
+ }
52
+
53
+ verifyCode(id: string, code: string): Promise<WhatsappNumber> {
54
+ return this.http.post<WhatsappNumber>(`/whatsapp/numbers/${id}/verify-code`, { code });
55
+ }
56
+
57
+ resendCode(id: string): Promise<void> {
58
+ return this.http.post(`/whatsapp/numbers/${id}/resend-code`);
59
+ }
60
+
61
+ getProfile(id: string): Promise<WhatsappNumberProfile> {
62
+ return this.http.get<WhatsappNumberProfile>(`/whatsapp/numbers/${id}/profile`);
63
+ }
64
+
65
+ updateProfile(id: string, input: UpdateWhatsappProfileInput): Promise<WhatsappNumberProfile> {
66
+ return this.http.patch<WhatsappNumberProfile>(`/whatsapp/numbers/${id}/profile`, input);
67
+ }
68
+
69
+ updateDisplayName(id: string, displayName: string): Promise<WhatsappNumber> {
70
+ return this.http.patch<WhatsappNumber>(`/whatsapp/numbers/${id}`, { displayName });
71
+ }
72
+
73
+ getStatus(id: string): Promise<PhoneNumberStatusResult> {
74
+ return this.http.get<PhoneNumberStatusResult>(`/whatsapp/numbers/${id}/status`);
75
+ }
76
+
77
+ refreshNumbers(): Promise<WhatsappNumber[]> {
78
+ return this.http.post<WhatsappNumber[]>("/whatsapp/numbers/refresh");
79
+ }
80
+
81
+ deleteNumber(id: string): Promise<void> {
82
+ return this.http.delete(`/whatsapp/numbers/${id}`);
83
+ }
84
+ }
@@ -0,0 +1,31 @@
1
+ import type { HttpClient } from "../http.js";
2
+ import type {
3
+ CreateWhatsappTemplateInput,
4
+ SyncWhatsappTemplatesResult,
5
+ UpdateWhatsappTemplateInput,
6
+ WhatsappTemplate,
7
+ } from "../types.js";
8
+
9
+ export class WhatsappTemplatesResource {
10
+ constructor(private readonly http: HttpClient) {}
11
+
12
+ list(): Promise<WhatsappTemplate[]> {
13
+ return this.http.get<WhatsappTemplate[]>("/whatsapp/templates");
14
+ }
15
+
16
+ create(input: CreateWhatsappTemplateInput): Promise<WhatsappTemplate> {
17
+ return this.http.post<WhatsappTemplate>("/whatsapp/templates", input);
18
+ }
19
+
20
+ update(id: string, input: UpdateWhatsappTemplateInput): Promise<WhatsappTemplate> {
21
+ return this.http.put<WhatsappTemplate>(`/whatsapp/templates/${id}`, input);
22
+ }
23
+
24
+ sync(): Promise<SyncWhatsappTemplatesResult> {
25
+ return this.http.post<SyncWhatsappTemplatesResult>("/whatsapp/templates/sync");
26
+ }
27
+
28
+ delete(id: string): Promise<void> {
29
+ return this.http.delete(`/whatsapp/templates/${id}`);
30
+ }
31
+ }
@@ -0,0 +1,112 @@
1
+ import type { TokenResolver } from "./http.js";
2
+
3
+ export interface ServiceAccountOptions {
4
+ /** Geekapps Auth issuer base URL (e.g. https://auth.geekapps.com.br) */
5
+ issuerUrl: string;
6
+ clientId: string;
7
+ clientSecret: string;
8
+ /** Seconds before expiry to proactively refresh. Defaults to 30. */
9
+ refreshBeforeExpirySeconds?: number;
10
+ }
11
+
12
+ interface CachedToken {
13
+ value: string;
14
+ expiresAt: number; // ms epoch
15
+ }
16
+
17
+ /**
18
+ * Fetches a short-lived token from the Geekapps Auth service using
19
+ * client_credentials grant and caches it until near expiry.
20
+ *
21
+ * Tokens are valid for ~7 min. A new one is fetched 30 s before that.
22
+ */
23
+ export class ServiceAccountTokenProvider {
24
+ private readonly issuerUrl: string;
25
+ private readonly clientId: string;
26
+ private readonly clientSecret: string;
27
+ private readonly refreshBeforeMs: number;
28
+ private cached: CachedToken | null = null;
29
+ private inflight: Promise<string> | null = null;
30
+
31
+ constructor(options: ServiceAccountOptions) {
32
+ this.issuerUrl = options.issuerUrl.replace(/\/$/, "");
33
+ this.clientId = options.clientId;
34
+ this.clientSecret = options.clientSecret;
35
+ this.refreshBeforeMs = (options.refreshBeforeExpirySeconds ?? 30) * 1000;
36
+ }
37
+
38
+ /** Returns a valid token, fetching a new one if necessary. */
39
+ getToken(): Promise<string> {
40
+ const now = Date.now();
41
+
42
+ if (this.cached && this.cached.expiresAt - now > this.refreshBeforeMs) {
43
+ return Promise.resolve(this.cached.value);
44
+ }
45
+
46
+ // Deduplicate concurrent calls — only one fetch in flight at a time
47
+ if (this.inflight) return this.inflight;
48
+
49
+ this.inflight = this.fetchToken().finally(() => {
50
+ this.inflight = null;
51
+ });
52
+
53
+ return this.inflight;
54
+ }
55
+
56
+ private async fetchToken(): Promise<string> {
57
+ const body = new URLSearchParams();
58
+ body.set("grant_type", "client_credentials");
59
+ body.set("client_id", this.clientId);
60
+ body.set("client_secret", this.clientSecret);
61
+
62
+ const res = await fetch(`${this.issuerUrl}/auth/token`, {
63
+ method: "POST",
64
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
65
+ body,
66
+ });
67
+
68
+ if (!res.ok) {
69
+ const err = await res.json().catch(() => ({})) as { error?: string };
70
+ throw new Error(
71
+ `ServiceAccount token fetch failed (${res.status}): ${err.error ?? "unknown error"}`,
72
+ );
73
+ }
74
+
75
+ const data = await res.json() as { access_token: string; expires_in?: number };
76
+
77
+ const expiresInMs = (data.expires_in ?? 420) * 1000;
78
+ this.cached = {
79
+ value: data.access_token,
80
+ expiresAt: Date.now() + expiresInMs,
81
+ };
82
+
83
+ return this.cached.value;
84
+ }
85
+
86
+ /** Returns this provider as a TokenResolver to pass directly to PostClient. */
87
+ asTokenResolver(): TokenResolver {
88
+ return () => this.getToken();
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Convenience factory. Returns a TokenResolver ready for use in PostClient.
94
+ *
95
+ * @example
96
+ * ```ts
97
+ * const post = new PostClient({
98
+ * baseUrl: process.env.POST_API_URL!,
99
+ * token: createServiceAccountToken({
100
+ * issuerUrl: process.env.GEEKAPPS_AUTH_ISSUER!,
101
+ * clientId: process.env.GEEKAPPS_SERVICE_ACCOUNT_CLIENT_ID!,
102
+ * clientSecret: process.env.GEEKAPPS_SERVICE_ACCOUNT_CLIENT_SECRET!,
103
+ * }),
104
+ * organizationId: process.env.POST_ORGANIZATION_ID!,
105
+ * });
106
+ * ```
107
+ */
108
+ export function createServiceAccountToken(
109
+ options: ServiceAccountOptions,
110
+ ): TokenResolver {
111
+ return new ServiceAccountTokenProvider(options).asTokenResolver();
112
+ }