@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.
@@ -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,23 @@
1
- import { type Func } from "@resonatehq/sdk";
2
- import { type Encryptor } from "@resonatehq/sdk/dist/src/encryptor";
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
- constructor({ verbose, encryptor, }?: {
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
- "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, 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 encryptor_1.NoopEncryptor();
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 sdk_1.JsonEncoder();
50
- const clock = new sdk_1.WallClock();
51
- const tracer = new tracer_1.NoopTracer();
52
- const network = new sdk_1.HttpNetwork({
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 sdk_1.ResonateInner({
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 sdk_1.Handler(network, encoder, this.encryptor),
63
+ handler: new Handler(network, encoder, this.encryptor),
66
64
  registry: this.registry,
67
- heartbeat: new sdk_1.NoopHeartbeat(),
65
+ heartbeat: new NoopHeartbeat(),
68
66
  dependencies: this.dependencies,
69
- optsBuilder: new options_1.OptionsBuilder({
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 completion = new Promise((resolve) => {
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
- resolve(new Response(JSON.stringify({
91
+ handleCallback({
89
92
  status: "completed",
90
- result: status.promise.value,
91
- requestUrl: url,
92
- }), {
93
- status: 200,
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
- resolve(new Response(JSON.stringify({
106
+ handleCallback({
99
107
  status: "suspended",
100
- requestUrl: url,
101
- }), {
102
- status: 200,
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.5",
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.3"
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
- }: { verbose?: boolean; encryptor?: Encryptor } = {}) {
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 completion: Promise<Response> = new Promise((resolve) => {
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
- resolve(
163
- new Response(
164
- JSON.stringify({
165
- status: "completed",
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
- resolve(
177
- new Response(
178
- JSON.stringify({
179
- status: "suspended",
180
- requestUrl: url,
181
- }),
182
- {
183
- status: 200,
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": "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",