spectrum-ts 0.1.1 → 0.2.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.
@@ -1 +1,147 @@
1
1
  export const SPECTRUM_CLOUD_URL = `https://${process.env.SPECTRUM_CLOUD_URL ?? "spectrum-cloud.photon.codes"}`;
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // API response types (aligned with OpenAPI spec)
5
+ // ---------------------------------------------------------------------------
6
+
7
+ export type SubscriptionStatus = "active" | "canceled" | "past_due";
8
+
9
+ export interface SubscriptionData {
10
+ status: SubscriptionStatus | null;
11
+ tier: string;
12
+ }
13
+
14
+ export interface SharedTokenData {
15
+ expiresIn: number;
16
+ token: string;
17
+ type: "shared";
18
+ }
19
+
20
+ export interface DedicatedTokenData {
21
+ auth: Record<string, string>;
22
+ expiresIn: number;
23
+ type: "dedicated";
24
+ }
25
+
26
+ export type TokenData = SharedTokenData | DedicatedTokenData;
27
+
28
+ export type CloudPlatform = "imessage" | "whatsapp_business";
29
+
30
+ export interface PlatformStatus {
31
+ enabled: boolean;
32
+ }
33
+
34
+ export type PlatformsData = Record<CloudPlatform, PlatformStatus>;
35
+
36
+ export interface ImessageInfoData {
37
+ type: "shared" | "dedicated";
38
+ }
39
+
40
+ // ---------------------------------------------------------------------------
41
+ // Error
42
+ // ---------------------------------------------------------------------------
43
+
44
+ export class SpectrumCloudError extends Error {
45
+ readonly status: number;
46
+ readonly code: string;
47
+
48
+ constructor(status: number, code: string, message: string) {
49
+ super(message);
50
+ this.name = "SpectrumCloudError";
51
+ this.status = status;
52
+ this.code = code;
53
+ }
54
+ }
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Internal helpers
58
+ // ---------------------------------------------------------------------------
59
+
60
+ interface SuccessResponse<T> {
61
+ data: T;
62
+ succeed: true;
63
+ }
64
+
65
+ interface ErrorBody {
66
+ code: string;
67
+ message: string;
68
+ succeed: false;
69
+ }
70
+
71
+ const request = async <T>(path: string, init?: RequestInit): Promise<T> => {
72
+ const response = await fetch(`${SPECTRUM_CLOUD_URL}${path}`, init);
73
+
74
+ if (!response.ok) {
75
+ const body = await response.text().catch(() => "");
76
+ try {
77
+ const parsed = JSON.parse(body) as ErrorBody;
78
+ throw new SpectrumCloudError(
79
+ response.status,
80
+ parsed.code,
81
+ parsed.message
82
+ );
83
+ } catch (error) {
84
+ if (error instanceof SpectrumCloudError) {
85
+ throw error;
86
+ }
87
+ throw new SpectrumCloudError(
88
+ response.status,
89
+ "UNKNOWN",
90
+ body || response.statusText
91
+ );
92
+ }
93
+ }
94
+
95
+ const json = (await response.json()) as SuccessResponse<T>;
96
+ if (!json.succeed) {
97
+ throw new SpectrumCloudError(
98
+ response.status,
99
+ "UNKNOWN",
100
+ "Server returned succeed=false"
101
+ );
102
+ }
103
+
104
+ return json.data;
105
+ };
106
+
107
+ const basicAuth = (projectId: string, projectSecret: string): string =>
108
+ `Basic ${btoa(`${projectId}:${projectSecret}`)}`;
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Cloud API client
112
+ // ---------------------------------------------------------------------------
113
+
114
+ export const cloud = {
115
+ getSubscription: (projectId: string): Promise<SubscriptionData> =>
116
+ request(`/projects/${projectId}/billing/subscription`),
117
+
118
+ issueImessageTokens: (
119
+ projectId: string,
120
+ projectSecret: string
121
+ ): Promise<TokenData> =>
122
+ request(`/projects/${projectId}/imessage/tokens`, {
123
+ method: "POST",
124
+ headers: { Authorization: basicAuth(projectId, projectSecret) },
125
+ }),
126
+
127
+ getImessageInfo: (projectId: string): Promise<ImessageInfoData> =>
128
+ request(`/projects/${projectId}/imessage/`),
129
+
130
+ getPlatforms: (projectId: string): Promise<PlatformsData> =>
131
+ request(`/projects/${projectId}/platforms/`),
132
+
133
+ togglePlatform: (
134
+ projectId: string,
135
+ projectSecret: string,
136
+ platform: CloudPlatform,
137
+ enabled: boolean
138
+ ): Promise<PlatformsData> =>
139
+ request(`/projects/${projectId}/platforms/`, {
140
+ method: "PATCH",
141
+ headers: {
142
+ Authorization: basicAuth(projectId, projectSecret),
143
+ "Content-Type": "application/json",
144
+ },
145
+ body: JSON.stringify({ platform, enabled }),
146
+ }),
147
+ };