@resonatehq/supabase 0.1.1 → 0.1.3
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.
- package/dist/index.js +18 -11
- package/package.json +2 -2
- package/src/index.ts +97 -86
package/dist/index.js
CHANGED
|
@@ -3,6 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Resonate = void 0;
|
|
4
4
|
const sdk_1 = require("@resonatehq/sdk");
|
|
5
5
|
const encryptor_1 = require("@resonatehq/sdk/dist/src/encryptor");
|
|
6
|
+
const options_1 = require("@resonatehq/sdk/dist/src/options");
|
|
7
|
+
const tracer_1 = require("@resonatehq/sdk/dist/src/tracer");
|
|
6
8
|
class Resonate {
|
|
7
9
|
constructor({ verbose = false, encryptor = undefined, } = {}) {
|
|
8
10
|
this.registry = new sdk_1.Registry();
|
|
@@ -45,6 +47,8 @@ class Resonate {
|
|
|
45
47
|
});
|
|
46
48
|
}
|
|
47
49
|
const encoder = new sdk_1.JsonEncoder();
|
|
50
|
+
const clock = new sdk_1.WallClock();
|
|
51
|
+
const tracer = new tracer_1.NoopTracer();
|
|
48
52
|
const network = new sdk_1.HttpNetwork({
|
|
49
53
|
headers: {},
|
|
50
54
|
timeout: 60 * 1000, // 60s
|
|
@@ -52,22 +56,25 @@ class Resonate {
|
|
|
52
56
|
verbose: this.verbose,
|
|
53
57
|
});
|
|
54
58
|
const resonateInner = new sdk_1.ResonateInner({
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
clock: new sdk_1.WallClock(),
|
|
58
|
-
dependencies: this.dependencies,
|
|
59
|
-
handler: new sdk_1.Handler(network, encoder, this.encryptor),
|
|
60
|
-
heartbeat: new sdk_1.NoopHeartbeat(),
|
|
61
|
-
network,
|
|
59
|
+
unicast: url,
|
|
60
|
+
anycast: url,
|
|
62
61
|
pid: `pid-${Math.random().toString(36).substring(7)}`,
|
|
62
|
+
ttl: 30 * 1000,
|
|
63
|
+
clock,
|
|
64
|
+
network,
|
|
65
|
+
handler: new sdk_1.Handler(network, encoder, this.encryptor),
|
|
63
66
|
registry: this.registry,
|
|
64
|
-
|
|
65
|
-
|
|
67
|
+
heartbeat: new sdk_1.NoopHeartbeat(),
|
|
68
|
+
dependencies: this.dependencies,
|
|
69
|
+
optsBuilder: new options_1.OptionsBuilder({
|
|
70
|
+
match: (_) => url,
|
|
71
|
+
}),
|
|
66
72
|
verbose: this.verbose,
|
|
73
|
+
tracer,
|
|
67
74
|
});
|
|
68
75
|
const task = { kind: "unclaimed", task: body.task };
|
|
69
76
|
const completion = new Promise((resolve) => {
|
|
70
|
-
resonateInner.process(task, (error, status) => {
|
|
77
|
+
resonateInner.process(tracer.startSpan(task.task.rootPromiseId, clock.now()), task, (error, status) => {
|
|
71
78
|
if (error || !status) {
|
|
72
79
|
resolve(new Response(JSON.stringify({
|
|
73
80
|
error: "Task processing failed",
|
|
@@ -123,7 +130,7 @@ function buildForwardedURL(req) {
|
|
|
123
130
|
// Dev: We need the port (e.g., :54321).
|
|
124
131
|
// Prod: We rarely need :443 explicitly in the URL string.
|
|
125
132
|
const forwardedPort = headers.get("x-forwarded-port");
|
|
126
|
-
const port =
|
|
133
|
+
const port = forwardedHost && forwardedPort ? `:${forwardedPort}` : "";
|
|
127
134
|
// 4. Path Logic
|
|
128
135
|
// Dev: "x-forwarded-path" contains the full path (/functions/v1/hello-world)
|
|
129
136
|
// Prod: We must use url.pathname.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@resonatehq/supabase",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "Resonate FaaS handler for Supabase Edge Functions (TypeScript)",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/resonatehq/resonate-faas-supabase-ts"
|
|
@@ -29,6 +29,6 @@
|
|
|
29
29
|
"typescript": "^5.9.3"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@resonatehq/sdk": "^0.
|
|
32
|
+
"@resonatehq/sdk": "^0.9.3"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,8 @@ import {
|
|
|
13
13
|
type Encryptor,
|
|
14
14
|
NoopEncryptor,
|
|
15
15
|
} from "@resonatehq/sdk/dist/src/encryptor";
|
|
16
|
+
import { OptionsBuilder } from "@resonatehq/sdk/dist/src/options";
|
|
17
|
+
import { NoopTracer } from "@resonatehq/sdk/dist/src/tracer";
|
|
16
18
|
|
|
17
19
|
export class Resonate {
|
|
18
20
|
private registry = new Registry();
|
|
@@ -107,6 +109,8 @@ export class Resonate {
|
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
const encoder = new JsonEncoder();
|
|
112
|
+
const clock = new WallClock();
|
|
113
|
+
const tracer = new NoopTracer();
|
|
110
114
|
const network = new HttpNetwork({
|
|
111
115
|
headers: {},
|
|
112
116
|
timeout: 60 * 1000, // 60s
|
|
@@ -115,68 +119,75 @@ export class Resonate {
|
|
|
115
119
|
});
|
|
116
120
|
|
|
117
121
|
const resonateInner = new ResonateInner({
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
clock: new WallClock(),
|
|
121
|
-
dependencies: this.dependencies,
|
|
122
|
-
handler: new Handler(network, encoder, this.encryptor),
|
|
123
|
-
heartbeat: new NoopHeartbeat(),
|
|
124
|
-
network,
|
|
122
|
+
unicast: url,
|
|
123
|
+
anycast: url,
|
|
125
124
|
pid: `pid-${Math.random().toString(36).substring(7)}`,
|
|
125
|
+
ttl: 30 * 1000,
|
|
126
|
+
clock,
|
|
127
|
+
network,
|
|
128
|
+
handler: new Handler(network, encoder, this.encryptor),
|
|
126
129
|
registry: this.registry,
|
|
127
|
-
|
|
128
|
-
|
|
130
|
+
heartbeat: new NoopHeartbeat(),
|
|
131
|
+
dependencies: this.dependencies,
|
|
132
|
+
optsBuilder: new OptionsBuilder({
|
|
133
|
+
match: (_: string): string => url,
|
|
134
|
+
}),
|
|
129
135
|
verbose: this.verbose,
|
|
136
|
+
tracer,
|
|
130
137
|
});
|
|
131
138
|
|
|
132
139
|
const task: Task = { kind: "unclaimed", task: body.task };
|
|
133
140
|
|
|
134
141
|
const completion: Promise<Response> = new Promise((resolve) => {
|
|
135
|
-
resonateInner.process(
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
142
|
+
resonateInner.process(
|
|
143
|
+
tracer.startSpan(task.task.rootPromiseId, clock.now()),
|
|
144
|
+
task,
|
|
145
|
+
(error, status) => {
|
|
146
|
+
if (error || !status) {
|
|
147
|
+
resolve(
|
|
148
|
+
new Response(
|
|
149
|
+
JSON.stringify({
|
|
150
|
+
error: "Task processing failed",
|
|
151
|
+
details: { error, status },
|
|
152
|
+
}),
|
|
153
|
+
{
|
|
154
|
+
status: 500,
|
|
155
|
+
},
|
|
156
|
+
),
|
|
157
|
+
);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (status.kind === "completed") {
|
|
162
|
+
resolve(
|
|
163
|
+
new Response(
|
|
164
|
+
JSON.stringify({
|
|
165
|
+
status: "completed",
|
|
166
|
+
result: status.promise.value,
|
|
167
|
+
requestUrl: url,
|
|
168
|
+
}),
|
|
169
|
+
{
|
|
170
|
+
status: 200,
|
|
171
|
+
},
|
|
172
|
+
),
|
|
173
|
+
);
|
|
174
|
+
return;
|
|
175
|
+
} else if (status.kind === "suspended") {
|
|
176
|
+
resolve(
|
|
177
|
+
new Response(
|
|
178
|
+
JSON.stringify({
|
|
179
|
+
status: "suspended",
|
|
180
|
+
requestUrl: url,
|
|
181
|
+
}),
|
|
182
|
+
{
|
|
183
|
+
status: 200,
|
|
184
|
+
},
|
|
185
|
+
),
|
|
186
|
+
);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
);
|
|
180
191
|
});
|
|
181
192
|
return completion;
|
|
182
193
|
} catch (error) {
|
|
@@ -191,36 +202,36 @@ export class Resonate {
|
|
|
191
202
|
}
|
|
192
203
|
|
|
193
204
|
function buildForwardedURL(req: Request) {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
205
|
+
const headers = req.headers;
|
|
206
|
+
const url = new URL(req.url);
|
|
207
|
+
|
|
208
|
+
// 1. Hostname Logic
|
|
209
|
+
// Dev: "x-forwarded-host" is present (e.g., 127.0.0.1)
|
|
210
|
+
// Prod: "x-forwarded-host" is missing, so we use url.hostname (e.g., project.supabase.co)
|
|
211
|
+
const forwardedHost = headers.get("x-forwarded-host");
|
|
212
|
+
const host = forwardedHost ?? url.hostname;
|
|
213
|
+
|
|
214
|
+
// 2. Protocol Logic
|
|
215
|
+
// Always prefer "x-forwarded-proto" (usually https in prod), fallback to "http"
|
|
216
|
+
const proto = headers.get("x-forwarded-proto") ?? "http";
|
|
217
|
+
|
|
218
|
+
// 3. Port Logic
|
|
219
|
+
// Dev: We need the port (e.g., :54321).
|
|
220
|
+
// Prod: We rarely need :443 explicitly in the URL string.
|
|
221
|
+
const forwardedPort = headers.get("x-forwarded-port");
|
|
222
|
+
const port = forwardedHost && forwardedPort ? `:${forwardedPort}` : "";
|
|
223
|
+
|
|
224
|
+
// 4. Path Logic
|
|
225
|
+
// Dev: "x-forwarded-path" contains the full path (/functions/v1/hello-world)
|
|
226
|
+
// Prod: We must use url.pathname.
|
|
227
|
+
let path = headers.get("x-forwarded-path") ?? url.pathname;
|
|
228
|
+
|
|
229
|
+
// 5. Production Path Fix
|
|
230
|
+
// In Prod, the internal req.url often strips '/functions/v1'.
|
|
231
|
+
// We re-add it if we are in Prod (no forwardedHost) and it's missing.
|
|
232
|
+
if (!forwardedHost && !path.startsWith("/functions/v1")) {
|
|
233
|
+
path = `/functions/v1${path}`;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return `${proto}://${host}${port}${path}`;
|
|
226
237
|
}
|