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