@sinch/functions-runtime 0.1.0-beta.28

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,812 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/bin/sinch-runtime.ts
4
+ import path4 from "path";
5
+ import { createRequire as createRequire3 } from "module";
6
+ import { pathToFileURL as pathToFileURL2 } from "url";
7
+ import fs3 from "fs";
8
+
9
+ // ../runtime-shared/dist/host/middleware.js
10
+ import { createRequire } from "module";
11
+ var requireCjs = createRequire(import.meta.url);
12
+ var defaultOptions = {
13
+ limit: "10mb",
14
+ allowJson5: true,
15
+ camelCase: {
16
+ deep: true,
17
+ stopPaths: ["custom", "applicationkey"],
18
+ exclude: []
19
+ }
20
+ };
21
+ var SPECIAL_CASES = {
22
+ callid: "callId",
23
+ applicationkey: "applicationKey",
24
+ callbackurl: "callbackUrl",
25
+ clinumber: "cliNumber",
26
+ menuResult: "menuResult",
27
+ userid: "userId",
28
+ username: "userName",
29
+ callleg: "callLeg",
30
+ conferenceid: "conferenceId",
31
+ participantid: "participantId"
32
+ };
33
+ function toCamelCase(str) {
34
+ if (!str)
35
+ return str;
36
+ if (str.includes("_") || str.includes("-")) {
37
+ return str.replace(/[-_]([a-z])/g, (_, char) => char.toUpperCase());
38
+ }
39
+ if (/[a-z][A-Z]/.test(str)) {
40
+ return str;
41
+ }
42
+ const lower = str.toLowerCase();
43
+ if (SPECIAL_CASES[lower]) {
44
+ return SPECIAL_CASES[lower];
45
+ }
46
+ return str;
47
+ }
48
+ function transformKeys(obj, options = {}) {
49
+ const { stopPaths = [], exclude = [], deep = true } = options;
50
+ if (obj === null || obj === void 0) {
51
+ return obj;
52
+ }
53
+ if (Array.isArray(obj)) {
54
+ return deep ? obj.map((item) => transformKeys(item, options)) : obj;
55
+ }
56
+ if (typeof obj !== "object") {
57
+ return obj;
58
+ }
59
+ const result = {};
60
+ const DANGEROUS_KEYS = ["__proto__", "constructor", "prototype"];
61
+ for (const [key, value] of Object.entries(obj)) {
62
+ if (DANGEROUS_KEYS.includes(key)) {
63
+ continue;
64
+ }
65
+ let newKey = key;
66
+ let shouldTransformValue = deep;
67
+ const isExcluded = exclude.some((pattern) => {
68
+ if (pattern instanceof RegExp) {
69
+ return pattern.test(key);
70
+ }
71
+ return pattern === key;
72
+ });
73
+ if (!isExcluded) {
74
+ newKey = toCamelCase(key);
75
+ }
76
+ if (DANGEROUS_KEYS.includes(newKey)) {
77
+ continue;
78
+ }
79
+ if (stopPaths.includes(newKey)) {
80
+ shouldTransformValue = false;
81
+ }
82
+ result[newKey] = shouldTransformValue ? transformKeys(value, options) : value;
83
+ }
84
+ return result;
85
+ }
86
+ function parseJson(text, allowJson5 = true) {
87
+ if (!text || typeof text !== "string") {
88
+ return {};
89
+ }
90
+ const trimmed = text.trim();
91
+ if (!trimmed) {
92
+ return {};
93
+ }
94
+ try {
95
+ return JSON.parse(trimmed);
96
+ } catch (e) {
97
+ if (!allowJson5) {
98
+ throw new Error(`Invalid JSON: ${e.message}`);
99
+ }
100
+ try {
101
+ const cleaned = trimmed.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "").replace(/,(\s*[}\]])/g, "$1");
102
+ return JSON.parse(cleaned);
103
+ } catch (e2) {
104
+ throw new Error(`Invalid JSON/JSON5: ${e.message}`);
105
+ }
106
+ }
107
+ }
108
+ function createLenientJsonParser(options = {}) {
109
+ const opts = { ...defaultOptions, ...options };
110
+ return function lenientJsonParser(req, res, next) {
111
+ if (req.body && typeof req.body === "object" && !Buffer.isBuffer(req.body)) {
112
+ if (!req._keysTransformed) {
113
+ req.body = transformKeys(req.body, opts.camelCase);
114
+ req._keysTransformed = true;
115
+ }
116
+ return next();
117
+ }
118
+ let raw = "";
119
+ if (typeof req.body === "string") {
120
+ raw = req.body;
121
+ req.rawBody = raw;
122
+ } else if (Buffer.isBuffer(req.body)) {
123
+ raw = req.body.toString("utf8");
124
+ req.rawBody = raw;
125
+ } else {
126
+ req.body = {};
127
+ return next();
128
+ }
129
+ try {
130
+ let parsed = parseJson(raw, opts.allowJson5);
131
+ parsed = transformKeys(parsed, opts.camelCase);
132
+ req._keysTransformed = true;
133
+ req.body = parsed;
134
+ next();
135
+ } catch (error) {
136
+ res.status(400).json({
137
+ error: "Invalid JSON in request body",
138
+ message: error.message,
139
+ hint: opts.allowJson5 ? "This endpoint accepts JSON and JSON5 (comments and trailing commas allowed)" : "This endpoint requires strict JSON format"
140
+ });
141
+ }
142
+ };
143
+ }
144
+ function setupJsonParsing(app, options = {}) {
145
+ const express = requireCjs("express");
146
+ app.use(express.text({
147
+ type: ["application/json", "application/*+json", "text/json"],
148
+ limit: options.limit || "10mb"
149
+ }));
150
+ app.use(createLenientJsonParser(options));
151
+ return app;
152
+ }
153
+
154
+ // ../runtime-shared/dist/host/app.js
155
+ import { createRequire as createRequire2 } from "module";
156
+ import { pathToFileURL } from "url";
157
+ import * as nodePath from "path";
158
+ var requireCjs2 = createRequire2(import.meta.url);
159
+ var LANDING_PAGE_HTML = `<!DOCTYPE html>
160
+ <html lang="en">
161
+ <head>
162
+ <meta charset="UTF-8">
163
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
164
+ <title>Sinch Function</title>
165
+ <link rel="icon" type="image/svg+xml" href="/favicon.ico">
166
+ <link href="https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap" rel="stylesheet">
167
+ <style>
168
+ * { margin: 0; padding: 0; box-sizing: border-box; }
169
+ body { font-family: "DM Sans", Arial, sans-serif; min-height: 100vh; overflow: hidden; background: #ffffff; }
170
+ #gradient-canvas { position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 0; }
171
+ .content { position: relative; z-index: 10; min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 2rem; mix-blend-mode: difference; }
172
+ .icon-wrapper { width: 120px; height: 120px; margin-bottom: 2rem; animation: float 6s ease-in-out infinite; }
173
+ @keyframes float { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-12px); } }
174
+ .icon-wrapper svg { width: 100%; height: 100%; fill: white; }
175
+ .title { font-size: clamp(32px, 6vw, 56px); font-weight: 700; letter-spacing: -0.02em; line-height: 1.2; color: white; text-align: center; max-width: 600px; margin-bottom: 1.5rem; }
176
+ .status { display: inline-flex; align-items: center; gap: 0.75rem; font-size: 18px; font-weight: 500; color: white; opacity: 0.9; }
177
+ .status-dot { width: 10px; height: 10px; background: white; border-radius: 50%; position: relative; }
178
+ .status-dot::before { content: ''; position: absolute; inset: -4px; border-radius: 50%; border: 2px solid white; animation: ripple 2s ease-out infinite; }
179
+ @keyframes ripple { 0% { transform: scale(1); opacity: 0.6; } 100% { transform: scale(2); opacity: 0; } }
180
+ footer { position: fixed; bottom: 0; left: 0; right: 0; padding: 1.5rem 2rem; text-align: center; z-index: 10; mix-blend-mode: difference; }
181
+ .footer-content { display: flex; align-items: center; justify-content: center; gap: 0.5rem; font-size: 13px; color: white; opacity: 0.7; }
182
+ .footer-content svg { height: 16px; width: auto; fill: white; }
183
+ @media (prefers-reduced-motion: reduce) { .icon-wrapper { animation: none; } .status-dot::before { animation: none; display: none; } }
184
+ </style>
185
+ </head>
186
+ <body>
187
+ <canvas id="gradient-canvas"></canvas>
188
+ <div class="content">
189
+ <div class="icon-wrapper">
190
+ <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
191
+ <path d="M0 0 C20.93144435 -0.58142901 39.09496106 1.50604372 55.875 15.5625 C66.82790249 26.17665293 72.53226475 40.66646351 74.60546875 55.56640625 C74.87588186 58.00035983 74.87588186 58.00035983 76 60 C76.96454894 67.72509952 77.18355452 75.52548686 77.39453125 83.30078125 C77.46339082 85.43557289 77.53307981 87.57033791 77.60351562 89.70507812 C77.70976411 92.99051459 77.81152568 96.27576582 77.89868164 99.56176758 C78.52393733 129.23731142 78.52393733 129.23731142 88 157 C88.35578125 157.67804688 88.7115625 158.35609375 89.078125 159.0546875 C94.76089061 168.37922543 104.94901494 170.48725373 115 173 C115 182.57 115 192.14 115 202 C112.69 202.37125 110.38 202.7425 108 203.125 C99.905737 204.67003153 95.0680161 206.8924082 90.109375 213.53125 C83.71376381 223.52775152 81.23188184 234.44421869 79.9609375 246.09765625 C79.87667007 246.86579147 79.79240265 247.6339267 79.70558167 248.42533875 C78.67925596 258.36255872 78.32712705 268.3341428 77.9375 278.3125 C76.56010435 312.28921394 76.56010435 312.28921394 74.25 321.5 C74.0744458 322.21430176 73.8988916 322.92860352 73.71801758 323.66455078 C69.36621237 340.7251508 62.22279512 355.52722574 46.7734375 364.97265625 C31.08266768 373.31391199 17.46036093 374.45648002 0 374 C0 362.78 0 351.56 0 340 C4.95 339.67 9.9 339.34 15 339 C21.41425661 337.54221441 27.40557289 335.94604143 32 331 C41.96653782 315.14896379 41.37732492 296.30175799 42 278.25 C44.29042973 212.3198731 44.29042973 212.3198731 64.91015625 190 C66.29780265 187.98880883 66.29780265 187.98880883 65.37890625 185.48046875 C64.05564488 183.10009772 62.69232678 181.32846483 60.875 179.3125 C43.91950219 157.82609672 43.67363702 127.5168667 42.25390625 101.43359375 C42.19595886 100.36962875 42.13801147 99.30566376 42.07830811 98.2094574 C41.84407978 93.84466467 41.61402719 89.47975805 41.39819336 85.11401367 C40.99015593 64.27717646 40.99015593 64.27717646 32.98828125 45.5234375 C32 44 32 44 32 42 C31.42121094 41.71253906 30.84242188 41.42507813 30.24609375 41.12890625 C28.83602338 40.42019262 27.43139326 39.70043581 26.03515625 38.96484375 C25.38417969 38.62582031 24.73320313 38.28679687 24.0625 37.9375 C23.41410156 37.59589844 22.76570312 37.25429688 22.09765625 36.90234375 C15.27203813 33.966184 7.11372705 34.47424847 0 34 C0 22.78 0 11.56 0 0 Z" transform="translate(654,325)"/>
192
+ <path d="M0 0 C3.444375 0.04125 6.88875 0.0825 10.4375 0.125 C10.4375 11.345 10.4375 22.565 10.4375 34.125 C7.83875 34.2075 5.24 34.29 2.5625 34.375 C-7.18272292 34.85729903 -15.63749007 36.71684985 -22.5625 44.125 C-31.49595906 57.5251886 -31.12984766 74.21365918 -31.625 89.6875 C-34.18432686 164.24320576 -34.18432686 164.24320576 -54.375 183.4765625 C-55.74969183 185.03433577 -55.74969183 185.03433577 -55.515625 186.95703125 C-54.17099734 190.0155081 -52.28807488 192.49561568 -50.3125 195.1875 C-32.54496946 220.15391355 -32.63824135 251.51444506 -31.51293945 280.92919922 C-31.08045868 292.11365858 -30.51897291 303.08447592 -28.5625 314.125 C-28.43262695 314.88192139 -28.30275391 315.63884277 -28.16894531 316.41870117 C-26.61388783 323.91215705 -23.50529382 330.13896804 -17.1875 334.5625 C-8.59143743 340.04835084 0.27828442 339.49004903 10.4375 340.125 C10.4375 351.345 10.4375 362.565 10.4375 374.125 C-11.03507606 374.69006779 -28.20349315 372.92712593 -45.375 358.5625 C-68.63112564 336.25560398 -67.21470802 299.23895394 -68.0625 269.5625 C-68.59361144 237.84268541 -68.59361144 237.84268541 -82.5625 210.125 C-89.22872268 204.50037462 -95.95018781 203.27807805 -104.5625 201.125 C-104.5625 191.885 -104.5625 182.645 -104.5625 173.125 C-102.0875 172.444375 -99.6125 171.76375 -97.0625 171.0625 C-88.61410179 168.53529591 -83.39407037 165.21504609 -78.3125 157.875 C-77.69451944 156.64176126 -77.11369297 155.38950152 -76.5625 154.125 C-76.05783203 152.97451172 -76.05783203 152.97451172 -75.54296875 151.80078125 C-70.10324087 138.17090127 -68.58488302 123.17691663 -68.1328125 108.6171875 C-68.0590342 106.55597377 -67.98479985 104.49477633 -67.91015625 102.43359375 C-67.79799647 99.2401961 -67.68897443 96.04681123 -67.58837891 92.85302734 C-67.22538737 81.52946225 -66.65494051 70.32073083 -65.13671875 59.0859375 C-64.95793686 57.75983963 -64.95793686 57.75983963 -64.77554321 56.4069519 C-62.24372342 39.06207822 -55.12155189 23.04594995 -40.9609375 12.1171875 C-28.07509054 3.53900119 -15.33988115 -0.26186367 0 0 Z" transform="translate(359.5625,324.875)"/>
193
+ <path d="M0 0 C9.89334431 8.68950817 14.30034619 23.01452361 15.24373245 35.79419899 C15.49099471 41.77148785 15.42334062 47.74978768 15.37109375 53.73046875 C15.36548489 55.63859724 15.36122091 57.54673011 15.35823059 59.4548645 C15.34688325 64.42950786 15.31750548 69.40388024 15.28411865 74.37841797 C15.25319735 79.47359555 15.23967854 84.56881775 15.22460938 89.6640625 C15.19262409 99.62643911 15.13994121 109.58854505 15.078125 119.55078125 C3.528125 119.55078125 -8.021875 119.55078125 -19.921875 119.55078125 C-19.97085938 114.4203125 -20.01984375 109.28984375 -20.0703125 104.00390625 C-20.10574492 100.73175245 -20.14173112 97.45962313 -20.1796875 94.1875 C-20.23973228 89.00671097 -20.29785091 83.82595572 -20.34375 78.64501953 C-20.38093086 74.46275871 -20.42737419 70.28068941 -20.47993851 66.09859467 C-20.49830992 64.51204578 -20.51347972 62.92545612 -20.52521896 61.3388443 C-20.22141003 42.05064114 -20.22141003 42.05064114 -28.921875 25.55078125 C-33.2097739 21.98892101 -37.29807009 19.87523153 -42.921875 19.55078125 C-43.79714844 19.48890625 -44.67242188 19.42703125 -45.57421875 19.36328125 C-54.66067243 18.98906437 -62.9621186 20.4280254 -69.859375 26.73828125 C-76.14726535 33.73487866 -78.0525657 41.92333342 -78.12719727 51.07324219 C-78.13709686 51.82485123 -78.14699646 52.57646027 -78.15719604 53.35084534 C-78.18871966 55.82891721 -78.21353223 58.30700823 -78.23828125 60.78515625 C-78.25885867 62.50580334 -78.27985536 64.22644545 -78.30125427 65.94708252 C-78.35639351 70.47125217 -78.40583867 74.99546682 -78.45410156 79.51971436 C-78.51321858 84.95049451 -78.57940167 90.38119259 -78.64440155 95.81190491 C-78.74230855 104.0581468 -78.83123469 112.30444185 -78.921875 120.55078125 C-90.801875 120.55078125 -102.681875 120.55078125 -114.921875 120.55078125 C-114.921875 77.65078125 -114.921875 34.75078125 -114.921875 -9.44921875 C-103.701875 -9.44921875 -92.481875 -9.44921875 -80.921875 -9.44921875 C-79.96000569 -5.60174152 -79.61528473 -2.14754023 -79.359375 1.80078125 C-79.27558594 3.0640625 -79.19179688 4.32734375 -79.10546875 5.62890625 C-79.04488281 6.593125 -78.98429688 7.55734375 -78.921875 8.55078125 C-78.48875 7.72578125 -78.055625 6.90078125 -77.609375 6.05078125 C-71.50314599 -3.01214812 -59.57220635 -8.76116827 -49.16015625 -11.05859375 C-31.06340614 -13.24155516 -14.8555768 -11.20207112 0 0 Z" transform="translate(613.921875,481.44921875)"/>
194
+ <path d="M0 0 C1.53906801 1.53906801 1.16955456 2.91263628 1.1875 5.0625 C1.1451715 9.92322255 0.65815533 14.68227908 0.0625 19.5 C-0.02427002 20.20648682 -0.11104004 20.91297363 -0.20043945 21.64086914 C-0.86920125 26.7384025 -0.86920125 26.7384025 -2 29 C-2.96808594 28.84144531 -3.93617188 28.68289063 -4.93359375 28.51953125 C-9.31081865 27.89956204 -13.64601408 27.74275212 -18.0625 27.6875 C-18.83916016 27.65849609 -19.61582031 27.62949219 -20.41601562 27.59960938 C-25.75566236 27.54083257 -28.83098013 28.36372264 -33 32 C-37.31404494 38.3211768 -37.31404494 38.3211768 -37 53 C-25.78 53 -14.56 53 -3 53 C-3 62.57 -3 72.14 -3 82 C-14.55 82 -26.1 82 -38 82 C-38 115 -38 148 -38 182 C-49.55 182 -61.1 182 -73 182 C-73 149 -73 116 -73 82 C-79.93 82 -86.86 82 -94 82 C-94 72.43 -94 62.86 -94 53 C-87.07 53 -80.14 53 -73 53 C-73.04125 50.6075 -73.0825 48.215 -73.125 45.75 C-73.17827085 31.60875021 -70.96095372 19.48048613 -61.0078125 8.81640625 C-54.5981324 3.0177657 -47.30019677 0.02408307 -39 -2 C-38.37625488 -2.17200928 -37.75250977 -2.34401855 -37.10986328 -2.52124023 C-25.33848182 -5.19234404 -11.53065338 -2.96722147 0 0 Z" transform="translate(486,419)"/>
195
+ </svg>
196
+ </div>
197
+ <h1 class="title">Your function is ready for traffic</h1>
198
+ <div class="status"><span class="status-dot"></span>Running</div>
199
+ </div>
200
+ <footer>
201
+ <div class="footer-content">
202
+ Powered by
203
+ <svg viewBox="0 0 93 48" xmlns="http://www.w3.org/2000/svg">
204
+ <path d="M92.298 25.271a17.167 17.167 0 0 1-.814 5.312c-1.51 4.734-5.27 8.678-10.06 10.549-5.64 2.202-12.252 1.416-18.624-2.21l-4.649-2.67a16.424 16.424 0 0 1-3.563 3.064l-14.817 8.679-.027.015v-7.501l.027-.014 22.29-13.057a16.017 16.017 0 0 1-.713 3.206l4.656 2.65c5.95 3.386 10.388 2.85 13.065 1.806 2.991-1.167 5.323-3.59 6.245-6.483.692-2.15.679-4.467-.04-6.609-.955-2.88-3.319-5.275-6.324-6.41-2.688-1.014-7.132-1.494-13.04 1.962L29.7 38.747l-.043.028c-4.017 2.35-8.14 3.556-12.065 3.58a18.162 18.162 0 0 1-6.53-1.145C6.247 39.396 2.44 35.498.874 30.783A17.116 17.116 0 0 1 .81 20.166c1.51-4.733 5.272-8.676 10.063-10.548 5.64-2.202 12.252-1.416 18.623 2.212l4.649 2.67a16.377 16.377 0 0 1 3.563-3.067l.281-.163 1.726-1.011-7.37-4.197A3.238 3.238 0 0 1 35.551.437l10.591 6.06L56.52.457a3.238 3.238 0 0 1 3.27 5.588l-29.528 17.05c.132-1.017.36-2.019.683-2.992l-4.656-2.65c-5.946-3.383-10.384-2.847-13.061-1.803-2.991 1.167-5.325 3.59-6.247 6.481a10.623 10.623 0 0 0 .039 6.608c.956 2.882 3.321 5.277 6.324 6.41 2.689 1.012 7.136 1.495 13.042-1.966l36.256-21.208c4.017-2.349 8.14-3.555 12.067-3.579a18.112 18.112 0 0 1 6.53 1.145c4.812 1.813 8.62 5.712 10.187 10.426a17.23 17.23 0 0 1 .872 5.304Z"/>
205
+ </svg>
206
+ </div>
207
+ </footer>
208
+ <script type="importmap">{"imports":{"three":"https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"}}</script>
209
+ <script type="module">
210
+ import * as THREE from 'three';
211
+ const COLORS={yellow:new THREE.Color(0xFFBE3C),green:new THREE.Color(0x059688),blue:new THREE.Color(0x3AA7EA),red:new THREE.Color(0xEF5858)};
212
+ const vertexShader=\`varying vec2 vUv;void main(){vUv=uv;gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);}\`;
213
+ const fragmentShader=\`uniform float uTime;uniform vec2 uResolution;uniform vec3 uColor1;uniform vec3 uColor2;uniform vec3 uColor3;uniform vec3 uColor4;varying vec2 vUv;vec3 mod289(vec3 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 mod289(vec4 x){return x-floor(x*(1.0/289.0))*289.0;}vec4 permute(vec4 x){return mod289(((x*34.0)+1.0)*x);}vec4 taylorInvSqrt(vec4 r){return 1.79284291400159-0.85373472095314*r;}float snoise(vec3 v){const vec2 C=vec2(1.0/6.0,1.0/3.0);const vec4 D=vec4(0.0,0.5,1.0,2.0);vec3 i=floor(v+dot(v,C.yyy));vec3 x0=v-i+dot(i,C.xxx);vec3 g=step(x0.yzx,x0.xyz);vec3 l=1.0-g;vec3 i1=min(g.xyz,l.zxy);vec3 i2=max(g.xyz,l.zxy);vec3 x1=x0-i1+C.xxx;vec3 x2=x0-i2+C.yyy;vec3 x3=x0-D.yyy;i=mod289(i);vec4 p=permute(permute(permute(i.z+vec4(0.0,i1.z,i2.z,1.0))+i.y+vec4(0.0,i1.y,i2.y,1.0))+i.x+vec4(0.0,i1.x,i2.x,1.0));float n_=0.142857142857;vec3 ns=n_*D.wyz-D.xzx;vec4 j=p-49.0*floor(p*ns.z*ns.z);vec4 x_=floor(j*ns.z);vec4 y_=floor(j-7.0*x_);vec4 x=x_*ns.x+ns.yyyy;vec4 y=y_*ns.x+ns.yyyy;vec4 h=1.0-abs(x)-abs(y);vec4 b0=vec4(x.xy,y.xy);vec4 b1=vec4(x.zw,y.zw);vec4 s0=floor(b0)*2.0+1.0;vec4 s1=floor(b1)*2.0+1.0;vec4 sh=-step(h,vec4(0.0));vec4 a0=b0.xzyw+s0.xzyw*sh.xxyy;vec4 a1=b1.xzyw+s1.xzyw*sh.zzww;vec3 p0=vec3(a0.xy,h.x);vec3 p1=vec3(a0.zw,h.y);vec3 p2=vec3(a1.xy,h.z);vec3 p3=vec3(a1.zw,h.w);vec4 norm=taylorInvSqrt(vec4(dot(p0,p0),dot(p1,p1),dot(p2,p2),dot(p3,p3)));p0*=norm.x;p1*=norm.y;p2*=norm.z;p3*=norm.w;vec4 m=max(0.6-vec4(dot(x0,x0),dot(x1,x1),dot(x2,x2),dot(x3,x3)),0.0);m=m*m;return 42.0*dot(m*m,vec4(dot(p0,x0),dot(p1,x1),dot(p2,x2),dot(p3,x3)));}float metaball(vec2 p,vec2 center,float radius){float d=length(p-center);return radius/(d*d+0.0001);}void main(){vec2 uv=vUv;vec2 aspect=vec2(uResolution.x/uResolution.y,1.0);vec2 p=(uv-0.5)*aspect;float time=uTime*0.15;vec2 blob1=vec2(0.6*sin(time*0.7+snoise(vec3(time*0.2,0.0,0.0))),0.5*cos(time*0.5+snoise(vec3(0.0,time*0.2,0.0))));vec2 blob2=vec2(0.55*cos(time*0.6+1.5+snoise(vec3(time*0.15,1.0,0.0))),0.6*sin(time*0.8+2.0+snoise(vec3(1.0,time*0.15,0.0))));vec2 blob3=vec2(0.7*sin(time*0.5+3.0+snoise(vec3(time*0.1,2.0,0.0))),0.5*cos(time*0.7+1.0+snoise(vec3(2.0,time*0.1,0.0))));vec2 blob4=vec2(0.55*cos(time*0.8+4.5+snoise(vec3(time*0.12,3.0,0.0))),0.65*sin(time*0.6+0.5+snoise(vec3(3.0,time*0.12,0.0))));float size1=0.16+0.04*sin(time*1.2);float size2=0.14+0.03*cos(time*1.5);float size3=0.18+0.05*sin(time*0.9);float size4=0.12+0.04*cos(time*1.1);float m1=metaball(p,blob1,size1);float m2=metaball(p,blob2,size2);float m3=metaball(p,blob3,size3);float m4=metaball(p,blob4,size4);float field=m1+m2+m3+m4;float noise=snoise(vec3(p*3.0,time*0.3))*0.15;field+=noise;vec3 color=vec3(0.0);float total=m1+m2+m3+m4+0.0001;color+=uColor1*(m1/total);color+=uColor2*(m2/total);color+=uColor3*(m3/total);color+=uColor4*(m4/total);float gradientNoise=snoise(vec3(uv*2.0,time*0.1));color+=gradientNoise*0.05;float threshold=0.8;float edge=smoothstep(threshold-0.3,threshold+0.5,field);vec3 bg1=mix(uColor1,uColor3,uv.y)*0.6+0.4;vec3 bg2=mix(uColor2,uColor4,uv.x)*0.6+0.4;vec3 background=mix(bg1,bg2,0.5+0.5*sin(time*0.2));vec3 finalColor=mix(background,color,edge);float vignette=1.0-length(uv-0.5)*0.5;finalColor*=vignette;finalColor=pow(finalColor,vec3(0.95));gl_FragColor=vec4(finalColor,1.0);}\`;
214
+ class GradientAnimation{constructor(){this.canvas=document.getElementById('gradient-canvas');this.scene=new THREE.Scene();this.camera=new THREE.OrthographicCamera(-1,1,1,-1,0,1);this.renderer=new THREE.WebGLRenderer({canvas:this.canvas,antialias:true,alpha:false});this.renderer.setPixelRatio(Math.min(window.devicePixelRatio,2));this.renderer.setSize(window.innerWidth,window.innerHeight);this.uniforms={uTime:{value:0},uResolution:{value:new THREE.Vector2(window.innerWidth,window.innerHeight)},uColor1:{value:COLORS.yellow},uColor2:{value:COLORS.green},uColor3:{value:COLORS.blue},uColor4:{value:COLORS.red}};const geometry=new THREE.PlaneGeometry(2,2);const material=new THREE.ShaderMaterial({vertexShader,fragmentShader,uniforms:this.uniforms});this.mesh=new THREE.Mesh(geometry,material);this.scene.add(this.mesh);window.addEventListener('resize',this.onResize.bind(this));this.animate();}onResize(){this.renderer.setSize(window.innerWidth,window.innerHeight);this.uniforms.uResolution.value.set(window.innerWidth,window.innerHeight);}animate(){this.uniforms.uTime.value+=0.016;this.renderer.render(this.scene,this.camera);requestAnimationFrame(this.animate.bind(this));}}
215
+ new GradientAnimation();
216
+ </script>
217
+ </body>
218
+ </html>`;
219
+ function getLandingPageHtml() {
220
+ return LANDING_PAGE_HTML;
221
+ }
222
+ var FAVICON_SVG = `<svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
223
+ <rect width="1024" height="1024" fill="#3AA7EA"/>
224
+ <path fill="white" d="M0 0 C20.93144435 -0.58142901 39.09496106 1.50604372 55.875 15.5625 C66.82790249 26.17665293 72.53226475 40.66646351 74.60546875 55.56640625 C74.87588186 58.00035983 74.87588186 58.00035983 76 60 C76.96454894 67.72509952 77.18355452 75.52548686 77.39453125 83.30078125 C77.46339082 85.43557289 77.53307981 87.57033791 77.60351562 89.70507812 C77.70976411 92.99051459 77.81152568 96.27576582 77.89868164 99.56176758 C78.52393733 129.23731142 78.52393733 129.23731142 88 157 C88.35578125 157.67804688 88.7115625 158.35609375 89.078125 159.0546875 C94.76089061 168.37922543 104.94901494 170.48725373 115 173 C115 182.57 115 192.14 115 202 C112.69 202.37125 110.38 202.7425 108 203.125 C99.905737 204.67003153 95.0680161 206.8924082 90.109375 213.53125 C83.71376381 223.52775152 81.23188184 234.44421869 79.9609375 246.09765625 C79.87667007 246.86579147 79.79240265 247.6339267 79.70558167 248.42533875 C78.67925596 258.36255872 78.32712705 268.3341428 77.9375 278.3125 C76.56010435 312.28921394 76.56010435 312.28921394 74.25 321.5 C74.0744458 322.21430176 73.8988916 322.92860352 73.71801758 323.66455078 C69.36621237 340.7251508 62.22279512 355.52722574 46.7734375 364.97265625 C31.08266768 373.31391199 17.46036093 374.45648002 0 374 C0 362.78 0 351.56 0 340 C4.95 339.67 9.9 339.34 15 339 C21.41425661 337.54221441 27.40557289 335.94604143 32 331 C41.96653782 315.14896379 41.37732492 296.30175799 42 278.25 C44.29042973 212.3198731 44.29042973 212.3198731 64.91015625 190 C66.29780265 187.98880883 66.29780265 187.98880883 65.37890625 185.48046875 C64.05564488 183.10009772 62.69232678 181.32846483 60.875 179.3125 C43.91950219 157.82609672 43.67363702 127.5168667 42.25390625 101.43359375 C42.19595886 100.36962875 42.13801147 99.30566376 42.07830811 98.2094574 C41.84407978 93.84466467 41.61402719 89.47975805 41.39819336 85.11401367 C40.99015593 64.27717646 40.99015593 64.27717646 32.98828125 45.5234375 C32 44 32 44 32 42 C31.42121094 41.71253906 30.84242188 41.42507813 30.24609375 41.12890625 C28.83602338 40.42019262 27.43139326 39.70043581 26.03515625 38.96484375 C25.38417969 38.62582031 24.73320313 38.28679687 24.0625 37.9375 C23.41410156 37.59589844 22.76570312 37.25429688 22.09765625 36.90234375 C15.27203813 33.966184 7.11372705 34.47424847 0 34 C0 22.78 0 11.56 0 0 Z" transform="translate(654,325)"/>
225
+ <path fill="white" d="M0 0 C3.444375 0.04125 6.88875 0.0825 10.4375 0.125 C10.4375 11.345 10.4375 22.565 10.4375 34.125 C7.83875 34.2075 5.24 34.29 2.5625 34.375 C-7.18272292 34.85729903 -15.63749007 36.71684985 -22.5625 44.125 C-31.49595906 57.5251886 -31.12984766 74.21365918 -31.625 89.6875 C-34.18432686 164.24320576 -34.18432686 164.24320576 -54.375 183.4765625 C-55.74969183 185.03433577 -55.74969183 185.03433577 -55.515625 186.95703125 C-54.17099734 190.0155081 -52.28807488 192.49561568 -50.3125 195.1875 C-32.54496946 220.15391355 -32.63824135 251.51444506 -31.51293945 280.92919922 C-31.08045868 292.11365858 -30.51897291 303.08447592 -28.5625 314.125 C-28.43262695 314.88192139 -28.30275391 315.63884277 -28.16894531 316.41870117 C-26.61388783 323.91215705 -23.50529382 330.13896804 -17.1875 334.5625 C-8.59143743 340.04835084 0.27828442 339.49004903 10.4375 340.125 C10.4375 351.345 10.4375 362.565 10.4375 374.125 C-11.03507606 374.69006779 -28.20349315 372.92712593 -45.375 358.5625 C-68.63112564 336.25560398 -67.21470802 299.23895394 -68.0625 269.5625 C-68.59361144 237.84268541 -68.59361144 237.84268541 -82.5625 210.125 C-89.22872268 204.50037462 -95.95018781 203.27807805 -104.5625 201.125 C-104.5625 191.885 -104.5625 182.645 -104.5625 173.125 C-102.0875 172.444375 -99.6125 171.76375 -97.0625 171.0625 C-88.61410179 168.53529591 -83.39407037 165.21504609 -78.3125 157.875 C-77.69451944 156.64176126 -77.11369297 155.38950152 -76.5625 154.125 C-76.05783203 152.97451172 -76.05783203 152.97451172 -75.54296875 151.80078125 C-70.10324087 138.17090127 -68.58488302 123.17691663 -68.1328125 108.6171875 C-68.0590342 106.55597377 -67.98479985 104.49477633 -67.91015625 102.43359375 C-67.79799647 99.2401961 -67.68897443 96.04681123 -67.58837891 92.85302734 C-67.22538737 81.52946225 -66.65494051 70.32073083 -65.13671875 59.0859375 C-64.95793686 57.75983963 -64.95793686 57.75983963 -64.77554321 56.4069519 C-62.24372342 39.06207822 -55.12155189 23.04594995 -40.9609375 12.1171875 C-28.07509054 3.53900119 -15.33988115 -0.26186367 0 0 Z" transform="translate(359.5625,324.875)"/>
226
+ <path fill="white" d="M0 0 C9.89334431 8.68950817 14.30034619 23.01452361 15.24373245 35.79419899 C15.49099471 41.77148785 15.42334062 47.74978768 15.37109375 53.73046875 C15.36548489 55.63859724 15.36122091 57.54673011 15.35823059 59.4548645 C15.34688325 64.42950786 15.31750548 69.40388024 15.28411865 74.37841797 C15.25319735 79.47359555 15.23967854 84.56881775 15.22460938 89.6640625 C15.19262409 99.62643911 15.13994121 109.58854505 15.078125 119.55078125 C3.528125 119.55078125 -8.021875 119.55078125 -19.921875 119.55078125 C-19.97085938 114.4203125 -20.01984375 109.28984375 -20.0703125 104.00390625 C-20.10574492 100.73175245 -20.14173112 97.45962313 -20.1796875 94.1875 C-20.23973228 89.00671097 -20.29785091 83.82595572 -20.34375 78.64501953 C-20.38093086 74.46275871 -20.42737419 70.28068941 -20.47993851 66.09859467 C-20.49830992 64.51204578 -20.51347972 62.92545612 -20.52521896 61.3388443 C-20.22141003 42.05064114 -20.22141003 42.05064114 -28.921875 25.55078125 C-33.2097739 21.98892101 -37.29807009 19.87523153 -42.921875 19.55078125 C-43.79714844 19.48890625 -44.67242188 19.42703125 -45.57421875 19.36328125 C-54.66067243 18.98906437 -62.9621186 20.4280254 -69.859375 26.73828125 C-76.14726535 33.73487866 -78.0525657 41.92333342 -78.12719727 51.07324219 C-78.13709686 51.82485123 -78.14699646 52.57646027 -78.15719604 53.35084534 C-78.18871966 55.82891721 -78.21353223 58.30700823 -78.23828125 60.78515625 C-78.25885867 62.50580334 -78.27985536 64.22644545 -78.30125427 65.94708252 C-78.35639351 70.47125217 -78.40583867 74.99546682 -78.45410156 79.51971436 C-78.51321858 84.95049451 -78.57940167 90.38119259 -78.64440155 95.81190491 C-78.74230855 104.0581468 -78.83123469 112.30444185 -78.921875 120.55078125 C-90.801875 120.55078125 -102.681875 120.55078125 -114.921875 120.55078125 C-114.921875 77.65078125 -114.921875 34.75078125 -114.921875 -9.44921875 C-103.701875 -9.44921875 -92.481875 -9.44921875 -80.921875 -9.44921875 C-79.96000569 -5.60174152 -79.61528473 -2.14754023 -79.359375 1.80078125 C-79.27558594 3.0640625 -79.19179688 4.32734375 -79.10546875 5.62890625 C-79.04488281 6.593125 -78.98429688 7.55734375 -78.921875 8.55078125 C-78.48875 7.72578125 -78.055625 6.90078125 -77.609375 6.05078125 C-71.50314599 -3.01214812 -59.57220635 -8.76116827 -49.16015625 -11.05859375 C-31.06340614 -13.24155516 -14.8555768 -11.20207112 0 0 Z" transform="translate(613.921875,481.44921875)"/>
227
+ <path fill="white" d="M0 0 C1.53906801 1.53906801 1.16955456 2.91263628 1.1875 5.0625 C1.1451715 9.92322255 0.65815533 14.68227908 0.0625 19.5 C-0.02427002 20.20648682 -0.11104004 20.91297363 -0.20043945 21.64086914 C-0.86920125 26.7384025 -0.86920125 26.7384025 -2 29 C-2.96808594 28.84144531 -3.93617188 28.68289063 -4.93359375 28.51953125 C-9.31081865 27.89956204 -13.64601408 27.74275212 -18.0625 27.6875 C-18.83916016 27.65849609 -19.61582031 27.62949219 -20.41601562 27.59960938 C-25.75566236 27.54083257 -28.83098013 28.36372264 -33 32 C-37.31404494 38.3211768 -37.31404494 38.3211768 -37 53 C-25.78 53 -14.56 53 -3 53 C-3 62.57 -3 72.14 -3 82 C-14.55 82 -26.1 82 -38 82 C-38 115 -38 148 -38 182 C-49.55 182 -61.1 182 -73 182 C-73 149 -73 116 -73 82 C-79.93 82 -86.86 82 -94 82 C-94 72.43 -94 62.86 -94 53 C-87.07 53 -80.14 53 -73 53 C-73.04125 50.6075 -73.0825 48.215 -73.125 45.75 C-73.17827085 31.60875021 -70.96095372 19.48048613 -61.0078125 8.81640625 C-54.5981324 3.0177657 -47.30019677 0.02408307 -39 -2 C-38.37625488 -2.17200928 -37.75250977 -2.34401855 -37.10986328 -2.52124023 C-25.33848182 -5.19234404 -11.53065338 -2.96722147 0 0 Z" transform="translate(486,419)"/>
228
+ </svg>`;
229
+ function getFaviconSvg() {
230
+ return FAVICON_SVG;
231
+ }
232
+ var VOICE_CALLBACKS = ["ice", "ace", "pie", "dice", "notify"];
233
+ var NOTIFICATION_EVENTS = ["dice", "notify"];
234
+ function isVoiceCallback(functionName) {
235
+ return VOICE_CALLBACKS.includes(functionName);
236
+ }
237
+ function isNotificationEvent(functionName) {
238
+ return NOTIFICATION_EVENTS.includes(functionName);
239
+ }
240
+ function extractFunctionName(path5, body) {
241
+ if (body?.event && isVoiceCallback(body.event)) {
242
+ return body.event;
243
+ }
244
+ const segments = path5.split("/").filter((s) => s && s !== "*");
245
+ if (segments.length === 1 && isVoiceCallback(segments[0])) {
246
+ return segments[0];
247
+ }
248
+ return segments[segments.length - 1] || "default";
249
+ }
250
+ function generateRequestId() {
251
+ return `req_${Date.now()}_${Math.random().toString(36).substring(7)}`;
252
+ }
253
+ function findFunctionPath() {
254
+ const fs4 = requireCjs2("fs");
255
+ const distPath = nodePath.join(process.cwd(), "dist", "function.js");
256
+ const rootPath = nodePath.join(process.cwd(), "function.js");
257
+ if (fs4.existsSync(distPath)) {
258
+ return distPath;
259
+ }
260
+ return rootPath;
261
+ }
262
+ function formatSvamlResponse(result, functionName) {
263
+ if (!result || typeof result !== "object") {
264
+ throw new Error(`Voice callback ${functionName} must return a valid SVAML object`);
265
+ }
266
+ const svaml = result;
267
+ if (!svaml.action && !svaml.instructions) {
268
+ throw new Error(`Voice callback ${functionName} must return SVAML with an action or instructions`);
269
+ }
270
+ if (!svaml.instructions) {
271
+ svaml.instructions = [];
272
+ }
273
+ return {
274
+ statusCode: 200,
275
+ headers: { "Content-Type": "application/json" },
276
+ body: svaml
277
+ };
278
+ }
279
+ function formatCustomResponse(result) {
280
+ if (!result || typeof result !== "object") {
281
+ return {
282
+ statusCode: 200,
283
+ headers: { "Content-Type": "application/json" },
284
+ body: result
285
+ };
286
+ }
287
+ const response = result;
288
+ if (!response.statusCode) {
289
+ return {
290
+ statusCode: 200,
291
+ headers: { "Content-Type": "application/json" },
292
+ body: result
293
+ };
294
+ }
295
+ return {
296
+ statusCode: response.statusCode,
297
+ headers: response.headers,
298
+ body: response.body
299
+ };
300
+ }
301
+ function validateVoiceRequest(body) {
302
+ if (!body || typeof body !== "object") {
303
+ return {
304
+ valid: false,
305
+ error: "Missing request body",
306
+ expectedEvents: [...VOICE_CALLBACKS]
307
+ };
308
+ }
309
+ const data = body;
310
+ if (!data.event) {
311
+ return {
312
+ valid: false,
313
+ error: "Missing event type in request body",
314
+ expectedEvents: [...VOICE_CALLBACKS]
315
+ };
316
+ }
317
+ if (!data.callId) {
318
+ return {
319
+ valid: false,
320
+ error: "Missing callId in request body"
321
+ };
322
+ }
323
+ return { valid: true };
324
+ }
325
+ var noOpCache = {
326
+ set: async () => {
327
+ },
328
+ get: async () => null,
329
+ has: async () => false,
330
+ delete: async () => false,
331
+ extend: async () => false,
332
+ keys: async () => [],
333
+ getMany: async () => ({})
334
+ };
335
+ function buildBaseContext(req, config = {}) {
336
+ return {
337
+ requestId: req.headers["x-request-id"] || generateRequestId(),
338
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
339
+ env: process.env,
340
+ config: {
341
+ projectId: config.projectId || "unknown",
342
+ functionName: config.functionName || "unknown",
343
+ environment: config.environment || "development",
344
+ variables: config.variables
345
+ },
346
+ cache: noOpCache
347
+ };
348
+ }
349
+ async function handleVoiceCallback(functionName, userFunction, context, callbackData, logger) {
350
+ const handler = userFunction[functionName];
351
+ if (!handler || typeof handler !== "function") {
352
+ throw new Error(`Function '${functionName}' not found in function.js`);
353
+ }
354
+ let result;
355
+ switch (functionName) {
356
+ case "ice":
357
+ result = await handler?.(context, callbackData);
358
+ break;
359
+ case "ace":
360
+ result = await handler?.(context, callbackData);
361
+ break;
362
+ case "pie":
363
+ result = await handler?.(context, callbackData);
364
+ break;
365
+ case "dice":
366
+ result = await handler?.(context, callbackData);
367
+ break;
368
+ case "notify":
369
+ result = await handler?.(context, callbackData);
370
+ break;
371
+ default:
372
+ throw new Error(`Unknown voice callback: ${functionName}`);
373
+ }
374
+ if (logger) {
375
+ logger("Function result:", result);
376
+ }
377
+ if (isNotificationEvent(functionName)) {
378
+ if (logger) {
379
+ logger(`${functionName.toUpperCase()} callback completed`);
380
+ }
381
+ return {
382
+ statusCode: 200,
383
+ headers: { "Content-Type": "application/json" },
384
+ body: {}
385
+ };
386
+ }
387
+ return formatSvamlResponse(result, functionName);
388
+ }
389
+ async function handleCustomEndpoint(functionName, userFunction, context, request, logger) {
390
+ const handler = userFunction[functionName];
391
+ if (!handler || typeof handler !== "function") {
392
+ throw new Error(`Function '${functionName}' not found in function.js`);
393
+ }
394
+ const result = await handler(context, request);
395
+ if (logger) {
396
+ logger("Function result:", result);
397
+ }
398
+ return formatCustomResponse(result);
399
+ }
400
+ function createApp(options = {}) {
401
+ const express = requireCjs2("express");
402
+ const app = express();
403
+ if (options.staticDir) {
404
+ app.use(express.static(options.staticDir, {
405
+ index: false,
406
+ // Don't serve index.html for /, landing page handles that
407
+ dotfiles: "ignore"
408
+ }));
409
+ }
410
+ const jsonOptions = options.jsonParsingOptions || {
411
+ limit: "10mb",
412
+ allowJson5: true,
413
+ camelCase: {
414
+ deep: true,
415
+ stopPaths: ["custom"],
416
+ exclude: []
417
+ }
418
+ };
419
+ setupJsonParsing(app, jsonOptions);
420
+ app.use(express.urlencoded({ extended: true, limit: "10mb" }));
421
+ return app;
422
+ }
423
+ function setupRequestHandler(app, options = {}) {
424
+ const { loadUserFunction = async () => {
425
+ const functionPath = findFunctionPath();
426
+ const functionUrl = pathToFileURL(functionPath).href;
427
+ const module = await import(functionUrl);
428
+ return module.default || module;
429
+ }, buildContext = buildBaseContext, logger = console.log, landingPageEnabled = true, onRequestStart = () => {
430
+ }, onRequestEnd = () => {
431
+ } } = options;
432
+ app.use("/{*splat}", async (req, res) => {
433
+ const startTime = Date.now();
434
+ if ((req.method === "GET" || req.method === "HEAD") && req.originalUrl === "/favicon.ico") {
435
+ const svg = getFaviconSvg();
436
+ res.type("image/svg+xml").send(svg);
437
+ return;
438
+ }
439
+ if (req.method === "GET" && req.path === "/" && landingPageEnabled) {
440
+ const acceptHeader = req.headers.accept || "";
441
+ if (acceptHeader.includes("text/html")) {
442
+ const html = getLandingPageHtml();
443
+ res.type("html").send(html);
444
+ return;
445
+ }
446
+ }
447
+ try {
448
+ const functionName = extractFunctionName(req.baseUrl, req.body);
449
+ logger(`[${(/* @__PURE__ */ new Date()).toISOString()}] ${req.method} ${req.path} -> ${functionName}`);
450
+ onRequestStart({ functionName, req });
451
+ const context = buildContext(req);
452
+ const userFunction = await Promise.resolve(loadUserFunction());
453
+ let response;
454
+ if (isVoiceCallback(functionName)) {
455
+ const validation = validateVoiceRequest(req.body);
456
+ if (!validation.valid) {
457
+ res.status(400).json({
458
+ error: validation.error,
459
+ ...validation.expectedEvents && { expectedEvents: validation.expectedEvents }
460
+ });
461
+ return;
462
+ }
463
+ response = await handleVoiceCallback(functionName, userFunction, context, req.body, logger);
464
+ } else {
465
+ const request = {
466
+ method: req.method,
467
+ path: req.path,
468
+ query: req.query,
469
+ headers: req.headers,
470
+ body: req.body,
471
+ params: req.params
472
+ };
473
+ response = await handleCustomEndpoint(functionName, userFunction, context, request, logger);
474
+ }
475
+ res.status(response.statusCode);
476
+ if (response.headers) {
477
+ for (const [key, value] of Object.entries(response.headers)) {
478
+ res.setHeader(key, value);
479
+ }
480
+ }
481
+ const contentType = response.headers?.["Content-Type"];
482
+ const isJsonContent = contentType?.includes("application/json");
483
+ const isHtmlContent = contentType?.includes("text/html");
484
+ if (response.body === void 0) {
485
+ res.end();
486
+ } else if (isJsonContent) {
487
+ res.json(response.body);
488
+ } else if (isHtmlContent) {
489
+ res.send(String(response.body));
490
+ } else {
491
+ res.send(response.body);
492
+ }
493
+ const duration = Date.now() - startTime;
494
+ logger(`[${(/* @__PURE__ */ new Date()).toISOString()}] Response sent: ${response.statusCode} (${duration}ms)`);
495
+ onRequestEnd({
496
+ functionName,
497
+ req,
498
+ response,
499
+ duration,
500
+ statusCode: response.statusCode
501
+ });
502
+ } catch (error) {
503
+ const duration = Date.now() - startTime;
504
+ logger("Function execution error:", {
505
+ error: error.message,
506
+ stack: error.stack,
507
+ function: extractFunctionName(req.path, req.body)
508
+ });
509
+ res.status(500).json({
510
+ error: "Internal server error",
511
+ message: error.message,
512
+ ...process.env.NODE_ENV === "development" && { stack: error.stack }
513
+ });
514
+ onRequestEnd({
515
+ functionName: extractFunctionName(req.path, req.body),
516
+ req,
517
+ error,
518
+ duration,
519
+ statusCode: 500
520
+ });
521
+ }
522
+ });
523
+ }
524
+
525
+ // ../runtime-shared/dist/utils/templateRender.js
526
+ import fs from "fs";
527
+ import path from "path";
528
+
529
+ // ../runtime-shared/dist/utils/versionExtractor.js
530
+ import fs2 from "fs";
531
+ import path2 from "path";
532
+
533
+ // ../runtime-shared/dist/utils/functionLoader.js
534
+ import path3 from "path";
535
+
536
+ // src/cache/local.ts
537
+ var globalCache = /* @__PURE__ */ new Map();
538
+ var LocalCache = class {
539
+ cache;
540
+ constructor() {
541
+ this.cache = globalCache;
542
+ }
543
+ async set(key, value, ttlSeconds = 3600) {
544
+ this.cache.set(key, {
545
+ value,
546
+ expiresAt: Date.now() + ttlSeconds * 1e3
547
+ });
548
+ }
549
+ async get(key) {
550
+ const item = this.cache.get(key);
551
+ if (!item || Date.now() > item.expiresAt) {
552
+ this.cache.delete(key);
553
+ return null;
554
+ }
555
+ return item.value;
556
+ }
557
+ async has(key) {
558
+ const value = await this.get(key);
559
+ return value !== null;
560
+ }
561
+ async delete(key) {
562
+ return this.cache.delete(key);
563
+ }
564
+ async extend(key, additionalSeconds) {
565
+ const item = this.cache.get(key);
566
+ if (!item || Date.now() > item.expiresAt) {
567
+ return false;
568
+ }
569
+ item.expiresAt += additionalSeconds * 1e3;
570
+ return true;
571
+ }
572
+ async keys(pattern = "*") {
573
+ const allKeys = Array.from(this.cache.keys());
574
+ const now = Date.now();
575
+ for (const key of allKeys) {
576
+ const item = this.cache.get(key);
577
+ if (item && now > item.expiresAt) {
578
+ this.cache.delete(key);
579
+ }
580
+ }
581
+ const validKeys = Array.from(this.cache.keys());
582
+ if (pattern === "*") {
583
+ return validKeys;
584
+ }
585
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
586
+ return validKeys.filter((key) => regex.test(key));
587
+ }
588
+ async getMany(keys) {
589
+ const results = {};
590
+ for (const key of keys) {
591
+ results[key] = await this.get(key);
592
+ }
593
+ return results;
594
+ }
595
+ /**
596
+ * Clear all entries from the cache
597
+ * (Utility method for testing)
598
+ */
599
+ async clear() {
600
+ this.cache.clear();
601
+ }
602
+ /**
603
+ * Get the number of entries in the cache
604
+ * (Utility method for debugging)
605
+ */
606
+ get size() {
607
+ return this.cache.size;
608
+ }
609
+ };
610
+ function createCacheClient(_projectId, _functionName) {
611
+ return new LocalCache();
612
+ }
613
+
614
+ // src/bin/sinch-runtime.ts
615
+ var requireCjs3 = createRequire3(import.meta.url);
616
+ function findFunctionPath3() {
617
+ const distPath = path4.join(process.cwd(), "dist", "function.js");
618
+ const rootPath = path4.join(process.cwd(), "function.js");
619
+ if (fs3.existsSync(distPath)) {
620
+ return distPath;
621
+ }
622
+ return rootPath;
623
+ }
624
+ function loadRuntimeConfig() {
625
+ return {
626
+ projectId: process.env.PROJECT_ID || process.env.SINCH_PROJECT_ID || "local-project",
627
+ projectName: process.env.PROJECT_NAME || process.env.SINCH_PROJECT_NAME || "Local Function",
628
+ functionId: process.env.FUNCTION_ID || process.env.SINCH_FUNCTION_ID || "local-dev"
629
+ };
630
+ }
631
+ function buildLocalContext(req, runtimeConfig) {
632
+ const baseContext = buildBaseContext(req);
633
+ const cache = createCacheClient();
634
+ return {
635
+ ...baseContext,
636
+ cache,
637
+ env: process.env,
638
+ config: {
639
+ projectId: runtimeConfig.projectId,
640
+ functionName: runtimeConfig.functionId,
641
+ environment: "development",
642
+ variables: process.env
643
+ }
644
+ // Sinch clients would be added here if SDK is available
645
+ };
646
+ }
647
+ function displayStartupInfo(config, verbose, _port) {
648
+ if (verbose) {
649
+ console.log("\n=== SINCH FUNCTIONS CONFIGURATION ===");
650
+ console.log("\nSystem Fields:");
651
+ console.log(` Project Name: ${config.projectName}`);
652
+ console.log(` Project ID: ${config.projectId}`);
653
+ console.log(` Function ID: ${config.functionId}`);
654
+ console.log(` Environment: ${process.env.NODE_ENV || "development"}`);
655
+ displayEnvironmentVariables();
656
+ displayApplicationCredentials();
657
+ console.log("\n========================================\n");
658
+ }
659
+ }
660
+ function displayEnvironmentVariables() {
661
+ console.log("\nEnvironment Variables:");
662
+ try {
663
+ const envPath = path4.join(process.cwd(), ".env");
664
+ if (!fs3.existsSync(envPath)) {
665
+ console.log(" (no .env file found)");
666
+ return;
667
+ }
668
+ const envContent = fs3.readFileSync(envPath, "utf8");
669
+ const envLines = envContent.split("\n");
670
+ const variables = [];
671
+ const secrets = [];
672
+ for (const line of envLines) {
673
+ const trimmedLine = line.trim();
674
+ if (!trimmedLine || trimmedLine.startsWith("#")) continue;
675
+ const [key, ...valueParts] = trimmedLine.split("=");
676
+ if (!key) continue;
677
+ const envKey = key.trim();
678
+ const envValue = valueParts.join("=").trim();
679
+ if (envValue === "" && process.env[envKey]) {
680
+ secrets.push({ key: envKey, status: "[LOADED]" });
681
+ } else if (envValue !== "") {
682
+ variables.push({ key: envKey, value: process.env[envKey] || envValue });
683
+ } else {
684
+ secrets.push({ key: envKey, status: "[MISSING]" });
685
+ }
686
+ }
687
+ if (variables.length > 0) {
688
+ console.log("\n Variables:");
689
+ for (const { key, value } of variables) {
690
+ console.log(` ${key}: ${value}`);
691
+ }
692
+ }
693
+ if (secrets.length > 0) {
694
+ console.log("\n Secrets:");
695
+ for (const { key, status } of secrets) {
696
+ console.log(` ${key}: ${status}`);
697
+ }
698
+ }
699
+ if (variables.length === 0 && secrets.length === 0) {
700
+ console.log(" (no environment variables defined in .env)");
701
+ }
702
+ } catch {
703
+ console.log(" (could not read .env file)");
704
+ }
705
+ }
706
+ function displayApplicationCredentials() {
707
+ console.log("\nApplication Credentials:");
708
+ const hasKey = process.env.VOICE_APPLICATION_KEY;
709
+ const hasSecret = process.env.VOICE_APPLICATION_SECRET;
710
+ if (hasKey && hasSecret) {
711
+ console.log(` Application Key: ${process.env.VOICE_APPLICATION_KEY}`);
712
+ console.log(" Application Secret: [LOADED]");
713
+ console.log(" Voice features: ENABLED");
714
+ } else if (hasKey && !hasSecret) {
715
+ console.log(` Application Key: ${process.env.VOICE_APPLICATION_KEY}`);
716
+ console.log(" Application Secret: [MISSING]");
717
+ console.log(" Voice features: DISABLED");
718
+ console.log(' Tip: Run "sinch auth login" to configure secrets');
719
+ } else {
720
+ console.log(" Not configured");
721
+ console.log(" Voice features: DISABLED");
722
+ console.log(' Tip: Add VOICE_APPLICATION_KEY to .env and run "sinch auth login"');
723
+ }
724
+ }
725
+ async function displayDetectedFunctions() {
726
+ try {
727
+ const functionPath = findFunctionPath3();
728
+ if (!fs3.existsSync(functionPath)) return;
729
+ const functionUrl = pathToFileURL2(functionPath).href;
730
+ const module = await import(functionUrl);
731
+ const userFunction = module.default || module;
732
+ const functions = Object.keys(userFunction);
733
+ if (functions.length > 0) {
734
+ console.log("\nDetected functions in function.js:");
735
+ for (const fn of functions) {
736
+ const type = isVoiceCallback(fn) ? "voice" : "custom";
737
+ console.log(` - ${fn} (${type})`);
738
+ }
739
+ }
740
+ } catch {
741
+ }
742
+ }
743
+ async function main() {
744
+ const args = process.argv.slice(2);
745
+ const verbose = args.includes("--verbose") || args.includes("-v") || process.env.VERBOSE === "true";
746
+ const portArg = args.indexOf("--port");
747
+ const port = portArg !== -1 ? parseInt(args[portArg + 1], 10) : parseInt(process.env.PORT || "3000", 10);
748
+ try {
749
+ const dotenv = requireCjs3("dotenv");
750
+ dotenv.config({ path: ".env.development" });
751
+ dotenv.config();
752
+ } catch {
753
+ }
754
+ const config = loadRuntimeConfig();
755
+ const staticDir = process.env.STATIC_DIR;
756
+ const app = createApp({ staticDir });
757
+ setupRequestHandler(app, {
758
+ loadUserFunction: async () => {
759
+ const functionPath = findFunctionPath3();
760
+ const functionUrl = pathToFileURL2(functionPath).href;
761
+ const module = await import(functionUrl);
762
+ return module.default || module;
763
+ },
764
+ buildContext: (req) => buildLocalContext(req, config),
765
+ logger: console.log,
766
+ onRequestStart: ({ req }) => {
767
+ if (verbose) {
768
+ console.log("Request headers:", req.headers);
769
+ console.log("Request body:", req.body);
770
+ }
771
+ },
772
+ onRequestEnd: ({ functionName: fn, duration, statusCode }) => {
773
+ if (verbose) {
774
+ console.log(`Function: ${fn}, Duration: ${duration}ms, Status: ${statusCode}`);
775
+ }
776
+ }
777
+ });
778
+ app.get("/_health", (_req, res) => {
779
+ res.json({
780
+ status: "healthy",
781
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
782
+ uptime: process.uptime()
783
+ });
784
+ });
785
+ displayStartupInfo(config, verbose, port);
786
+ app.listen(port, () => {
787
+ console.log(`Function server running on http://localhost:${port}`);
788
+ console.log("\nTest endpoints:");
789
+ console.log(` ICE: POST http://localhost:${port}/ice`);
790
+ console.log(` PIE: POST http://localhost:${port}/pie`);
791
+ console.log(` ACE: POST http://localhost:${port}/ace`);
792
+ console.log(` DICE: POST http://localhost:${port}/dice`);
793
+ void displayDetectedFunctions().then(() => {
794
+ if (!verbose) {
795
+ console.log("\nTip: Set VERBOSE=true or use --verbose for detailed output");
796
+ }
797
+ });
798
+ });
799
+ }
800
+ main().catch((error) => {
801
+ console.error("Failed to start server:", error);
802
+ process.exit(1);
803
+ });
804
+ process.on("SIGTERM", () => {
805
+ console.log("SIGTERM signal received: closing HTTP server");
806
+ process.exit(0);
807
+ });
808
+ process.on("SIGINT", () => {
809
+ console.log("\nSIGINT signal received: closing HTTP server");
810
+ process.exit(0);
811
+ });
812
+ //# sourceMappingURL=sinch-runtime.js.map