@stacksjs/ts-cloud 0.9.3 → 0.9.4

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 (143) hide show
  1. package/dist/aws/index.js +1 -269
  2. package/dist/bin/chunk-00kg80qg.js +1 -0
  3. package/dist/bin/{chunk-hzqw8xm5.js → chunk-1k5kszjp.js} +1 -1
  4. package/dist/bin/{chunk-9v39615t.js → chunk-21e0mavm.js} +1 -1
  5. package/dist/bin/{chunk-waayf9ay.js → chunk-2empps47.js} +1 -1
  6. package/dist/bin/{chunk-14cwr6eh.js → chunk-3vqfexc4.js} +1 -1
  7. package/dist/bin/chunk-5ectjq0b.js +1 -0
  8. package/dist/bin/{chunk-b5gd39s8.js → chunk-5erkxpt7.js} +4 -4
  9. package/dist/bin/{chunk-41x17hw1.js → chunk-5mrtzemj.js} +1 -1
  10. package/dist/bin/{chunk-p8q9bq9g.js → chunk-5n9fmabb.js} +1 -1
  11. package/dist/bin/{chunk-gqf6jsmy.js → chunk-9knpg30y.js} +1 -1
  12. package/dist/bin/{chunk-r3kv0vm9.js → chunk-ddk4rt4j.js} +1 -1
  13. package/dist/bin/{chunk-avm7tnwe.js → chunk-e0rkrq70.js} +1 -1
  14. package/dist/bin/{chunk-ry030a6b.js → chunk-etrb03mt.js} +1 -1
  15. package/dist/bin/{chunk-8v7ddyvf.js → chunk-k9t9wvms.js} +1 -1
  16. package/dist/bin/{chunk-92mea34a.js → chunk-m7dgskt1.js} +1 -1
  17. package/dist/bin/{chunk-3r4fb59r.js → chunk-mz0wbbsj.js} +1 -1
  18. package/dist/bin/{chunk-b9qbp8j1.js → chunk-qk9qgepa.js} +1 -1
  19. package/dist/bin/chunk-rxcvf10f.js +7364 -0
  20. package/dist/bin/{chunk-r9hjwcj9.js → chunk-tga3hhwk.js} +1 -1
  21. package/dist/bin/{chunk-ynjvbphf.js → chunk-tx0tqq2k.js} +1 -1
  22. package/dist/bin/{chunk-57y1zxbf.js → chunk-vm3q5gf2.js} +1 -1
  23. package/dist/bin/{chunk-bz828v8q.js → chunk-y7s5r8y6.js} +1 -1
  24. package/dist/bin/{chunk-sgyffpgm.js → chunk-zmegvjp8.js} +1 -1
  25. package/dist/bin/cli.js +14 -14
  26. package/dist/bin/dashboard-server.js +1 -1
  27. package/dist/chunk-0ccta6z6.js +6 -0
  28. package/dist/chunk-0k1cs6pp.js +1 -0
  29. package/dist/chunk-1egjn203.js +704 -0
  30. package/dist/chunk-2wx29qga.js +5 -0
  31. package/dist/chunk-5m5rqmv7.js +1 -0
  32. package/dist/chunk-8ea5022g.js +114 -0
  33. package/dist/chunk-8xqn3c0w.js +2 -0
  34. package/dist/chunk-b4esxhmw.js +2 -0
  35. package/dist/chunk-b8e5wzwn.js +44 -0
  36. package/dist/chunk-bggt4n6e.js +2 -0
  37. package/dist/chunk-cwkg37rs.js +37 -0
  38. package/dist/chunk-dskvqt67.js +7355 -0
  39. package/dist/chunk-gahsdmxf.js +1617 -0
  40. package/dist/chunk-gnv3r2jg.js +1 -0
  41. package/dist/chunk-hg3c48cp.js +34 -0
  42. package/dist/chunk-m5azeva3.js +2 -0
  43. package/dist/chunk-r3qf56b3.js +92 -0
  44. package/dist/chunk-sdqa9ghv.js +141 -0
  45. package/dist/chunk-svrvvcm7.js +1 -0
  46. package/dist/chunk-v0p3hpc3.js +60 -0
  47. package/dist/chunk-wdzjbecg.js +50 -0
  48. package/dist/chunk-ww8k3g7j.js +1 -0
  49. package/dist/chunk-xmqfc62w.js +1 -0
  50. package/dist/chunk-xrebj679.js +435 -0
  51. package/dist/chunk-xt3s24vr.js +2 -0
  52. package/dist/chunk-y21zk0pn.js +4 -0
  53. package/dist/deploy/index.js +1 -168
  54. package/dist/dns/index.js +1 -41
  55. package/dist/drivers/index.js +1 -154
  56. package/dist/index.js +100 -6129
  57. package/dist/protection/index.js +1 -89
  58. package/dist/push/index.js +1 -509
  59. package/dist/spend/index.js +1 -173
  60. package/dist/ui/404.html +1 -1
  61. package/dist/ui/accept-invitation.html +1 -1
  62. package/dist/ui/access-denied.html +1 -1
  63. package/dist/ui/account/automation.html +6 -6
  64. package/dist/ui/account/security.html +2 -2
  65. package/dist/ui/applications/compose.html +6 -6
  66. package/dist/ui/applications/new.html +2 -2
  67. package/dist/ui/data/backups.html +5 -5
  68. package/dist/ui/data/services.html +5 -5
  69. package/dist/ui/data/volumes.html +6 -6
  70. package/dist/ui/index.html +6 -6
  71. package/dist/ui/infrastructure/topology.html +5 -5
  72. package/dist/ui/integrations.html +1 -1
  73. package/dist/ui/operations/alerts.html +5 -5
  74. package/dist/ui/operations/configuration.html +5 -5
  75. package/dist/ui/operations/jobs.html +5 -5
  76. package/dist/ui/operations/maintenance.html +5 -5
  77. package/dist/ui/operations/observability.html +6 -6
  78. package/dist/ui/operations/previews.html +6 -6
  79. package/dist/ui/operations/queue.html +6 -6
  80. package/dist/ui/operations/regions.html +6 -6
  81. package/dist/ui/operations/releases.html +6 -6
  82. package/dist/ui/operations/spend.html +6 -6
  83. package/dist/ui/operations/workloads.html +6 -6
  84. package/dist/ui/security.html +1 -1
  85. package/dist/ui/server/actions.html +5 -5
  86. package/dist/ui/server/activity.html +1 -1
  87. package/dist/ui/server/capacity.html +6 -6
  88. package/dist/ui/server/database.html +6 -6
  89. package/dist/ui/server/deployments.html +6 -6
  90. package/dist/ui/server/diagnostics.html +2 -2
  91. package/dist/ui/server/firewall.html +6 -6
  92. package/dist/ui/server/fleet.html +6 -6
  93. package/dist/ui/server/logs.html +6 -6
  94. package/dist/ui/server/metrics.html +6 -6
  95. package/dist/ui/server/security.html +2 -2
  96. package/dist/ui/server/services.html +1 -1
  97. package/dist/ui/server/sites.html +6 -6
  98. package/dist/ui/server/ssh-keys.html +6 -6
  99. package/dist/ui/server/team.html +6 -6
  100. package/dist/ui/server/terminal.html +1 -1
  101. package/dist/ui/serverless/alarms.html +5 -5
  102. package/dist/ui/serverless/assets.html +2 -2
  103. package/dist/ui/serverless/cost.html +1 -1
  104. package/dist/ui/serverless/data.html +6 -6
  105. package/dist/ui/serverless/deployments.html +2 -2
  106. package/dist/ui/serverless/firewall.html +1 -1
  107. package/dist/ui/serverless/functions.html +6 -6
  108. package/dist/ui/serverless/logs.html +6 -6
  109. package/dist/ui/serverless/metrics.html +2 -2
  110. package/dist/ui/serverless/queues.html +6 -6
  111. package/dist/ui/serverless/secrets.html +6 -6
  112. package/dist/ui/serverless/traces.html +6 -6
  113. package/dist/ui/serverless.html +5 -5
  114. package/package.json +3 -3
  115. package/dist/bin/chunk-jpjamjey.js +0 -6935
  116. package/dist/bin/chunk-m2zwtapr.js +0 -1
  117. package/dist/bin/chunk-rtczra13.js +0 -1
  118. package/dist/chunk-01d86gt1.js +0 -1324
  119. package/dist/chunk-050r7ycy.js +0 -46516
  120. package/dist/chunk-1c8dbv57.js +0 -7278
  121. package/dist/chunk-29rse4p1.js +0 -12203
  122. package/dist/chunk-32e7ya18.js +0 -642
  123. package/dist/chunk-4cjrg98a.js +0 -597
  124. package/dist/chunk-50jpda9q.js +0 -371
  125. package/dist/chunk-6a1t7fnq.js +0 -12121
  126. package/dist/chunk-728jvrr0.js +0 -1701
  127. package/dist/chunk-7m60qnc8.js +0 -1762
  128. package/dist/chunk-aa2dkn7b.js +0 -205
  129. package/dist/chunk-d48vtdj4.js +0 -433
  130. package/dist/chunk-f55nkpvb.js +0 -8
  131. package/dist/chunk-fgk8cqew.js +0 -152
  132. package/dist/chunk-he9a874b.js +0 -769
  133. package/dist/chunk-k2yyatfw.js +0 -10
  134. package/dist/chunk-k4px0bnv.js +0 -23
  135. package/dist/chunk-nsgqsmrh.js +0 -1779
  136. package/dist/chunk-q0st3se8.js +0 -42033
  137. package/dist/chunk-qr803fye.js +0 -2122
  138. package/dist/chunk-rds0sy87.js +0 -1771
  139. package/dist/chunk-ttz2ra5j.js +0 -12
  140. package/dist/chunk-v0bahtg2.js +0 -4
  141. package/dist/chunk-va2yd85b.js +0 -200
  142. package/dist/chunk-x9s0cqfx.js +0 -13
  143. package/dist/chunk-zqtpg06c.js +0 -1752
@@ -1,89 +1 @@
1
- import {
2
- DEFAULT_ATTACK_MODE_HOURS,
3
- MAX_CONTROL_HOURS,
4
- PROTECTION_SETTING,
5
- ProtectionControlStore,
6
- RATE_LIMIT_KEY_SEPARATOR,
7
- RateLimiter,
8
- applyControlsToDdos,
9
- applyControlsToRateLimits,
10
- defaultRateLimitRules,
11
- describePosture,
12
- globMatches,
13
- mergeControlsIntoConfig,
14
- rateLimitHeaders,
15
- rateLimitKey,
16
- ruleMatches
17
- } from "../chunk-d48vtdj4.js";
18
- import {
19
- escapeSecLang,
20
- globToRegex,
21
- isSafePattern,
22
- renderWafConfig,
23
- renderWafInstallScript,
24
- wafEventTelemetry
25
- } from "../chunk-va2yd85b.js";
26
- import {
27
- DEFAULT_DDOS_THRESHOLDS,
28
- applyMitigationFactor,
29
- isValidCidr,
30
- planMitigation,
31
- renderDdosInstallScript,
32
- renderNftablesRuleset,
33
- renderSysctlFile,
34
- sysctlHardening
35
- } from "../chunk-aa2dkn7b.js";
36
- import {
37
- CHAIN_HEADER,
38
- DEFAULT_RECURSION_LIMITS,
39
- DEPTH_HEADER,
40
- RecursionGuard,
41
- TRACE_HEADER,
42
- functionFingerprint,
43
- inspectInvocation,
44
- parseChain,
45
- propagationHeaders,
46
- recursionBlockedResponse
47
- } from "../chunk-050r7ycy.js";
48
- import"../chunk-v0bahtg2.js";
49
- export {
50
- wafEventTelemetry,
51
- sysctlHardening,
52
- ruleMatches,
53
- renderWafInstallScript,
54
- renderWafConfig,
55
- renderSysctlFile,
56
- renderNftablesRuleset,
57
- renderDdosInstallScript,
58
- recursionBlockedResponse,
59
- rateLimitKey,
60
- rateLimitHeaders,
61
- propagationHeaders,
62
- planMitigation,
63
- parseChain,
64
- mergeControlsIntoConfig,
65
- isValidCidr,
66
- isSafePattern,
67
- inspectInvocation,
68
- globToRegex,
69
- globMatches,
70
- functionFingerprint,
71
- escapeSecLang,
72
- describePosture,
73
- defaultRateLimitRules,
74
- applyMitigationFactor,
75
- applyControlsToRateLimits,
76
- applyControlsToDdos,
77
- TRACE_HEADER,
78
- RecursionGuard,
79
- RateLimiter,
80
- RATE_LIMIT_KEY_SEPARATOR,
81
- ProtectionControlStore,
82
- PROTECTION_SETTING,
83
- MAX_CONTROL_HOURS,
84
- DEPTH_HEADER,
85
- DEFAULT_RECURSION_LIMITS,
86
- DEFAULT_DDOS_THRESHOLDS,
87
- DEFAULT_ATTACK_MODE_HOURS,
88
- CHAIN_HEADER
89
- };
1
+ import{$k as H,Sk as y,Tk as z,Uk as A,Vk as B,Wk as C,Xk as D,Yk as E,Zk as F,_k as G,al as I,bl as J,cl as K,dl as L,el as M}from"../chunk-gnv3r2jg.js";import{fl as s,gl as t,hl as u,il as v,jl as w,kl as x}from"../chunk-cwkg37rs.js";import{ll as k,ml as l,nl as m,ol as n,pl as o,ql as p,rl as q,sl as r}from"../chunk-b8e5wzwn.js";import{Bs as a,Cs as b,Ds as c,Es as d,Fs as e,Gs as f,Hs as g,Is as h,Js as i,Ks as j}from"../chunk-dskvqt67.js";import"../chunk-xt3s24vr.js";export{x as wafEventTelemetry,m as sysctlHardening,A as ruleMatches,w as renderWafInstallScript,v as renderWafConfig,n as renderSysctlFile,o as renderNftablesRuleset,p as renderDdosInstallScript,j as recursionBlockedResponse,B as rateLimitKey,D as rateLimitHeaders,i as propagationHeaders,q as planMitigation,f as parseChain,M as mergeControlsIntoConfig,l as isValidCidr,t as isSafePattern,g as inspectInvocation,u as globToRegex,z as globMatches,d as functionFingerprint,s as escapeSecLang,J as describePosture,E as defaultRateLimitRules,r as applyMitigationFactor,K as applyControlsToRateLimits,L as applyControlsToDdos,c as TRACE_HEADER,h as RecursionGuard,C as RateLimiter,y as RATE_LIMIT_KEY_SEPARATOR,I as ProtectionControlStore,F as PROTECTION_SETTING,G as MAX_CONTROL_HOURS,a as DEPTH_HEADER,e as DEFAULT_RECURSION_LIMITS,k as DEFAULT_DDOS_THRESHOLDS,H as DEFAULT_ATTACK_MODE_HOURS,b as CHAIN_HEADER};
@@ -1,509 +1 @@
1
- import"../chunk-v0bahtg2.js";
2
-
3
- // src/push/apns.ts
4
- import * as http2 from "node:http2";
5
- import { createSign } from "node:crypto";
6
- var APNS_PRODUCTION_HOST = "api.push.apple.com";
7
- var APNS_SANDBOX_HOST = "api.sandbox.push.apple.com";
8
- var TOKEN_EXPIRY_MS = 45 * 60 * 1000;
9
-
10
- class APNsClient {
11
- config;
12
- token = null;
13
- tokenGeneratedAt = 0;
14
- client = null;
15
- host;
16
- constructor(config) {
17
- this.config = config;
18
- this.host = config.production ? APNS_PRODUCTION_HOST : APNS_SANDBOX_HOST;
19
- }
20
- generateToken() {
21
- const now = Math.floor(Date.now() / 1000);
22
- if (this.token && Date.now() - this.tokenGeneratedAt < TOKEN_EXPIRY_MS) {
23
- return this.token;
24
- }
25
- const header = {
26
- alg: "ES256",
27
- kid: this.config.keyId
28
- };
29
- const payload = {
30
- iss: this.config.teamId,
31
- iat: now
32
- };
33
- const encodedHeader = Buffer.from(JSON.stringify(header)).toString("base64url");
34
- const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
35
- const signatureInput = `${encodedHeader}.${encodedPayload}`;
36
- const sign = createSign("SHA256");
37
- sign.update(signatureInput);
38
- const signature = sign.sign(this.config.privateKey);
39
- const rawSignature = this.derToRaw(signature);
40
- const encodedSignature = rawSignature.toString("base64url");
41
- this.token = `${signatureInput}.${encodedSignature}`;
42
- this.tokenGeneratedAt = Date.now();
43
- return this.token;
44
- }
45
- derToRaw(derSignature) {
46
- let offset = 2;
47
- if (derSignature[offset] !== 2) {
48
- throw new Error("Invalid DER signature: expected 0x02 for R");
49
- }
50
- offset++;
51
- const rLength = derSignature[offset];
52
- offset++;
53
- let r = derSignature.subarray(offset, offset + rLength);
54
- offset += rLength;
55
- if (derSignature[offset] !== 2) {
56
- throw new Error("Invalid DER signature: expected 0x02 for S");
57
- }
58
- offset++;
59
- const sLength = derSignature[offset];
60
- offset++;
61
- let s = derSignature.subarray(offset, offset + sLength);
62
- if (r[0] === 0 && r.length === 33) {
63
- r = r.subarray(1);
64
- }
65
- if (s[0] === 0 && s.length === 33) {
66
- s = s.subarray(1);
67
- }
68
- const result = Buffer.alloc(64);
69
- r.copy(result, 32 - r.length);
70
- s.copy(result, 64 - s.length);
71
- return result;
72
- }
73
- async getClient() {
74
- if (this.client && !this.client.destroyed) {
75
- return this.client;
76
- }
77
- return new Promise((resolve, reject) => {
78
- this.client = http2.connect(`https://${this.host}`);
79
- this.client.on("error", (err) => {
80
- reject(err);
81
- });
82
- this.client.on("connect", () => {
83
- resolve(this.client);
84
- });
85
- this.client.on("close", () => {
86
- this.client = null;
87
- });
88
- });
89
- }
90
- buildPayload(notification) {
91
- const aps = {};
92
- if (notification.title || notification.body || notification.subtitle) {
93
- aps.alert = {};
94
- if (notification.title)
95
- aps.alert.title = notification.title;
96
- if (notification.subtitle)
97
- aps.alert.subtitle = notification.subtitle;
98
- if (notification.body)
99
- aps.alert.body = notification.body;
100
- }
101
- if (notification.badge !== undefined) {
102
- aps.badge = notification.badge;
103
- }
104
- if (notification.sound !== undefined) {
105
- aps.sound = notification.sound;
106
- }
107
- if (notification.category) {
108
- aps.category = notification.category;
109
- }
110
- if (notification.threadId) {
111
- aps["thread-id"] = notification.threadId;
112
- }
113
- if (notification.contentAvailable) {
114
- aps["content-available"] = 1;
115
- }
116
- if (notification.mutableContent) {
117
- aps["mutable-content"] = 1;
118
- }
119
- if (notification.targetContentId) {
120
- aps["target-content-id"] = notification.targetContentId;
121
- }
122
- const payload = { aps };
123
- if (notification.data) {
124
- Object.assign(payload, notification.data);
125
- }
126
- return payload;
127
- }
128
- async send(notification) {
129
- try {
130
- const client = await this.getClient();
131
- const token = this.generateToken();
132
- const payload = JSON.stringify(this.buildPayload(notification));
133
- const headers = {
134
- ":method": "POST",
135
- ":path": `/3/device/${notification.deviceToken}`,
136
- authorization: `bearer ${token}`,
137
- "apns-topic": this.config.bundleId,
138
- "apns-push-type": notification.pushType || "alert",
139
- "apns-priority": String(notification.priority || 10)
140
- };
141
- if (notification.expiration !== undefined) {
142
- headers["apns-expiration"] = String(notification.expiration);
143
- }
144
- if (notification.collapseId) {
145
- headers["apns-collapse-id"] = notification.collapseId;
146
- }
147
- return new Promise((resolve) => {
148
- const req = client.request(headers);
149
- let responseData = "";
150
- let statusCode = 0;
151
- let apnsId;
152
- req.on("response", (headers2) => {
153
- statusCode = headers2[":status"];
154
- apnsId = headers2["apns-id"];
155
- });
156
- req.on("data", (chunk) => {
157
- responseData += chunk.toString();
158
- });
159
- req.on("end", () => {
160
- if (statusCode === 200) {
161
- resolve({
162
- success: true,
163
- deviceToken: notification.deviceToken,
164
- apnsId,
165
- statusCode
166
- });
167
- } else {
168
- let error = "Unknown error";
169
- let reason;
170
- let timestamp;
171
- if (responseData) {
172
- try {
173
- const parsed = JSON.parse(responseData);
174
- reason = parsed.reason;
175
- timestamp = parsed.timestamp;
176
- error = reason || error;
177
- } catch {
178
- error = responseData;
179
- }
180
- }
181
- resolve({
182
- success: false,
183
- deviceToken: notification.deviceToken,
184
- apnsId,
185
- statusCode,
186
- error,
187
- reason,
188
- timestamp
189
- });
190
- }
191
- });
192
- req.on("error", (err) => {
193
- resolve({
194
- success: false,
195
- deviceToken: notification.deviceToken,
196
- error: err.message
197
- });
198
- });
199
- req.write(payload);
200
- req.end();
201
- });
202
- } catch (error) {
203
- return {
204
- success: false,
205
- deviceToken: notification.deviceToken,
206
- error: error.message
207
- };
208
- }
209
- }
210
- async sendBatch(notifications, options) {
211
- const concurrency = options?.concurrency || 10;
212
- const results = [];
213
- for (let i = 0;i < notifications.length; i += concurrency) {
214
- const batch = notifications.slice(i, i + concurrency);
215
- const batchResults = await Promise.all(batch.map((n) => this.send(n)));
216
- results.push(...batchResults);
217
- }
218
- return {
219
- sent: results.filter((r) => r.success).length,
220
- failed: results.filter((r) => !r.success).length,
221
- results
222
- };
223
- }
224
- async sendSimple(deviceToken, title, body, data) {
225
- return this.send({
226
- deviceToken,
227
- title,
228
- body,
229
- data
230
- });
231
- }
232
- async sendSilent(deviceToken, data) {
233
- return this.send({
234
- deviceToken,
235
- contentAvailable: true,
236
- pushType: "background",
237
- priority: 5,
238
- data
239
- });
240
- }
241
- close() {
242
- if (this.client) {
243
- this.client.close();
244
- this.client = null;
245
- }
246
- this.token = null;
247
- this.tokenGeneratedAt = 0;
248
- }
249
- }
250
- // src/push/fcm.ts
251
- import { createSign as createSign2 } from "node:crypto";
252
- var FCM_API_URL = "https://fcm.googleapis.com/v1/projects";
253
- var GOOGLE_TOKEN_URL = "https://oauth2.googleapis.com/token";
254
- var TOKEN_EXPIRY_MS2 = 55 * 60 * 1000;
255
-
256
- class FCMClient {
257
- config;
258
- accessToken = null;
259
- tokenExpiresAt = 0;
260
- constructor(config) {
261
- this.config = config;
262
- }
263
- static fromServiceAccount(serviceAccount) {
264
- return new FCMClient({
265
- projectId: serviceAccount.project_id,
266
- clientEmail: serviceAccount.client_email,
267
- privateKey: serviceAccount.private_key
268
- });
269
- }
270
- generateJWT() {
271
- const now = Math.floor(Date.now() / 1000);
272
- const exp = now + 3600;
273
- const header = {
274
- alg: "RS256",
275
- typ: "JWT"
276
- };
277
- const payload = {
278
- iss: this.config.clientEmail,
279
- sub: this.config.clientEmail,
280
- aud: GOOGLE_TOKEN_URL,
281
- iat: now,
282
- exp,
283
- scope: "https://www.googleapis.com/auth/firebase.messaging"
284
- };
285
- const encodedHeader = Buffer.from(JSON.stringify(header)).toString("base64url");
286
- const encodedPayload = Buffer.from(JSON.stringify(payload)).toString("base64url");
287
- const signatureInput = `${encodedHeader}.${encodedPayload}`;
288
- const sign = createSign2("SHA256");
289
- sign.update(signatureInput);
290
- const signature = sign.sign(this.config.privateKey, "base64url");
291
- return `${signatureInput}.${signature}`;
292
- }
293
- async getAccessToken() {
294
- if (this.accessToken && Date.now() < this.tokenExpiresAt) {
295
- return this.accessToken;
296
- }
297
- const jwt = this.generateJWT();
298
- const response = await fetch(GOOGLE_TOKEN_URL, {
299
- method: "POST",
300
- headers: {
301
- "Content-Type": "application/x-www-form-urlencoded"
302
- },
303
- body: new URLSearchParams({
304
- grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
305
- assertion: jwt
306
- }).toString()
307
- });
308
- if (!response.ok) {
309
- const errorText = await response.text();
310
- throw new Error(`Failed to get access token: ${errorText}`);
311
- }
312
- const data = await response.json();
313
- this.accessToken = data.access_token;
314
- this.tokenExpiresAt = Date.now() + TOKEN_EXPIRY_MS2;
315
- return this.accessToken;
316
- }
317
- buildMessage(notification) {
318
- const message = {};
319
- if (notification.token) {
320
- message.token = notification.token;
321
- } else if (notification.topic) {
322
- message.topic = notification.topic;
323
- } else if (notification.condition) {
324
- message.condition = notification.condition;
325
- }
326
- if (notification.title || notification.body || notification.imageUrl) {
327
- message.notification = {};
328
- if (notification.title)
329
- message.notification.title = notification.title;
330
- if (notification.body)
331
- message.notification.body = notification.body;
332
- if (notification.imageUrl)
333
- message.notification.image = notification.imageUrl;
334
- }
335
- if (notification.data && Object.keys(notification.data).length > 0) {
336
- message.data = notification.data;
337
- }
338
- if (notification.android) {
339
- message.android = {
340
- priority: notification.android.priority || "high"
341
- };
342
- if (notification.android.ttl) {
343
- message.android.ttl = `${notification.android.ttl}s`;
344
- }
345
- if (notification.android.collapseKey) {
346
- message.android.collapse_key = notification.android.collapseKey;
347
- }
348
- if (notification.android.directBootOk) {
349
- message.android.direct_boot_ok = notification.android.directBootOk;
350
- }
351
- const androidNotification = {};
352
- if (notification.android.channelId)
353
- androidNotification.channel_id = notification.android.channelId;
354
- if (notification.android.icon)
355
- androidNotification.icon = notification.android.icon;
356
- if (notification.android.color)
357
- androidNotification.color = notification.android.color;
358
- if (notification.android.sound)
359
- androidNotification.sound = notification.android.sound;
360
- if (notification.android.clickAction)
361
- androidNotification.click_action = notification.android.clickAction;
362
- if (notification.android.tag)
363
- androidNotification.tag = notification.android.tag;
364
- if (notification.android.visibility)
365
- androidNotification.visibility = notification.android.visibility;
366
- if (notification.android.notificationCount !== undefined) {
367
- androidNotification.notification_count = notification.android.notificationCount;
368
- }
369
- if (Object.keys(androidNotification).length > 0) {
370
- message.android.notification = androidNotification;
371
- }
372
- }
373
- if (notification.webpush) {
374
- message.webpush = notification.webpush;
375
- }
376
- if (notification.apns) {
377
- message.apns = notification.apns;
378
- }
379
- if (notification.fcmOptions) {
380
- message.fcm_options = notification.fcmOptions;
381
- }
382
- return { message };
383
- }
384
- async send(notification) {
385
- try {
386
- const accessToken = await this.getAccessToken();
387
- const payload = this.buildMessage(notification);
388
- const response = await fetch(`${FCM_API_URL}/${this.config.projectId}/messages:send`, {
389
- method: "POST",
390
- headers: {
391
- Authorization: `Bearer ${accessToken}`,
392
- "Content-Type": "application/json"
393
- },
394
- body: JSON.stringify(payload)
395
- });
396
- const data = await response.json();
397
- if (response.ok) {
398
- return {
399
- success: true,
400
- messageId: data.name
401
- };
402
- } else {
403
- return {
404
- success: false,
405
- error: data.error?.message || "Unknown error",
406
- errorCode: data.error?.status
407
- };
408
- }
409
- } catch (error) {
410
- return {
411
- success: false,
412
- error: error.message
413
- };
414
- }
415
- }
416
- async sendBatch(tokens, notification, options) {
417
- const concurrency = options?.concurrency || 10;
418
- const results = [];
419
- for (let i = 0;i < tokens.length; i += concurrency) {
420
- const batch = tokens.slice(i, i + concurrency);
421
- const batchPromises = batch.map(async (token) => {
422
- const result = await this.send({ ...notification, token });
423
- return { ...result, token };
424
- });
425
- const batchResults = await Promise.all(batchPromises);
426
- results.push(...batchResults);
427
- }
428
- return {
429
- sent: results.filter((r) => r.success).length,
430
- failed: results.filter((r) => !r.success).length,
431
- results
432
- };
433
- }
434
- async sendToTopic(topic, notification) {
435
- return this.send({ ...notification, topic });
436
- }
437
- async sendToCondition(condition, notification) {
438
- return this.send({ ...notification, condition });
439
- }
440
- async sendSimple(token, title, body, data) {
441
- return this.send({
442
- token,
443
- title,
444
- body,
445
- data
446
- });
447
- }
448
- async sendSilent(token, data) {
449
- return this.send({
450
- token,
451
- data,
452
- android: {
453
- priority: "high"
454
- }
455
- });
456
- }
457
- async subscribeToTopic(tokens, topic) {
458
- try {
459
- const accessToken = await this.getAccessToken();
460
- const response = await fetch(`https://iid.googleapis.com/iid/v1:batchAdd`, {
461
- method: "POST",
462
- headers: {
463
- Authorization: `Bearer ${accessToken}`,
464
- "Content-Type": "application/json"
465
- },
466
- body: JSON.stringify({
467
- to: `/topics/${topic}`,
468
- registration_tokens: tokens
469
- })
470
- });
471
- if (response.ok) {
472
- return { success: true };
473
- } else {
474
- const data = await response.json();
475
- return { success: false, error: data.error?.message || "Failed to subscribe" };
476
- }
477
- } catch (error) {
478
- return { success: false, error: error.message };
479
- }
480
- }
481
- async unsubscribeFromTopic(tokens, topic) {
482
- try {
483
- const accessToken = await this.getAccessToken();
484
- const response = await fetch(`https://iid.googleapis.com/iid/v1:batchRemove`, {
485
- method: "POST",
486
- headers: {
487
- Authorization: `Bearer ${accessToken}`,
488
- "Content-Type": "application/json"
489
- },
490
- body: JSON.stringify({
491
- to: `/topics/${topic}`,
492
- registration_tokens: tokens
493
- })
494
- });
495
- if (response.ok) {
496
- return { success: true };
497
- } else {
498
- const data = await response.json();
499
- return { success: false, error: data.error?.message || "Failed to unsubscribe" };
500
- }
501
- } catch (error) {
502
- return { success: false, error: error.message };
503
- }
504
- }
505
- }
506
- export {
507
- FCMClient,
508
- APNsClient
509
- };
1
+ import"../chunk-xt3s24vr.js";import*as K from"node:http2";import{createSign as U}from"node:crypto";var q="api.push.apple.com",D="api.sandbox.push.apple.com",M=2700000;class E{config;token=null;tokenGeneratedAt=0;client=null;host;constructor(z){this.config=z,this.host=z.production?q:D}generateToken(){let z=Math.floor(Date.now()/1000);if(this.token&&Date.now()-this.tokenGeneratedAt<M)return this.token;let J={alg:"ES256",kid:this.config.keyId},Q={iss:this.config.teamId,iat:z},V=Buffer.from(JSON.stringify(J)).toString("base64url"),W=Buffer.from(JSON.stringify(Q)).toString("base64url"),Z=`${V}.${W}`,$=U("SHA256");$.update(Z);let B=$.sign(this.config.privateKey),x=this.derToRaw(B).toString("base64url");return this.token=`${Z}.${x}`,this.tokenGeneratedAt=Date.now(),this.token}derToRaw(z){let J=2;if(z[J]!==2)throw Error("Invalid DER signature: expected 0x02 for R");J++;let Q=z[J];J++;let V=z.subarray(J,J+Q);if(J+=Q,z[J]!==2)throw Error("Invalid DER signature: expected 0x02 for S");J++;let W=z[J];J++;let Z=z.subarray(J,J+W);if(V[0]===0&&V.length===33)V=V.subarray(1);if(Z[0]===0&&Z.length===33)Z=Z.subarray(1);let $=Buffer.alloc(64);return V.copy($,32-V.length),Z.copy($,64-Z.length),$}async getClient(){if(this.client&&!this.client.destroyed)return this.client;return new Promise((z,J)=>{this.client=K.connect(`https://${this.host}`),this.client.on("error",(Q)=>{J(Q)}),this.client.on("connect",()=>{z(this.client)}),this.client.on("close",()=>{this.client=null})})}buildPayload(z){let J={};if(z.title||z.body||z.subtitle){if(J.alert={},z.title)J.alert.title=z.title;if(z.subtitle)J.alert.subtitle=z.subtitle;if(z.body)J.alert.body=z.body}if(z.badge!==void 0)J.badge=z.badge;if(z.sound!==void 0)J.sound=z.sound;if(z.category)J.category=z.category;if(z.threadId)J["thread-id"]=z.threadId;if(z.contentAvailable)J["content-available"]=1;if(z.mutableContent)J["mutable-content"]=1;if(z.targetContentId)J["target-content-id"]=z.targetContentId;let Q={aps:J};if(z.data)Object.assign(Q,z.data);return Q}async send(z){try{let J=await this.getClient(),Q=this.generateToken(),V=JSON.stringify(this.buildPayload(z)),W={":method":"POST",":path":`/3/device/${z.deviceToken}`,authorization:`bearer ${Q}`,"apns-topic":this.config.bundleId,"apns-push-type":z.pushType||"alert","apns-priority":String(z.priority||10)};if(z.expiration!==void 0)W["apns-expiration"]=String(z.expiration);if(z.collapseId)W["apns-collapse-id"]=z.collapseId;return new Promise((Z)=>{let $=J.request(W),B="",j=0,x;$.on("response",(Y)=>{j=Y[":status"],x=Y["apns-id"]}),$.on("data",(Y)=>{B+=Y.toString()}),$.on("end",()=>{if(j===200)Z({success:!0,deviceToken:z.deviceToken,apnsId:x,statusCode:j});else{let Y="Unknown error",X,w;if(B)try{let G=JSON.parse(B);X=G.reason,w=G.timestamp,Y=X||Y}catch{Y=B}Z({success:!1,deviceToken:z.deviceToken,apnsId:x,statusCode:j,error:Y,reason:X,timestamp:w})}}),$.on("error",(Y)=>{Z({success:!1,deviceToken:z.deviceToken,error:Y.message})}),$.write(V),$.end()})}catch(J){return{success:!1,deviceToken:z.deviceToken,error:J.message}}}async sendBatch(z,J){let Q=J?.concurrency||10,V=[];for(let W=0;W<z.length;W+=Q){let Z=z.slice(W,W+Q),$=await Promise.all(Z.map((B)=>this.send(B)));V.push(...$)}return{sent:V.filter((W)=>W.success).length,failed:V.filter((W)=>!W.success).length,results:V}}async sendSimple(z,J,Q,V){return this.send({deviceToken:z,title:J,body:Q,data:V})}async sendSilent(z,J){return this.send({deviceToken:z,contentAvailable:!0,pushType:"background",priority:5,data:J})}close(){if(this.client)this.client.close(),this.client=null;this.token=null,this.tokenGeneratedAt=0}}import{createSign as L}from"node:crypto";var R="https://fcm.googleapis.com/v1/projects",F="https://oauth2.googleapis.com/token",b=3300000;class H{config;accessToken=null;tokenExpiresAt=0;constructor(z){this.config=z}static fromServiceAccount(z){return new H({projectId:z.project_id,clientEmail:z.client_email,privateKey:z.private_key})}generateJWT(){let z=Math.floor(Date.now()/1000),J=z+3600,Q={alg:"RS256",typ:"JWT"},V={iss:this.config.clientEmail,sub:this.config.clientEmail,aud:F,iat:z,exp:J,scope:"https://www.googleapis.com/auth/firebase.messaging"},W=Buffer.from(JSON.stringify(Q)).toString("base64url"),Z=Buffer.from(JSON.stringify(V)).toString("base64url"),$=`${W}.${Z}`,B=L("SHA256");B.update($);let j=B.sign(this.config.privateKey,"base64url");return`${$}.${j}`}async getAccessToken(){if(this.accessToken&&Date.now()<this.tokenExpiresAt)return this.accessToken;let z=this.generateJWT(),J=await fetch(F,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"urn:ietf:params:oauth:grant-type:jwt-bearer",assertion:z}).toString()});if(!J.ok){let V=await J.text();throw Error(`Failed to get access token: ${V}`)}let Q=await J.json();return this.accessToken=Q.access_token,this.tokenExpiresAt=Date.now()+b,this.accessToken}buildMessage(z){let J={};if(z.token)J.token=z.token;else if(z.topic)J.topic=z.topic;else if(z.condition)J.condition=z.condition;if(z.title||z.body||z.imageUrl){if(J.notification={},z.title)J.notification.title=z.title;if(z.body)J.notification.body=z.body;if(z.imageUrl)J.notification.image=z.imageUrl}if(z.data&&Object.keys(z.data).length>0)J.data=z.data;if(z.android){if(J.android={priority:z.android.priority||"high"},z.android.ttl)J.android.ttl=`${z.android.ttl}s`;if(z.android.collapseKey)J.android.collapse_key=z.android.collapseKey;if(z.android.directBootOk)J.android.direct_boot_ok=z.android.directBootOk;let Q={};if(z.android.channelId)Q.channel_id=z.android.channelId;if(z.android.icon)Q.icon=z.android.icon;if(z.android.color)Q.color=z.android.color;if(z.android.sound)Q.sound=z.android.sound;if(z.android.clickAction)Q.click_action=z.android.clickAction;if(z.android.tag)Q.tag=z.android.tag;if(z.android.visibility)Q.visibility=z.android.visibility;if(z.android.notificationCount!==void 0)Q.notification_count=z.android.notificationCount;if(Object.keys(Q).length>0)J.android.notification=Q}if(z.webpush)J.webpush=z.webpush;if(z.apns)J.apns=z.apns;if(z.fcmOptions)J.fcm_options=z.fcmOptions;return{message:J}}async send(z){try{let J=await this.getAccessToken(),Q=this.buildMessage(z),V=await fetch(`${R}/${this.config.projectId}/messages:send`,{method:"POST",headers:{Authorization:`Bearer ${J}`,"Content-Type":"application/json"},body:JSON.stringify(Q)}),W=await V.json();if(V.ok)return{success:!0,messageId:W.name};else return{success:!1,error:W.error?.message||"Unknown error",errorCode:W.error?.status}}catch(J){return{success:!1,error:J.message}}}async sendBatch(z,J,Q){let V=Q?.concurrency||10,W=[];for(let Z=0;Z<z.length;Z+=V){let B=z.slice(Z,Z+V).map(async(x)=>{return{...await this.send({...J,token:x}),token:x}}),j=await Promise.all(B);W.push(...j)}return{sent:W.filter((Z)=>Z.success).length,failed:W.filter((Z)=>!Z.success).length,results:W}}async sendToTopic(z,J){return this.send({...J,topic:z})}async sendToCondition(z,J){return this.send({...J,condition:z})}async sendSimple(z,J,Q,V){return this.send({token:z,title:J,body:Q,data:V})}async sendSilent(z,J){return this.send({token:z,data:J,android:{priority:"high"}})}async subscribeToTopic(z,J){try{let Q=await this.getAccessToken(),V=await fetch("https://iid.googleapis.com/iid/v1:batchAdd",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({to:`/topics/${J}`,registration_tokens:z})});if(V.ok)return{success:!0};else return{success:!1,error:(await V.json()).error?.message||"Failed to subscribe"}}catch(Q){return{success:!1,error:Q.message}}}async unsubscribeFromTopic(z,J){try{let Q=await this.getAccessToken(),V=await fetch("https://iid.googleapis.com/iid/v1:batchRemove",{method:"POST",headers:{Authorization:`Bearer ${Q}`,"Content-Type":"application/json"},body:JSON.stringify({to:`/topics/${J}`,registration_tokens:z})});if(V.ok)return{success:!0};else return{success:!1,error:(await V.json()).error?.message||"Failed to unsubscribe"}}catch(Q){return{success:!1,error:Q.message}}}}export{H as FCMClient,E as APNsClient};