@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.
@@ -27,13 +27,10 @@ jobs:
27
27
  steps:
28
28
  - uses: actions/checkout@v4
29
29
 
30
- - name: Set up Bun
31
- uses: oven-sh/setup-bun@v2
30
+ - name: Set up Deno
31
+ uses: denoland/setup-deno@v1
32
32
  with:
33
- bun-version: 1.3.0
34
-
35
- - name: install
36
- run: bun install
33
+ deno-version: v1.x
37
34
 
38
35
  - name: check linting
39
- run: bun run check
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
- constructor({ verbose, encryptor, }?: {
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
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Resonate = void 0;
4
- const sdk_1 = require("@resonatehq/sdk");
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, 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 encryptor_1.NoopEncryptor();
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 sdk_1.JsonEncoder();
50
- const clock = new sdk_1.WallClock();
51
- const tracer = new tracer_1.NoopTracer();
52
- const network = new sdk_1.HttpNetwork({
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 sdk_1.ResonateInner({
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 sdk_1.Handler(network, encoder, this.encryptor),
66
+ handler: new Handler(network, encoder, this.encryptor),
66
67
  registry: this.registry,
67
- heartbeat: new sdk_1.NoopHeartbeat(),
68
+ heartbeat: new NoopHeartbeat(),
68
69
  dependencies: this.dependencies,
69
- optsBuilder: new options_1.OptionsBuilder({
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 completion = new Promise((resolve) => {
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
- resolve(new Response(JSON.stringify({
94
+ handleCallback({
89
95
  status: "completed",
90
- result: status.promise.value,
91
- requestUrl: url,
92
- }), {
93
- status: 200,
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
- resolve(new Response(JSON.stringify({
109
+ handleCallback({
99
110
  status: "suspended",
100
- requestUrl: url,
101
- }), {
102
- status: 200,
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.5",
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.3"
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
- }: { verbose?: boolean; encryptor?: Encryptor } = {}) {
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 completion: Promise<Response> = new Promise((resolve) => {
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
- resolve(
163
- new Response(
164
- JSON.stringify({
165
- status: "completed",
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
- resolve(
177
- new Response(
178
- JSON.stringify({
179
- status: "suspended",
180
- requestUrl: url,
181
- }),
182
- {
183
- status: 200,
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": "commonjs",
5
- "lib": ["ES2020", "DOM"],
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
7
  "declaration": true,
7
8
  "outDir": "./dist",
8
9
  "rootDir": "./src",