@stacksjs/ts-cloud 0.1.2 → 0.1.5

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 (187) hide show
  1. package/README.md +98 -13
  2. package/dist/aws/acm.d.ts +129 -0
  3. package/dist/aws/application-autoscaling.d.ts +282 -0
  4. package/dist/aws/bedrock.d.ts +2292 -0
  5. package/dist/aws/client.d.ts +79 -0
  6. package/dist/aws/cloudformation.d.ts +105 -0
  7. package/dist/aws/cloudfront.d.ts +265 -0
  8. package/dist/aws/cloudwatch-logs.d.ts +48 -0
  9. package/dist/aws/comprehend.d.ts +505 -0
  10. package/dist/aws/connect.d.ts +377 -0
  11. package/dist/aws/deploy-imap.d.ts +14 -0
  12. package/dist/aws/dynamodb.d.ts +176 -0
  13. package/dist/aws/ec2.d.ts +272 -0
  14. package/dist/aws/ecr.d.ts +149 -0
  15. package/dist/aws/ecs.d.ts +162 -0
  16. package/dist/aws/elasticache.d.ts +71 -0
  17. package/dist/aws/elbv2.d.ts +248 -0
  18. package/dist/aws/email.d.ts +175 -0
  19. package/dist/aws/eventbridge.d.ts +142 -0
  20. package/dist/aws/iam.d.ts +638 -0
  21. package/dist/aws/imap-server.d.ts +119 -0
  22. package/{src/aws/index.ts → dist/aws/index.d.ts} +62 -83
  23. package/{src/aws/kendra.ts → dist/aws/kendra.d.ts} +71 -386
  24. package/dist/aws/lambda.d.ts +232 -0
  25. package/dist/aws/opensearch.d.ts +87 -0
  26. package/dist/aws/personalize.d.ts +516 -0
  27. package/dist/aws/polly.d.ts +214 -0
  28. package/dist/aws/rds.d.ts +240 -0
  29. package/dist/aws/rekognition.d.ts +543 -0
  30. package/dist/aws/route53-domains.d.ts +113 -0
  31. package/dist/aws/route53.d.ts +215 -0
  32. package/dist/aws/s3.d.ts +212 -0
  33. package/dist/aws/scheduler.d.ts +140 -0
  34. package/dist/aws/secrets-manager.d.ts +170 -0
  35. package/dist/aws/ses.d.ts +288 -0
  36. package/dist/aws/setup-phone.d.ts +0 -0
  37. package/dist/aws/setup-sms.d.ts +115 -0
  38. package/dist/aws/sms.d.ts +304 -0
  39. package/dist/aws/smtp-server.d.ts +61 -0
  40. package/dist/aws/sns.d.ts +117 -0
  41. package/dist/aws/sqs.d.ts +65 -0
  42. package/dist/aws/ssm.d.ts +179 -0
  43. package/dist/aws/sts.d.ts +15 -0
  44. package/dist/aws/support.d.ts +104 -0
  45. package/dist/aws/test-imap.d.ts +0 -0
  46. package/dist/aws/textract.d.ts +403 -0
  47. package/dist/aws/transcribe.d.ts +60 -0
  48. package/dist/aws/translate.d.ts +358 -0
  49. package/dist/aws/voice.d.ts +219 -0
  50. package/dist/bin/cli.js +1724 -0
  51. package/dist/config.d.ts +7 -0
  52. package/dist/deploy/index.d.ts +2 -0
  53. package/dist/deploy/static-site-external-dns.d.ts +51 -0
  54. package/dist/deploy/static-site.d.ts +71 -0
  55. package/dist/dns/cloudflare.d.ts +52 -0
  56. package/dist/dns/godaddy.d.ts +38 -0
  57. package/dist/dns/index.d.ts +45 -0
  58. package/dist/dns/porkbun.d.ts +18 -0
  59. package/dist/dns/route53-adapter.d.ts +38 -0
  60. package/{src/dns/types.ts → dist/dns/types.d.ts} +26 -63
  61. package/dist/dns/validator.d.ts +78 -0
  62. package/dist/generators/index.d.ts +1 -0
  63. package/dist/generators/infrastructure.d.ts +30 -0
  64. package/{src/index.ts → dist/index.d.ts} +70 -93
  65. package/dist/index.js +7881 -0
  66. package/dist/push/apns.d.ts +60 -0
  67. package/dist/push/fcm.d.ts +117 -0
  68. package/dist/push/index.d.ts +14 -0
  69. package/dist/security/pre-deploy-scanner.d.ts +69 -0
  70. package/dist/ssl/acme-client.d.ts +67 -0
  71. package/dist/ssl/index.d.ts +2 -0
  72. package/dist/ssl/letsencrypt.d.ts +48 -0
  73. package/dist/types.d.ts +1 -0
  74. package/dist/utils/cli.d.ts +123 -0
  75. package/dist/validation/index.d.ts +1 -0
  76. package/dist/validation/template.d.ts +23 -0
  77. package/package.json +8 -8
  78. package/bin/cli.ts +0 -133
  79. package/bin/commands/analytics.ts +0 -328
  80. package/bin/commands/api.ts +0 -379
  81. package/bin/commands/assets.ts +0 -221
  82. package/bin/commands/audit.ts +0 -501
  83. package/bin/commands/backup.ts +0 -682
  84. package/bin/commands/cache.ts +0 -294
  85. package/bin/commands/cdn.ts +0 -281
  86. package/bin/commands/config.ts +0 -202
  87. package/bin/commands/container.ts +0 -105
  88. package/bin/commands/cost.ts +0 -208
  89. package/bin/commands/database.ts +0 -401
  90. package/bin/commands/deploy.ts +0 -674
  91. package/bin/commands/domain.ts +0 -397
  92. package/bin/commands/email.ts +0 -423
  93. package/bin/commands/environment.ts +0 -285
  94. package/bin/commands/events.ts +0 -424
  95. package/bin/commands/firewall.ts +0 -145
  96. package/bin/commands/function.ts +0 -116
  97. package/bin/commands/generate.ts +0 -280
  98. package/bin/commands/git.ts +0 -139
  99. package/bin/commands/iam.ts +0 -464
  100. package/bin/commands/index.ts +0 -48
  101. package/bin/commands/init.ts +0 -120
  102. package/bin/commands/logs.ts +0 -148
  103. package/bin/commands/network.ts +0 -579
  104. package/bin/commands/notify.ts +0 -489
  105. package/bin/commands/queue.ts +0 -407
  106. package/bin/commands/scheduler.ts +0 -370
  107. package/bin/commands/secrets.ts +0 -54
  108. package/bin/commands/server.ts +0 -629
  109. package/bin/commands/shared.ts +0 -97
  110. package/bin/commands/ssl.ts +0 -138
  111. package/bin/commands/stack.ts +0 -325
  112. package/bin/commands/status.ts +0 -385
  113. package/bin/commands/storage.ts +0 -450
  114. package/bin/commands/team.ts +0 -96
  115. package/bin/commands/tunnel.ts +0 -489
  116. package/bin/commands/utils.ts +0 -202
  117. package/build.ts +0 -15
  118. package/cloud +0 -2
  119. package/src/aws/acm.ts +0 -768
  120. package/src/aws/application-autoscaling.ts +0 -845
  121. package/src/aws/bedrock.ts +0 -4074
  122. package/src/aws/client.ts +0 -878
  123. package/src/aws/cloudformation.ts +0 -896
  124. package/src/aws/cloudfront.ts +0 -1531
  125. package/src/aws/cloudwatch-logs.ts +0 -154
  126. package/src/aws/comprehend.ts +0 -839
  127. package/src/aws/connect.ts +0 -1056
  128. package/src/aws/deploy-imap.ts +0 -384
  129. package/src/aws/dynamodb.ts +0 -340
  130. package/src/aws/ec2.ts +0 -1385
  131. package/src/aws/ecr.ts +0 -621
  132. package/src/aws/ecs.ts +0 -615
  133. package/src/aws/elasticache.ts +0 -301
  134. package/src/aws/elbv2.ts +0 -942
  135. package/src/aws/email.ts +0 -928
  136. package/src/aws/eventbridge.ts +0 -248
  137. package/src/aws/iam.ts +0 -1689
  138. package/src/aws/imap-server.ts +0 -2100
  139. package/src/aws/lambda.ts +0 -786
  140. package/src/aws/opensearch.ts +0 -158
  141. package/src/aws/personalize.ts +0 -977
  142. package/src/aws/polly.ts +0 -559
  143. package/src/aws/rds.ts +0 -888
  144. package/src/aws/rekognition.ts +0 -846
  145. package/src/aws/route53-domains.ts +0 -359
  146. package/src/aws/route53.ts +0 -1046
  147. package/src/aws/s3.ts +0 -2318
  148. package/src/aws/scheduler.ts +0 -571
  149. package/src/aws/secrets-manager.ts +0 -769
  150. package/src/aws/ses.ts +0 -1081
  151. package/src/aws/setup-phone.ts +0 -104
  152. package/src/aws/setup-sms.ts +0 -580
  153. package/src/aws/sms.ts +0 -1735
  154. package/src/aws/smtp-server.ts +0 -531
  155. package/src/aws/sns.ts +0 -758
  156. package/src/aws/sqs.ts +0 -382
  157. package/src/aws/ssm.ts +0 -807
  158. package/src/aws/sts.ts +0 -92
  159. package/src/aws/support.ts +0 -391
  160. package/src/aws/test-imap.ts +0 -86
  161. package/src/aws/textract.ts +0 -780
  162. package/src/aws/transcribe.ts +0 -108
  163. package/src/aws/translate.ts +0 -641
  164. package/src/aws/voice.ts +0 -1379
  165. package/src/config.ts +0 -35
  166. package/src/deploy/index.ts +0 -7
  167. package/src/deploy/static-site-external-dns.ts +0 -906
  168. package/src/deploy/static-site.ts +0 -1125
  169. package/src/dns/godaddy.ts +0 -412
  170. package/src/dns/index.ts +0 -183
  171. package/src/dns/porkbun.ts +0 -362
  172. package/src/dns/route53-adapter.ts +0 -414
  173. package/src/dns/validator.ts +0 -369
  174. package/src/generators/index.ts +0 -5
  175. package/src/generators/infrastructure.ts +0 -1660
  176. package/src/push/apns.ts +0 -452
  177. package/src/push/fcm.ts +0 -506
  178. package/src/push/index.ts +0 -58
  179. package/src/ssl/acme-client.ts +0 -478
  180. package/src/ssl/index.ts +0 -7
  181. package/src/ssl/letsencrypt.ts +0 -747
  182. package/src/types.ts +0 -2
  183. package/src/utils/cli.ts +0 -398
  184. package/src/validation/index.ts +0 -5
  185. package/src/validation/template.ts +0 -405
  186. package/test/index.test.ts +0 -128
  187. package/tsconfig.json +0 -18
package/src/push/fcm.ts DELETED
@@ -1,506 +0,0 @@
1
- /**
2
- * Firebase Cloud Messaging (FCM) Client
3
- * Uses FCM HTTP v1 API with Google OAuth2 authentication
4
- *
5
- * Prerequisites:
6
- * - Firebase project
7
- * - Service account JSON key from Firebase Console
8
- *
9
- * @example
10
- * ```ts
11
- * const fcm = new FCMClient({
12
- * projectId: 'your-project-id',
13
- * clientEmail: 'firebase-adminsdk@project.iam.gserviceaccount.com',
14
- * privateKey: '-----BEGIN PRIVATE KEY-----\n...',
15
- * })
16
- *
17
- * await fcm.send({
18
- * token: '...',
19
- * title: 'Hello',
20
- * body: 'World',
21
- * })
22
- * ```
23
- */
24
-
25
- import { createSign } from 'node:crypto'
26
-
27
- export interface FCMConfig {
28
- /** Firebase project ID */
29
- projectId: string
30
- /** Service account client email */
31
- clientEmail: string
32
- /** Service account private key (PEM format) */
33
- privateKey: string
34
- }
35
-
36
- export interface FCMNotification {
37
- /** Device FCM token */
38
- token?: string
39
- /** Topic to send to (instead of token) */
40
- topic?: string
41
- /** Condition expression for targeting multiple topics */
42
- condition?: string
43
- /** Notification title */
44
- title?: string
45
- /** Notification body */
46
- body?: string
47
- /** Notification image URL */
48
- imageUrl?: string
49
- /** Custom data payload */
50
- data?: Record<string, string>
51
- /** Android-specific options */
52
- android?: {
53
- /** Channel ID for Android O+ */
54
- channelId?: string
55
- /** Notification priority */
56
- priority?: 'normal' | 'high'
57
- /** Time to live in seconds */
58
- ttl?: number
59
- /** Collapse key for message deduplication */
60
- collapseKey?: string
61
- /** Notification icon */
62
- icon?: string
63
- /** Notification icon color (hex) */
64
- color?: string
65
- /** Sound to play */
66
- sound?: string
67
- /** Click action */
68
- clickAction?: string
69
- /** Tag for notification replacement */
70
- tag?: string
71
- /** Direct boot aware */
72
- directBootOk?: boolean
73
- /** Visibility: private, public, secret */
74
- visibility?: 'private' | 'public' | 'secret'
75
- /** Notification count */
76
- notificationCount?: number
77
- }
78
- /** Web push options */
79
- webpush?: {
80
- /** Web notification options */
81
- notification?: {
82
- title?: string
83
- body?: string
84
- icon?: string
85
- badge?: string
86
- image?: string
87
- requireInteraction?: boolean
88
- silent?: boolean
89
- tag?: string
90
- actions?: Array<{ action: string; title: string; icon?: string }>
91
- }
92
- /** FCM options for web */
93
- fcmOptions?: {
94
- link?: string
95
- analyticsLabel?: string
96
- }
97
- /** Custom headers */
98
- headers?: Record<string, string>
99
- /** Custom data */
100
- data?: Record<string, string>
101
- }
102
- /** APNS options (for iOS via FCM) */
103
- apns?: {
104
- /** APNs headers */
105
- headers?: Record<string, string>
106
- /** APNs payload */
107
- payload?: {
108
- aps?: Record<string, any>
109
- [key: string]: any
110
- }
111
- /** FCM options */
112
- fcmOptions?: {
113
- analyticsLabel?: string
114
- image?: string
115
- }
116
- }
117
- /** FCM options */
118
- fcmOptions?: {
119
- analyticsLabel?: string
120
- }
121
- }
122
-
123
- export interface FCMSendResult {
124
- success: boolean
125
- messageId?: string
126
- error?: string
127
- errorCode?: string
128
- }
129
-
130
- export interface FCMBatchResult {
131
- sent: number
132
- failed: number
133
- results: Array<FCMSendResult & { token?: string }>
134
- }
135
-
136
- const FCM_API_URL = 'https://fcm.googleapis.com/v1/projects'
137
- const GOOGLE_TOKEN_URL = 'https://oauth2.googleapis.com/token'
138
- const TOKEN_EXPIRY_MS = 55 * 60 * 1000 // 55 minutes (tokens valid for 1 hour)
139
-
140
- /**
141
- * Firebase Cloud Messaging client
142
- */
143
- export class FCMClient {
144
- private config: FCMConfig
145
- private accessToken: string | null = null
146
- private tokenExpiresAt: number = 0
147
-
148
- constructor(config: FCMConfig) {
149
- this.config = config
150
- }
151
-
152
- /**
153
- * Load config from service account JSON
154
- */
155
- static fromServiceAccount(serviceAccount: {
156
- project_id: string
157
- client_email: string
158
- private_key: string
159
- }): FCMClient {
160
- return new FCMClient({
161
- projectId: serviceAccount.project_id,
162
- clientEmail: serviceAccount.client_email,
163
- privateKey: serviceAccount.private_key,
164
- })
165
- }
166
-
167
- /**
168
- * Generate a JWT for Google OAuth2
169
- */
170
- private generateJWT(): string {
171
- const now = Math.floor(Date.now() / 1000)
172
- const exp = now + 3600 // 1 hour
173
-
174
- const header = {
175
- alg: 'RS256',
176
- typ: 'JWT',
177
- }
178
-
179
- const payload = {
180
- iss: this.config.clientEmail,
181
- sub: this.config.clientEmail,
182
- aud: GOOGLE_TOKEN_URL,
183
- iat: now,
184
- exp,
185
- scope: 'https://www.googleapis.com/auth/firebase.messaging',
186
- }
187
-
188
- const encodedHeader = Buffer.from(JSON.stringify(header)).toString('base64url')
189
- const encodedPayload = Buffer.from(JSON.stringify(payload)).toString('base64url')
190
- const signatureInput = `${encodedHeader}.${encodedPayload}`
191
-
192
- const sign = createSign('SHA256')
193
- sign.update(signatureInput)
194
- const signature = sign.sign(this.config.privateKey, 'base64url')
195
-
196
- return `${signatureInput}.${signature}`
197
- }
198
-
199
- /**
200
- * Get a valid access token, refreshing if needed
201
- */
202
- private async getAccessToken(): Promise<string> {
203
- if (this.accessToken && Date.now() < this.tokenExpiresAt) {
204
- return this.accessToken
205
- }
206
-
207
- const jwt = this.generateJWT()
208
-
209
- const response = await fetch(GOOGLE_TOKEN_URL, {
210
- method: 'POST',
211
- headers: {
212
- 'Content-Type': 'application/x-www-form-urlencoded',
213
- },
214
- body: new URLSearchParams({
215
- grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
216
- assertion: jwt,
217
- }).toString(),
218
- })
219
-
220
- if (!response.ok) {
221
- const errorText = await response.text()
222
- throw new Error(`Failed to get access token: ${errorText}`)
223
- }
224
-
225
- const data = await response.json() as Record<string, any>
226
- this.accessToken = data.access_token
227
- this.tokenExpiresAt = Date.now() + TOKEN_EXPIRY_MS
228
-
229
- return this.accessToken!
230
- }
231
-
232
- /**
233
- * Build FCM message payload
234
- */
235
- private buildMessage(notification: FCMNotification): object {
236
- const message: Record<string, any> = {}
237
-
238
- // Target (one of: token, topic, condition)
239
- if (notification.token) {
240
- message.token = notification.token
241
- } else if (notification.topic) {
242
- message.topic = notification.topic
243
- } else if (notification.condition) {
244
- message.condition = notification.condition
245
- }
246
-
247
- // Notification payload
248
- if (notification.title || notification.body || notification.imageUrl) {
249
- message.notification = {}
250
- if (notification.title) message.notification.title = notification.title
251
- if (notification.body) message.notification.body = notification.body
252
- if (notification.imageUrl) message.notification.image = notification.imageUrl
253
- }
254
-
255
- // Data payload
256
- if (notification.data && Object.keys(notification.data).length > 0) {
257
- message.data = notification.data
258
- }
259
-
260
- // Android options
261
- if (notification.android) {
262
- message.android = {
263
- priority: notification.android.priority || 'high',
264
- }
265
-
266
- if (notification.android.ttl) {
267
- message.android.ttl = `${notification.android.ttl}s`
268
- }
269
-
270
- if (notification.android.collapseKey) {
271
- message.android.collapse_key = notification.android.collapseKey
272
- }
273
-
274
- if (notification.android.directBootOk) {
275
- message.android.direct_boot_ok = notification.android.directBootOk
276
- }
277
-
278
- // Android notification
279
- const androidNotification: Record<string, any> = {}
280
- if (notification.android.channelId) androidNotification.channel_id = notification.android.channelId
281
- if (notification.android.icon) androidNotification.icon = notification.android.icon
282
- if (notification.android.color) androidNotification.color = notification.android.color
283
- if (notification.android.sound) androidNotification.sound = notification.android.sound
284
- if (notification.android.clickAction) androidNotification.click_action = notification.android.clickAction
285
- if (notification.android.tag) androidNotification.tag = notification.android.tag
286
- if (notification.android.visibility) androidNotification.visibility = notification.android.visibility
287
- if (notification.android.notificationCount !== undefined) {
288
- androidNotification.notification_count = notification.android.notificationCount
289
- }
290
-
291
- if (Object.keys(androidNotification).length > 0) {
292
- message.android.notification = androidNotification
293
- }
294
- }
295
-
296
- // Web push options
297
- if (notification.webpush) {
298
- message.webpush = notification.webpush
299
- }
300
-
301
- // APNS options (iOS)
302
- if (notification.apns) {
303
- message.apns = notification.apns
304
- }
305
-
306
- // FCM options
307
- if (notification.fcmOptions) {
308
- message.fcm_options = notification.fcmOptions
309
- }
310
-
311
- return { message }
312
- }
313
-
314
- /**
315
- * Send a push notification
316
- */
317
- async send(notification: FCMNotification): Promise<FCMSendResult> {
318
- try {
319
- const accessToken = await this.getAccessToken()
320
- const payload = this.buildMessage(notification)
321
-
322
- const response = await fetch(
323
- `${FCM_API_URL}/${this.config.projectId}/messages:send`,
324
- {
325
- method: 'POST',
326
- headers: {
327
- 'Authorization': `Bearer ${accessToken}`,
328
- 'Content-Type': 'application/json',
329
- },
330
- body: JSON.stringify(payload),
331
- }
332
- )
333
-
334
- const data = await response.json() as Record<string, any>
335
-
336
- if (response.ok) {
337
- return {
338
- success: true,
339
- messageId: data.name,
340
- }
341
- } else {
342
- return {
343
- success: false,
344
- error: data.error?.message || 'Unknown error',
345
- errorCode: data.error?.status,
346
- }
347
- }
348
- } catch (error: any) {
349
- return {
350
- success: false,
351
- error: error.message,
352
- }
353
- }
354
- }
355
-
356
- /**
357
- * Send to multiple device tokens
358
- */
359
- async sendBatch(
360
- tokens: string[],
361
- notification: Omit<FCMNotification, 'token' | 'topic' | 'condition'>,
362
- options?: { concurrency?: number }
363
- ): Promise<FCMBatchResult> {
364
- const concurrency = options?.concurrency || 10
365
- const results: Array<FCMSendResult & { token?: string }> = []
366
-
367
- // Process in batches
368
- for (let i = 0; i < tokens.length; i += concurrency) {
369
- const batch = tokens.slice(i, i + concurrency)
370
- const batchPromises = batch.map(async (token) => {
371
- const result = await this.send({ ...notification, token })
372
- return { ...result, token }
373
- })
374
- const batchResults = await Promise.all(batchPromises)
375
- results.push(...batchResults)
376
- }
377
-
378
- return {
379
- sent: results.filter(r => r.success).length,
380
- failed: results.filter(r => !r.success).length,
381
- results,
382
- }
383
- }
384
-
385
- /**
386
- * Send to a topic
387
- */
388
- async sendToTopic(
389
- topic: string,
390
- notification: Omit<FCMNotification, 'token' | 'topic' | 'condition'>
391
- ): Promise<FCMSendResult> {
392
- return this.send({ ...notification, topic })
393
- }
394
-
395
- /**
396
- * Send to topics with a condition
397
- * @example sendToCondition("'TopicA' in topics && 'TopicB' in topics", {...})
398
- */
399
- async sendToCondition(
400
- condition: string,
401
- notification: Omit<FCMNotification, 'token' | 'topic' | 'condition'>
402
- ): Promise<FCMSendResult> {
403
- return this.send({ ...notification, condition })
404
- }
405
-
406
- /**
407
- * Send a simple notification (convenience method)
408
- */
409
- async sendSimple(
410
- token: string,
411
- title: string,
412
- body: string,
413
- data?: Record<string, string>
414
- ): Promise<FCMSendResult> {
415
- return this.send({
416
- token,
417
- title,
418
- body,
419
- data,
420
- })
421
- }
422
-
423
- /**
424
- * Send a data-only (silent) notification
425
- */
426
- async sendSilent(
427
- token: string,
428
- data: Record<string, string>
429
- ): Promise<FCMSendResult> {
430
- return this.send({
431
- token,
432
- data,
433
- android: {
434
- priority: 'high',
435
- },
436
- })
437
- }
438
-
439
- /**
440
- * Subscribe a token to a topic
441
- */
442
- async subscribeToTopic(tokens: string[], topic: string): Promise<{ success: boolean; error?: string }> {
443
- try {
444
- const accessToken = await this.getAccessToken()
445
-
446
- const response = await fetch(
447
- `https://iid.googleapis.com/iid/v1:batchAdd`,
448
- {
449
- method: 'POST',
450
- headers: {
451
- 'Authorization': `Bearer ${accessToken}`,
452
- 'Content-Type': 'application/json',
453
- },
454
- body: JSON.stringify({
455
- to: `/topics/${topic}`,
456
- registration_tokens: tokens,
457
- }),
458
- }
459
- )
460
-
461
- if (response.ok) {
462
- return { success: true }
463
- } else {
464
- const data = await response.json() as Record<string, any>
465
- return { success: false, error: data.error?.message || 'Failed to subscribe' }
466
- }
467
- } catch (error: any) {
468
- return { success: false, error: error.message }
469
- }
470
- }
471
-
472
- /**
473
- * Unsubscribe a token from a topic
474
- */
475
- async unsubscribeFromTopic(tokens: string[], topic: string): Promise<{ success: boolean; error?: string }> {
476
- try {
477
- const accessToken = await this.getAccessToken()
478
-
479
- const response = await fetch(
480
- `https://iid.googleapis.com/iid/v1:batchRemove`,
481
- {
482
- method: 'POST',
483
- headers: {
484
- 'Authorization': `Bearer ${accessToken}`,
485
- 'Content-Type': 'application/json',
486
- },
487
- body: JSON.stringify({
488
- to: `/topics/${topic}`,
489
- registration_tokens: tokens,
490
- }),
491
- }
492
- )
493
-
494
- if (response.ok) {
495
- return { success: true }
496
- } else {
497
- const data = await response.json() as Record<string, any>
498
- return { success: false, error: data.error?.message || 'Failed to unsubscribe' }
499
- }
500
- } catch (error: any) {
501
- return { success: false, error: error.message }
502
- }
503
- }
504
- }
505
-
506
- export default FCMClient
package/src/push/index.ts DELETED
@@ -1,58 +0,0 @@
1
- /**
2
- * Push Notifications Module
3
- *
4
- * Provides clients for Apple Push Notification Service (APNs) and
5
- * Firebase Cloud Messaging (FCM).
6
- *
7
- * @example
8
- * ```ts
9
- * // Apple Push Notifications
10
- * import { APNsClient } from 'ts-cloud/push'
11
- *
12
- * const apns = new APNsClient({
13
- * keyId: 'ABC123DEFG',
14
- * teamId: 'DEF456GHIJ',
15
- * privateKey: fs.readFileSync('AuthKey.p8', 'utf8'),
16
- * bundleId: 'com.example.app',
17
- * })
18
- *
19
- * await apns.send({
20
- * deviceToken: '...',
21
- * title: 'Hello',
22
- * body: 'World',
23
- * })
24
- *
25
- * // Firebase Cloud Messaging
26
- * import { FCMClient } from 'ts-cloud/push'
27
- *
28
- * const fcm = new FCMClient({
29
- * projectId: 'your-project-id',
30
- * clientEmail: 'firebase-adminsdk@project.iam.gserviceaccount.com',
31
- * privateKey: '-----BEGIN PRIVATE KEY-----\n...',
32
- * })
33
- *
34
- * await fcm.send({
35
- * token: '...',
36
- * title: 'Hello',
37
- * body: 'World',
38
- * })
39
- * ```
40
- */
41
-
42
- export * from './apns'
43
- export * from './fcm'
44
-
45
- // Re-export types for convenience
46
- export type {
47
- APNsConfig,
48
- APNsNotification,
49
- APNsSendResult,
50
- APNsBatchResult,
51
- } from './apns'
52
-
53
- export type {
54
- FCMConfig,
55
- FCMNotification,
56
- FCMSendResult,
57
- FCMBatchResult,
58
- } from './fcm'