@protobase/server 0.32.0 → 0.33.0

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.
@@ -47,6 +47,11 @@ export type CorsOptions = {
47
47
  type SharedOptions = {
48
48
  /** Answers CORS preflights before authentication and adds the CORS headers to every response, problems included. */
49
49
  cors?: CorsOptions;
50
+ /**
51
+ * Also answers at `/api/sb/functions/v1/<name>`, as Supabase's `verify_jwt` does, where the app's publishable key alone
52
+ * admits a caller. For functions moved from Supabase; not together with `roles` or `capability`.
53
+ */
54
+ supabase?: boolean;
50
55
  };
51
56
  /** A function anyone may call, such as a webhook; it can still ask for a caller with `context.caller()`. */
52
57
  export type PublicFunctionOptions = SharedOptions & {
@@ -78,7 +83,7 @@ export type FunctionSource = ApiFunction | FunctionHandler | FunctionApp;
78
83
  /**
79
84
  * A function of your own, served at `/api/functions/<name>`. Without options it needs a signed-in caller, through the
80
85
  * app's `authenticate`, and with the app's `roles` one whose roles hold `*`; `{ roles }` or `{ capability }` opens it
81
- * to more, `{ public: true }` to anyone, as for a webhook.
86
+ * to more, `{ public: true }` to anyone, as for a webhook. `{ supabase: true }` serves it at `/api/sb/functions/v1/<name>` too.
82
87
  */
83
88
  export declare function defineFunction(handler: FunctionHandler | FunctionApp): ApiFunction;
84
89
  export declare function defineFunction(options: PublicFunctionOptions, handler: PublicFunctionHandler | FunctionApp<PublicFunctionContext>): ApiFunction;
@@ -7,11 +7,12 @@ import { Hono } from "hono";
7
7
  import { cors } from "hono/cors";
8
8
  //#region src/functions/supabase-routes.ts
9
9
  /**
10
- * The app's functions again at `/api/sb/functions/v1/<name>`, as Supabase serves Edge Functions. A protected function lets in
11
- * a request its app's keys admit, as Supabase's `verify_jwt` does, and a public one anyone. Either gets the key-made
12
- * caller, not the app's session, so a function with `roles` is served at `/api/functions/<name>` only. As on Supabase,
13
- * the function sees the path from its name on, `/<name>/more/parts`, and a CORS preflight, which carries no key,
14
- * reaches it unchecked.
10
+ * The functions with `supabase: true` again at `/api/sb/functions/v1/<name>`, as Supabase serves Edge Functions. A
11
+ * protected one lets in a request its app's keys admit, as Supabase's `verify_jwt` does, the publishable key alone
12
+ * included, and a public one anyone. Either gets the key-made caller, not the app's session, so neither may have
13
+ * `roles` or `capability`: that stops startup. As on Supabase, the function sees the path from its name on,
14
+ * `/<name>/more/parts`, and a CORS preflight, which carries no key, reaches it unchecked. Every other function is a 404
15
+ * here, and none of its code runs.
15
16
  */
16
17
  const supabaseFunctionRoutes = ({ functions, db, keys, caller, onError }) => {
17
18
  const app = new Hono().basePath(supabaseFunctionsPath);
@@ -19,9 +20,17 @@ const supabaseFunctionRoutes = ({ functions, db, keys, caller, onError }) => {
19
20
  const hasKeys = keys.publishable !== void 0 || keys.secret !== void 0;
20
21
  for (const [name, fn] of Object.entries(functions)) {
21
22
  const { options } = fn;
23
+ if (options.supabase !== true) {
24
+ app.all(`/${name}/*`, () => {
25
+ throw notFound(`The function "${name}" answers at /api/functions/${name} only: give it supabase: true to answer here too`);
26
+ });
27
+ continue;
28
+ }
29
+ const { roles, capability } = options;
30
+ const gated = roles !== void 0 ? "roles" : capability !== void 0 ? "a capability" : void 0;
31
+ if (gated) throw new Error(`The function "${name}" has supabase: true and ${gated}, which /api/sb/functions/v1 cannot check: drop one`);
22
32
  if (options.cors) app.use(`/${name}/*`, cors(options.cors));
23
33
  app.all(`/${name}/*`, (c) => runInBackground(async () => {
24
- if (!options.public && options.roles) throw notFound(`The function "${name}" checks roles, so it is served at /api/functions/${name} only`);
25
34
  const request = relativeRequest(c.req.raw, supabaseFunctionsPath);
26
35
  if (options.public || c.req.method === "OPTIONS") {
27
36
  let resolved;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@protobase/server",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "The Protobase REST API as a Hono app, with Better Auth sign-in.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -32,9 +32,9 @@
32
32
  "dependencies": {
33
33
  "@better-auth/passkey": "^1.7.7",
34
34
  "@better-auth/sso": "^1.7.7",
35
- "@protobase/layout": "0.32.0",
36
- "@protobase/query": "0.32.0",
37
- "@protobase/schema": "0.32.0",
35
+ "@protobase/layout": "0.33.0",
36
+ "@protobase/query": "0.33.0",
37
+ "@protobase/schema": "0.33.0",
38
38
  "@react-email/render": "^2.1.0",
39
39
  "@scalar/hono-api-reference": "^0.12.10",
40
40
  "@sentry/core": "^11.7.0",