@resonatehq/supabase 0.1.5 → 0.1.6
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/.github/workflows/ci.yaml +4 -7
- package/dist/index.d.ts +14 -2
- package/dist/index.js +47 -33
- package/package.json +2 -2
- package/src/index.ts +62 -26
- package/tsconfig.json +3 -2
|
@@ -27,13 +27,10 @@ jobs:
|
|
|
27
27
|
steps:
|
|
28
28
|
- uses: actions/checkout@v4
|
|
29
29
|
|
|
30
|
-
- name: Set up
|
|
31
|
-
uses:
|
|
30
|
+
- name: Set up Deno
|
|
31
|
+
uses: denoland/setup-deno@v1
|
|
32
32
|
with:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- name: install
|
|
36
|
-
run: bun install
|
|
33
|
+
deno-version: v1.x
|
|
37
34
|
|
|
38
35
|
- name: check linting
|
|
39
|
-
run:
|
|
36
|
+
run: deno run check
|
package/dist/index.d.ts
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
-
import { type Func } from "@resonatehq/sdk";
|
|
1
|
+
import { Context, type Func } from "@resonatehq/sdk";
|
|
2
2
|
import { type Encryptor } from "@resonatehq/sdk/dist/src/encryptor";
|
|
3
|
+
type OnTerminateCallback = (result: {
|
|
4
|
+
status: "completed";
|
|
5
|
+
data?: any;
|
|
6
|
+
} | {
|
|
7
|
+
status: "suspended";
|
|
8
|
+
result: string[];
|
|
9
|
+
}) => Promise<void>;
|
|
10
|
+
export { Context };
|
|
3
11
|
export declare class Resonate {
|
|
4
12
|
private registry;
|
|
5
13
|
private dependencies;
|
|
6
14
|
private verbose;
|
|
7
15
|
private encryptor;
|
|
8
|
-
|
|
16
|
+
private idPrefix;
|
|
17
|
+
private onTerminateFn?;
|
|
18
|
+
constructor({ verbose, encryptor, prefix, }?: {
|
|
9
19
|
verbose?: boolean;
|
|
10
20
|
encryptor?: Encryptor;
|
|
21
|
+
prefix?: string;
|
|
11
22
|
});
|
|
12
23
|
register<F extends Func>(name: string, func: F, options?: {
|
|
13
24
|
version?: number;
|
|
@@ -16,6 +27,7 @@ export declare class Resonate {
|
|
|
16
27
|
version?: number;
|
|
17
28
|
}): void;
|
|
18
29
|
setDependency(name: string, obj: any): void;
|
|
30
|
+
onTerminate(fn: OnTerminateCallback): void;
|
|
19
31
|
handler(req: Request): Promise<Response>;
|
|
20
32
|
httpHandler(): Deno.HttpServer;
|
|
21
33
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Resonate {
|
|
9
|
-
constructor({ verbose = false, encryptor = undefined, } = {}) {
|
|
10
|
-
this.registry = new sdk_1.Registry();
|
|
1
|
+
import { Handler, HttpNetwork, JsonEncoder, NoopHeartbeat, Registry, ResonateInner, WallClock, } from "@resonatehq/sdk";
|
|
2
|
+
import { NoopEncryptor, } from "@resonatehq/sdk/dist/src/encryptor";
|
|
3
|
+
import { OptionsBuilder } from "@resonatehq/sdk/dist/src/options";
|
|
4
|
+
import { NoopTracer } from "@resonatehq/sdk/dist/src/tracer";
|
|
5
|
+
export class Resonate {
|
|
6
|
+
constructor({ verbose = false, encryptor = undefined, prefix = undefined, } = {}) {
|
|
7
|
+
this.registry = new Registry();
|
|
11
8
|
this.dependencies = new Map();
|
|
12
9
|
this.verbose = verbose;
|
|
13
|
-
this.encryptor = encryptor ?? new
|
|
10
|
+
this.encryptor = encryptor ?? new NoopEncryptor();
|
|
11
|
+
this.idPrefix = prefix ? `${prefix}:` : "";
|
|
14
12
|
}
|
|
15
13
|
register(nameOrFunc, funcOrOptions, maybeOptions = {}) {
|
|
16
14
|
const { version = 1 } = (typeof funcOrOptions === "object" ? funcOrOptions : maybeOptions) ?? {};
|
|
@@ -21,6 +19,9 @@ class Resonate {
|
|
|
21
19
|
setDependency(name, obj) {
|
|
22
20
|
this.dependencies.set(name, obj);
|
|
23
21
|
}
|
|
22
|
+
onTerminate(fn) {
|
|
23
|
+
this.onTerminateFn = fn;
|
|
24
|
+
}
|
|
24
25
|
async handler(req) {
|
|
25
26
|
try {
|
|
26
27
|
if (req.method !== "POST") {
|
|
@@ -46,34 +47,39 @@ class Resonate {
|
|
|
46
47
|
status: 400,
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
|
-
const encoder = new
|
|
50
|
-
const clock = new
|
|
51
|
-
const tracer = new
|
|
52
|
-
const network = new
|
|
50
|
+
const encoder = new JsonEncoder();
|
|
51
|
+
const clock = new WallClock();
|
|
52
|
+
const tracer = new NoopTracer();
|
|
53
|
+
const network = new HttpNetwork({
|
|
53
54
|
headers: {},
|
|
54
55
|
timeout: 60 * 1000, // 60s
|
|
55
56
|
url: body.href.base,
|
|
56
57
|
verbose: this.verbose,
|
|
57
58
|
});
|
|
58
|
-
const resonateInner = new
|
|
59
|
+
const resonateInner = new ResonateInner({
|
|
59
60
|
unicast: url,
|
|
60
61
|
anycast: url,
|
|
61
62
|
pid: `pid-${Math.random().toString(36).substring(7)}`,
|
|
62
63
|
ttl: 30 * 1000,
|
|
63
64
|
clock,
|
|
64
65
|
network,
|
|
65
|
-
handler: new
|
|
66
|
+
handler: new Handler(network, encoder, this.encryptor),
|
|
66
67
|
registry: this.registry,
|
|
67
|
-
heartbeat: new
|
|
68
|
+
heartbeat: new NoopHeartbeat(),
|
|
68
69
|
dependencies: this.dependencies,
|
|
69
|
-
optsBuilder: new
|
|
70
|
+
optsBuilder: new OptionsBuilder({
|
|
70
71
|
match: (_) => url,
|
|
72
|
+
idPrefix: this.idPrefix,
|
|
71
73
|
}),
|
|
72
74
|
verbose: this.verbose,
|
|
73
75
|
tracer,
|
|
74
76
|
});
|
|
75
77
|
const task = { kind: "unclaimed", task: body.task };
|
|
76
|
-
const
|
|
78
|
+
const handleCallback = (data) => {
|
|
79
|
+
this.onTerminateFn?.(data);
|
|
80
|
+
return Promise.resolve();
|
|
81
|
+
};
|
|
82
|
+
return new Promise((resolve) => {
|
|
77
83
|
resonateInner.process(tracer.startSpan(task.task.rootPromiseId, clock.now()), task, (error, status) => {
|
|
78
84
|
if (error || !status) {
|
|
79
85
|
resolve(new Response(JSON.stringify({
|
|
@@ -85,27 +91,36 @@ class Resonate {
|
|
|
85
91
|
return;
|
|
86
92
|
}
|
|
87
93
|
if (status.kind === "completed") {
|
|
88
|
-
|
|
94
|
+
handleCallback({
|
|
89
95
|
status: "completed",
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
data: encoder.decode(this.encryptor.decrypt(status.promise.value)),
|
|
97
|
+
}).finally(() => {
|
|
98
|
+
resolve(new Response(JSON.stringify({
|
|
99
|
+
status: "completed",
|
|
100
|
+
result: status.promise.value,
|
|
101
|
+
requestUrl: url,
|
|
102
|
+
}), {
|
|
103
|
+
status: 200,
|
|
104
|
+
}));
|
|
105
|
+
});
|
|
95
106
|
return;
|
|
96
107
|
}
|
|
97
108
|
else if (status.kind === "suspended") {
|
|
98
|
-
|
|
109
|
+
handleCallback({
|
|
99
110
|
status: "suspended",
|
|
100
|
-
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
|
|
111
|
+
result: status.callbacks.map((callback) => callback.promiseId),
|
|
112
|
+
}).finally(() => {
|
|
113
|
+
resolve(new Response(JSON.stringify({
|
|
114
|
+
status: "suspended",
|
|
115
|
+
requestUrl: url,
|
|
116
|
+
}), {
|
|
117
|
+
status: 200,
|
|
118
|
+
}));
|
|
119
|
+
});
|
|
104
120
|
return;
|
|
105
121
|
}
|
|
106
122
|
});
|
|
107
123
|
});
|
|
108
|
-
return completion;
|
|
109
124
|
}
|
|
110
125
|
catch (error) {
|
|
111
126
|
return new Response(JSON.stringify({
|
|
@@ -119,7 +134,6 @@ class Resonate {
|
|
|
119
134
|
});
|
|
120
135
|
}
|
|
121
136
|
}
|
|
122
|
-
exports.Resonate = Resonate;
|
|
123
137
|
function buildForwardedURL(req) {
|
|
124
138
|
const headers = req.headers;
|
|
125
139
|
const url = new URL(req.url);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@resonatehq/supabase",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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.9.
|
|
32
|
+
"@resonatehq/sdk": "^0.9.5"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
Context,
|
|
2
3
|
type Func,
|
|
3
4
|
Handler,
|
|
4
5
|
HttpNetwork,
|
|
@@ -9,6 +10,7 @@ import {
|
|
|
9
10
|
type Task,
|
|
10
11
|
WallClock,
|
|
11
12
|
} from "@resonatehq/sdk";
|
|
13
|
+
|
|
12
14
|
import {
|
|
13
15
|
type Encryptor,
|
|
14
16
|
NoopEncryptor,
|
|
@@ -16,18 +18,29 @@ import {
|
|
|
16
18
|
import { OptionsBuilder } from "@resonatehq/sdk/dist/src/options";
|
|
17
19
|
import { NoopTracer } from "@resonatehq/sdk/dist/src/tracer";
|
|
18
20
|
|
|
21
|
+
type OnTerminateCallback = (
|
|
22
|
+
result:
|
|
23
|
+
| { status: "completed"; data?: any }
|
|
24
|
+
| { status: "suspended"; result: string[] },
|
|
25
|
+
) => Promise<void>;
|
|
26
|
+
|
|
27
|
+
export { Context };
|
|
19
28
|
export class Resonate {
|
|
20
29
|
private registry = new Registry();
|
|
21
30
|
private dependencies = new Map<string, any>();
|
|
22
31
|
private verbose: boolean;
|
|
23
32
|
private encryptor: Encryptor;
|
|
33
|
+
private idPrefix: string;
|
|
34
|
+
private onTerminateFn?: OnTerminateCallback;
|
|
24
35
|
|
|
25
36
|
constructor({
|
|
26
37
|
verbose = false,
|
|
27
38
|
encryptor = undefined,
|
|
28
|
-
|
|
39
|
+
prefix = undefined,
|
|
40
|
+
}: { verbose?: boolean; encryptor?: Encryptor; prefix?: string } = {}) {
|
|
29
41
|
this.verbose = verbose;
|
|
30
42
|
this.encryptor = encryptor ?? new NoopEncryptor();
|
|
43
|
+
this.idPrefix = prefix ? `${prefix}:` : "";
|
|
31
44
|
}
|
|
32
45
|
|
|
33
46
|
public register<F extends Func>(
|
|
@@ -66,6 +79,9 @@ export class Resonate {
|
|
|
66
79
|
public setDependency(name: string, obj: any): void {
|
|
67
80
|
this.dependencies.set(name, obj);
|
|
68
81
|
}
|
|
82
|
+
public onTerminate(fn: OnTerminateCallback): void {
|
|
83
|
+
this.onTerminateFn = fn;
|
|
84
|
+
}
|
|
69
85
|
|
|
70
86
|
public async handler(req: Request): Promise<Response> {
|
|
71
87
|
try {
|
|
@@ -131,6 +147,7 @@ export class Resonate {
|
|
|
131
147
|
dependencies: this.dependencies,
|
|
132
148
|
optsBuilder: new OptionsBuilder({
|
|
133
149
|
match: (_: string): string => url,
|
|
150
|
+
idPrefix: this.idPrefix,
|
|
134
151
|
}),
|
|
135
152
|
verbose: this.verbose,
|
|
136
153
|
tracer,
|
|
@@ -138,7 +155,16 @@ export class Resonate {
|
|
|
138
155
|
|
|
139
156
|
const task: Task = { kind: "unclaimed", task: body.task };
|
|
140
157
|
|
|
141
|
-
const
|
|
158
|
+
const handleCallback = (
|
|
159
|
+
data:
|
|
160
|
+
| { status: "completed"; data?: any }
|
|
161
|
+
| { status: "suspended"; result: string[] },
|
|
162
|
+
): Promise<void> => {
|
|
163
|
+
this.onTerminateFn?.(data);
|
|
164
|
+
return Promise.resolve();
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
return new Promise((resolve) => {
|
|
142
168
|
resonateInner.process(
|
|
143
169
|
tracer.startSpan(task.task.rootPromiseId, clock.now()),
|
|
144
170
|
task,
|
|
@@ -157,39 +183,49 @@ export class Resonate {
|
|
|
157
183
|
);
|
|
158
184
|
return;
|
|
159
185
|
}
|
|
160
|
-
|
|
161
186
|
if (status.kind === "completed") {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
result: status.promise.value,
|
|
167
|
-
requestUrl: url,
|
|
168
|
-
}),
|
|
169
|
-
{
|
|
170
|
-
status: 200,
|
|
171
|
-
},
|
|
187
|
+
handleCallback({
|
|
188
|
+
status: "completed",
|
|
189
|
+
data: encoder.decode(
|
|
190
|
+
this.encryptor.decrypt(status.promise.value),
|
|
172
191
|
),
|
|
173
|
-
)
|
|
192
|
+
}).finally(() => {
|
|
193
|
+
resolve(
|
|
194
|
+
new Response(
|
|
195
|
+
JSON.stringify({
|
|
196
|
+
status: "completed",
|
|
197
|
+
result: status.promise.value,
|
|
198
|
+
requestUrl: url,
|
|
199
|
+
}),
|
|
200
|
+
{
|
|
201
|
+
status: 200,
|
|
202
|
+
},
|
|
203
|
+
),
|
|
204
|
+
);
|
|
205
|
+
});
|
|
174
206
|
return;
|
|
175
207
|
} else if (status.kind === "suspended") {
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
208
|
+
handleCallback({
|
|
209
|
+
status: "suspended",
|
|
210
|
+
result: status.callbacks.map((callback) => callback.promiseId),
|
|
211
|
+
}).finally(() => {
|
|
212
|
+
resolve(
|
|
213
|
+
new Response(
|
|
214
|
+
JSON.stringify({
|
|
215
|
+
status: "suspended",
|
|
216
|
+
requestUrl: url,
|
|
217
|
+
}),
|
|
218
|
+
{
|
|
219
|
+
status: 200,
|
|
220
|
+
},
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
});
|
|
187
224
|
return;
|
|
188
225
|
}
|
|
189
226
|
},
|
|
190
227
|
);
|
|
191
228
|
});
|
|
192
|
-
return completion;
|
|
193
229
|
} catch (error) {
|
|
194
230
|
return new Response(
|
|
195
231
|
JSON.stringify({
|
package/tsconfig.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
|
-
"module": "
|
|
5
|
-
"
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
6
7
|
"declaration": true,
|
|
7
8
|
"outDir": "./dist",
|
|
8
9
|
"rootDir": "./src",
|