@pawabase/client 0.0.0-stage → 0.1.3

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.
Files changed (243) hide show
  1. package/README.md +313 -2
  2. package/dist/cjs/admin.d.ts +187 -0
  3. package/dist/cjs/admin.d.ts.map +1 -0
  4. package/dist/cjs/admin.js +235 -0
  5. package/dist/cjs/admin.js.map +1 -0
  6. package/dist/cjs/auth.d.ts +448 -0
  7. package/dist/cjs/auth.d.ts.map +1 -0
  8. package/dist/cjs/auth.js +1016 -0
  9. package/dist/cjs/auth.js.map +1 -0
  10. package/dist/cjs/client.d.ts +103 -0
  11. package/dist/cjs/client.d.ts.map +1 -0
  12. package/dist/cjs/client.js +144 -0
  13. package/dist/cjs/client.js.map +1 -0
  14. package/dist/cjs/data.d.ts +220 -0
  15. package/dist/cjs/data.d.ts.map +1 -0
  16. package/dist/cjs/data.js +490 -0
  17. package/dist/cjs/data.js.map +1 -0
  18. package/dist/cjs/errors.d.ts +167 -0
  19. package/dist/cjs/errors.d.ts.map +1 -0
  20. package/dist/cjs/errors.js +316 -0
  21. package/dist/cjs/errors.js.map +1 -0
  22. package/dist/cjs/files.d.ts +80 -0
  23. package/dist/cjs/files.d.ts.map +1 -0
  24. package/dist/cjs/files.js +167 -0
  25. package/dist/cjs/files.js.map +1 -0
  26. package/dist/cjs/functions.d.ts +66 -0
  27. package/dist/cjs/functions.d.ts.map +1 -0
  28. package/dist/cjs/functions.js +109 -0
  29. package/dist/cjs/functions.js.map +1 -0
  30. package/dist/cjs/http.d.ts +101 -0
  31. package/dist/cjs/http.d.ts.map +1 -0
  32. package/dist/cjs/http.js +249 -0
  33. package/dist/cjs/http.js.map +1 -0
  34. package/dist/cjs/index.d.ts +22 -0
  35. package/dist/cjs/index.d.ts.map +1 -0
  36. package/dist/cjs/index.js +45 -0
  37. package/dist/cjs/index.js.map +1 -0
  38. package/dist/cjs/manage/access.d.ts +136 -0
  39. package/dist/cjs/manage/access.d.ts.map +1 -0
  40. package/dist/cjs/manage/access.js +162 -0
  41. package/dist/cjs/manage/access.js.map +1 -0
  42. package/dist/cjs/manage/automation.d.ts +106 -0
  43. package/dist/cjs/manage/automation.d.ts.map +1 -0
  44. package/dist/cjs/manage/automation.js +144 -0
  45. package/dist/cjs/manage/automation.js.map +1 -0
  46. package/dist/cjs/manage/base.d.ts +52 -0
  47. package/dist/cjs/manage/base.d.ts.map +1 -0
  48. package/dist/cjs/manage/base.js +69 -0
  49. package/dist/cjs/manage/base.js.map +1 -0
  50. package/dist/cjs/manage/data.d.ts +100 -0
  51. package/dist/cjs/manage/data.d.ts.map +1 -0
  52. package/dist/cjs/manage/data.js +141 -0
  53. package/dist/cjs/manage/data.js.map +1 -0
  54. package/dist/cjs/manage/files.d.ts +45 -0
  55. package/dist/cjs/manage/files.d.ts.map +1 -0
  56. package/dist/cjs/manage/files.js +73 -0
  57. package/dist/cjs/manage/files.js.map +1 -0
  58. package/dist/cjs/manage/functions.d.ts +48 -0
  59. package/dist/cjs/manage/functions.d.ts.map +1 -0
  60. package/dist/cjs/manage/functions.js +61 -0
  61. package/dist/cjs/manage/functions.js.map +1 -0
  62. package/dist/cjs/manage/index.d.ts +76 -0
  63. package/dist/cjs/manage/index.d.ts.map +1 -0
  64. package/dist/cjs/manage/index.js +134 -0
  65. package/dist/cjs/manage/index.js.map +1 -0
  66. package/dist/cjs/manage/lifecycle.d.ts +128 -0
  67. package/dist/cjs/manage/lifecycle.d.ts.map +1 -0
  68. package/dist/cjs/manage/lifecycle.js +167 -0
  69. package/dist/cjs/manage/lifecycle.js.map +1 -0
  70. package/dist/cjs/manage/mail.d.ts +16 -0
  71. package/dist/cjs/manage/mail.d.ts.map +1 -0
  72. package/dist/cjs/manage/mail.js +24 -0
  73. package/dist/cjs/manage/mail.js.map +1 -0
  74. package/dist/cjs/manage/observe.d.ts +149 -0
  75. package/dist/cjs/manage/observe.d.ts.map +1 -0
  76. package/dist/cjs/manage/observe.js +168 -0
  77. package/dist/cjs/manage/observe.js.map +1 -0
  78. package/dist/cjs/manage/realtime.d.ts +52 -0
  79. package/dist/cjs/manage/realtime.d.ts.map +1 -0
  80. package/dist/cjs/manage/realtime.js +71 -0
  81. package/dist/cjs/manage/realtime.js.map +1 -0
  82. package/dist/cjs/package.json +1 -0
  83. package/dist/cjs/realtime.d.ts +207 -0
  84. package/dist/cjs/realtime.d.ts.map +1 -0
  85. package/dist/cjs/realtime.js +704 -0
  86. package/dist/cjs/realtime.js.map +1 -0
  87. package/dist/cjs/session-store.d.ts +16 -0
  88. package/dist/cjs/session-store.d.ts.map +1 -0
  89. package/dist/cjs/session-store.js +37 -0
  90. package/dist/cjs/session-store.js.map +1 -0
  91. package/dist/cjs/typegen.d.ts +26 -0
  92. package/dist/cjs/typegen.d.ts.map +1 -0
  93. package/dist/cjs/typegen.js +167 -0
  94. package/dist/cjs/typegen.js.map +1 -0
  95. package/dist/cjs/types.d.ts +178 -0
  96. package/dist/cjs/types.d.ts.map +1 -0
  97. package/dist/cjs/types.js +4 -0
  98. package/dist/cjs/types.js.map +1 -0
  99. package/dist/cjs/util.d.ts +27 -0
  100. package/dist/cjs/util.d.ts.map +1 -0
  101. package/dist/cjs/util.js +115 -0
  102. package/dist/cjs/util.js.map +1 -0
  103. package/dist/cjs/version.d.ts +2 -0
  104. package/dist/cjs/version.d.ts.map +1 -0
  105. package/dist/cjs/version.js +5 -0
  106. package/dist/cjs/version.js.map +1 -0
  107. package/dist/esm/admin.d.ts +187 -0
  108. package/dist/esm/admin.d.ts.map +1 -0
  109. package/dist/esm/admin.js +222 -0
  110. package/dist/esm/admin.js.map +1 -0
  111. package/dist/esm/auth.d.ts +448 -0
  112. package/dist/esm/auth.d.ts.map +1 -0
  113. package/dist/esm/auth.js +1012 -0
  114. package/dist/esm/auth.js.map +1 -0
  115. package/dist/esm/cli/gen-types.d.ts +2 -0
  116. package/dist/esm/cli/gen-types.d.ts.map +1 -0
  117. package/dist/esm/cli/gen-types.js +100 -0
  118. package/dist/esm/cli/gen-types.js.map +1 -0
  119. package/dist/esm/client.d.ts +103 -0
  120. package/dist/esm/client.d.ts.map +1 -0
  121. package/dist/esm/client.js +139 -0
  122. package/dist/esm/client.js.map +1 -0
  123. package/dist/esm/data.d.ts +220 -0
  124. package/dist/esm/data.d.ts.map +1 -0
  125. package/dist/esm/data.js +485 -0
  126. package/dist/esm/data.js.map +1 -0
  127. package/dist/esm/errors.d.ts +167 -0
  128. package/dist/esm/errors.d.ts.map +1 -0
  129. package/dist/esm/errors.js +293 -0
  130. package/dist/esm/errors.js.map +1 -0
  131. package/dist/esm/files.d.ts +80 -0
  132. package/dist/esm/files.d.ts.map +1 -0
  133. package/dist/esm/files.js +162 -0
  134. package/dist/esm/files.js.map +1 -0
  135. package/dist/esm/functions.d.ts +66 -0
  136. package/dist/esm/functions.d.ts.map +1 -0
  137. package/dist/esm/functions.js +103 -0
  138. package/dist/esm/functions.js.map +1 -0
  139. package/dist/esm/http.d.ts +101 -0
  140. package/dist/esm/http.d.ts.map +1 -0
  141. package/dist/esm/http.js +245 -0
  142. package/dist/esm/http.js.map +1 -0
  143. package/dist/esm/index.d.ts +22 -0
  144. package/dist/esm/index.d.ts.map +1 -0
  145. package/dist/esm/index.js +12 -0
  146. package/dist/esm/index.js.map +1 -0
  147. package/dist/esm/manage/access.d.ts +136 -0
  148. package/dist/esm/manage/access.d.ts.map +1 -0
  149. package/dist/esm/manage/access.js +155 -0
  150. package/dist/esm/manage/access.js.map +1 -0
  151. package/dist/esm/manage/automation.d.ts +106 -0
  152. package/dist/esm/manage/automation.d.ts.map +1 -0
  153. package/dist/esm/manage/automation.js +134 -0
  154. package/dist/esm/manage/automation.js.map +1 -0
  155. package/dist/esm/manage/base.d.ts +52 -0
  156. package/dist/esm/manage/base.d.ts.map +1 -0
  157. package/dist/esm/manage/base.js +63 -0
  158. package/dist/esm/manage/base.js.map +1 -0
  159. package/dist/esm/manage/data.d.ts +100 -0
  160. package/dist/esm/manage/data.d.ts.map +1 -0
  161. package/dist/esm/manage/data.js +130 -0
  162. package/dist/esm/manage/data.js.map +1 -0
  163. package/dist/esm/manage/files.d.ts +45 -0
  164. package/dist/esm/manage/files.d.ts.map +1 -0
  165. package/dist/esm/manage/files.js +68 -0
  166. package/dist/esm/manage/files.js.map +1 -0
  167. package/dist/esm/manage/functions.d.ts +48 -0
  168. package/dist/esm/manage/functions.d.ts.map +1 -0
  169. package/dist/esm/manage/functions.js +57 -0
  170. package/dist/esm/manage/functions.js.map +1 -0
  171. package/dist/esm/manage/index.d.ts +76 -0
  172. package/dist/esm/manage/index.d.ts.map +1 -0
  173. package/dist/esm/manage/index.js +115 -0
  174. package/dist/esm/manage/index.js.map +1 -0
  175. package/dist/esm/manage/lifecycle.d.ts +128 -0
  176. package/dist/esm/manage/lifecycle.d.ts.map +1 -0
  177. package/dist/esm/manage/lifecycle.js +161 -0
  178. package/dist/esm/manage/lifecycle.js.map +1 -0
  179. package/dist/esm/manage/mail.d.ts +16 -0
  180. package/dist/esm/manage/mail.d.ts.map +1 -0
  181. package/dist/esm/manage/mail.js +19 -0
  182. package/dist/esm/manage/mail.js.map +1 -0
  183. package/dist/esm/manage/observe.d.ts +149 -0
  184. package/dist/esm/manage/observe.d.ts.map +1 -0
  185. package/dist/esm/manage/observe.js +161 -0
  186. package/dist/esm/manage/observe.js.map +1 -0
  187. package/dist/esm/manage/realtime.d.ts +52 -0
  188. package/dist/esm/manage/realtime.d.ts.map +1 -0
  189. package/dist/esm/manage/realtime.js +66 -0
  190. package/dist/esm/manage/realtime.js.map +1 -0
  191. package/dist/esm/package.json +1 -0
  192. package/dist/esm/realtime.d.ts +207 -0
  193. package/dist/esm/realtime.d.ts.map +1 -0
  194. package/dist/esm/realtime.js +699 -0
  195. package/dist/esm/realtime.js.map +1 -0
  196. package/dist/esm/session-store.d.ts +16 -0
  197. package/dist/esm/session-store.d.ts.map +1 -0
  198. package/dist/esm/session-store.js +32 -0
  199. package/dist/esm/session-store.js.map +1 -0
  200. package/dist/esm/typegen.d.ts +26 -0
  201. package/dist/esm/typegen.d.ts.map +1 -0
  202. package/dist/esm/typegen.js +163 -0
  203. package/dist/esm/typegen.js.map +1 -0
  204. package/dist/esm/types.d.ts +178 -0
  205. package/dist/esm/types.d.ts.map +1 -0
  206. package/dist/esm/types.js +3 -0
  207. package/dist/esm/types.js.map +1 -0
  208. package/dist/esm/util.d.ts +27 -0
  209. package/dist/esm/util.d.ts.map +1 -0
  210. package/dist/esm/util.js +102 -0
  211. package/dist/esm/util.js.map +1 -0
  212. package/dist/esm/version.d.ts +2 -0
  213. package/dist/esm/version.d.ts.map +1 -0
  214. package/dist/esm/version.js +2 -0
  215. package/dist/esm/version.js.map +1 -0
  216. package/package.json +92 -4
  217. package/src/admin.ts +311 -0
  218. package/src/auth.ts +1180 -0
  219. package/src/cli/gen-types.ts +105 -0
  220. package/src/client.ts +189 -0
  221. package/src/data.ts +576 -0
  222. package/src/errors.ts +330 -0
  223. package/src/files.ts +208 -0
  224. package/src/functions.ts +131 -0
  225. package/src/http.ts +354 -0
  226. package/src/index.ts +56 -0
  227. package/src/manage/access.ts +206 -0
  228. package/src/manage/automation.ts +162 -0
  229. package/src/manage/base.ts +83 -0
  230. package/src/manage/data.ts +159 -0
  231. package/src/manage/files.ts +79 -0
  232. package/src/manage/functions.ts +69 -0
  233. package/src/manage/index.ts +132 -0
  234. package/src/manage/lifecycle.ts +208 -0
  235. package/src/manage/mail.ts +22 -0
  236. package/src/manage/observe.ts +226 -0
  237. package/src/manage/realtime.ts +95 -0
  238. package/src/realtime.ts +765 -0
  239. package/src/session-store.ts +36 -0
  240. package/src/typegen.ts +192 -0
  241. package/src/types.ts +195 -0
  242. package/src/util.ts +114 -0
  243. package/src/version.ts +1 -0
@@ -0,0 +1,105 @@
1
+ import { readFileSync, writeFileSync, existsSync } from "node:fs";
2
+ import { generateTypes } from "../typegen.js";
3
+
4
+ const USAGE = `pawabase-types: generate TypeScript types for createClient<Database>()
5
+
6
+ Usage:
7
+ pawabase-types --url <gateway> --project <ref> --env <name> [--out types.ts]
8
+ pawabase-types --file openapi.json [--out types.ts]
9
+
10
+ Options:
11
+ --url, -u The gateway origin (env PAWABASE_URL)
12
+ --project, -p The project's ref (env PAWABASE_PROJECT)
13
+ --env, -e The environment's name (env PAWABASE_ENV)
14
+ --api-key, -k An API key, sent as 'apikey' (env PAWABASE_API_KEY)
15
+ --file, -f Read the OpenAPI document from a file instead of the gateway
16
+ --out, -o Where to write the types. Default: pawabase.types.ts. '-' prints them.
17
+ --name The root interface's name. Default: Database
18
+ --check Exit 1 if --out is out of date (for CI); writes nothing
19
+ --help, -h Show this
20
+
21
+ The gateway serves /docs/v1/<project>/<env>/openapi.json when the environment's
22
+ "public docs" setting is on. Otherwise download the document from Studio (API
23
+ Explorer) and pass it with --file.
24
+ `;
25
+
26
+ function parse(argv: string[]): Record<string, string | boolean> {
27
+ const out: Record<string, string | boolean> = {};
28
+ const alias: Record<string, string> = { u: "url", p: "project", e: "env", k: "api-key", f: "file", o: "out", h: "help" };
29
+ for (let i = 0; i < argv.length; i++) {
30
+ const arg = argv[i]!;
31
+ if (!arg.startsWith("-")) continue;
32
+ const name = arg.startsWith("--") ? arg.slice(2) : (alias[arg.slice(1)] ?? arg.slice(1));
33
+ if (name === "help" || name === "check") out[name] = true;
34
+ else out[name] = argv[++i] ?? "";
35
+ }
36
+ return out;
37
+ }
38
+
39
+ async function main(): Promise<number> {
40
+ const args = parse(process.argv.slice(2));
41
+ if (args["help"]) {
42
+ console.log(USAGE);
43
+ return 0;
44
+ }
45
+ const file = args["file"] as string | undefined;
46
+ const url = (args["url"] as string | undefined) ?? process.env["PAWABASE_URL"];
47
+ const project = (args["project"] as string | undefined) ?? process.env["PAWABASE_PROJECT"];
48
+ const env = (args["env"] as string | undefined) ?? process.env["PAWABASE_ENV"];
49
+ const apiKey = (args["api-key"] as string | undefined) ?? process.env["PAWABASE_API_KEY"];
50
+
51
+ let spec: unknown;
52
+ let source: string;
53
+ if (file) {
54
+ spec = JSON.parse(readFileSync(file, "utf8"));
55
+ source = file;
56
+ } else {
57
+ if (!url || !project || !env) {
58
+ console.error("Give --url, --project and --env (or --file).\n\n" + USAGE);
59
+ return 2;
60
+ }
61
+ const endpoint = `${url.replace(/\/+$/, "")}/docs/v1/${encodeURIComponent(project)}/${encodeURIComponent(env)}/openapi.json`;
62
+ const response = await fetch(endpoint, { headers: apiKey ? { apikey: apiKey } : {} });
63
+ if (!response.ok) {
64
+ console.error(
65
+ `Could not read ${endpoint}: ${response.status}. ` +
66
+ (response.status === 404 ? "Turn on public docs for this environment, or use --file with the document from Studio." : ""),
67
+ );
68
+ return 1;
69
+ }
70
+ spec = await response.json();
71
+ source = endpoint;
72
+ }
73
+
74
+ const text = generateTypes(spec as Record<string, unknown>, {
75
+ ...(args["name"] ? { name: String(args["name"]) } : {}),
76
+ source,
77
+ });
78
+ const out = (args["out"] as string | undefined) ?? "pawabase.types.ts";
79
+ if (out === "-") {
80
+ process.stdout.write(text);
81
+ return 0;
82
+ }
83
+ if (args["check"]) {
84
+ const current = existsSync(out) ? readFileSync(out, "utf8") : "";
85
+ // The header names the source and version; compare the body only.
86
+ const body = (value: string) => value.split("\n").slice(3).join("\n");
87
+ if (body(current) !== body(text)) {
88
+ console.error(`${out} is out of date. Run pawabase-types again.`);
89
+ return 1;
90
+ }
91
+ console.log(`${out} is up to date.`);
92
+ return 0;
93
+ }
94
+ writeFileSync(out, text);
95
+ console.log(`Wrote ${out}`);
96
+ return 0;
97
+ }
98
+
99
+ main().then(
100
+ (code) => process.exit(code),
101
+ (error) => {
102
+ console.error(error instanceof Error ? error.message : error);
103
+ process.exit(1);
104
+ },
105
+ );
package/src/client.ts ADDED
@@ -0,0 +1,189 @@
1
+ import { AuthClient, type AuthOptions } from "./auth.js";
2
+ import { ResourceClient, type AnyRow, type ResourceTypes } from "./data.js";
3
+ import { ConfigError } from "./errors.js";
4
+ import { StorageClient } from "./files.js";
5
+ import { FlowsClient, FunctionsClient, RoutesClient } from "./functions.js";
6
+ import { HttpClient, type FetchLike, type Hooks, type RetryOptions, type TokenProvider } from "./http.js";
7
+ import { RealtimeClient, type RealtimeOptions } from "./realtime.js";
8
+ import { MemoryStorage } from "./session-store.js";
9
+ import { isSecretKey, trimSlash } from "./util.js";
10
+
11
+ /** The shape `createClient<Database>()` expects. `pawabase-types` generates one from your project. */
12
+ export interface DatabaseShape {
13
+ resources: Record<string, ResourceTypes<any, any, any>>;
14
+ }
15
+
16
+ type Untyped = { resources: Record<string, ResourceTypes> };
17
+
18
+ export interface ClientOptions {
19
+ /** The gateway's origin, e.g. `https://api.example.com`. */
20
+ url: string;
21
+ /** The project API key: `pb_pk_…` (publishable, safe in a browser) or `pb_sk_…` (secret, servers only). */
22
+ apiKey: string;
23
+ /**
24
+ * The environment this client talks to (`development`, `production`, a preview's name). The API key already names
25
+ * one, so it is optional for data calls; social sign-in, realtime and the management clients (`@pawabase/client/manage`,
26
+ * `@pawabase/client/admin`) use it. `project` is only sent as a scope hint.
27
+ */
28
+ project?: string;
29
+ environment?: string;
30
+ /** Per-attempt timeout in milliseconds. Default `30000`; `0` disables it. */
31
+ timeoutMs?: number;
32
+ /** Retry policy for rate limits, `502`/`503`/`504` and network failures. `false` to never retry. */
33
+ retry?: RetryOptions | false;
34
+ /** Your `fetch` (Node < 18 polyfills, React Native, a test double, instrumentation). */
35
+ fetch?: FetchLike;
36
+ /** Extra headers sent on every request. */
37
+ headers?: Record<string, string>;
38
+ hooks?: Hooks;
39
+ auth?: AuthOptions;
40
+ realtime?: RealtimeOptions;
41
+ /**
42
+ * Use this user's access token instead of a stored session: a string, or a function
43
+ * (for frameworks that own the session). With it the client keeps no session, does not
44
+ * refresh, and is meant for one server-side request.
45
+ */
46
+ accessToken?: string | (() => string | null | Promise<string | null>);
47
+ /** A secret key in a browser leaks it to every visitor, so it is refused. Set this to override. */
48
+ dangerouslyAllowBrowser?: boolean;
49
+ }
50
+
51
+ function isBrowser(): boolean {
52
+ return typeof window !== "undefined" && typeof (globalThis as { document?: unknown }).document !== "undefined";
53
+ }
54
+
55
+ function staticTokens(source: NonNullable<ClientOptions["accessToken"]>): TokenProvider {
56
+ const get = async () => (typeof source === "string" ? source : await source());
57
+ return { getAccessToken: get, onUnauthorized: async () => null };
58
+ }
59
+
60
+ /**
61
+ * The entry point.
62
+ *
63
+ * ```ts
64
+ * const pawabase = createClient({ url: "https://api.example.com", apiKey: "pb_pk_…" });
65
+ * await pawabase.auth.signInWithPassword({ email, password });
66
+ * const { data } = await pawabase.from("posts").eq("status", "live").order("created_at", "desc");
67
+ * ```
68
+ */
69
+ export class PawabaseClient<DB extends DatabaseShape = Untyped> {
70
+ readonly http: HttpClient;
71
+ /** Sign-in, session lifecycle and the signed-in user. */
72
+ readonly auth: AuthClient;
73
+ /** Storage buckets. */
74
+ readonly storage: StorageClient;
75
+ /** Functions: `/functions/v1`. */
76
+ readonly functions: FunctionsClient;
77
+ /** Flows with a pathless HTTP trigger: `/flows/v1`. */
78
+ readonly flows: FlowsClient;
79
+ /** Custom routes: `/rest/v1/<path>`. */
80
+ readonly routes: RoutesClient;
81
+ /** Channels, presence and publishing. */
82
+ readonly realtime: RealtimeClient;
83
+
84
+ constructor(readonly options: ClientOptions) {
85
+ if (!options.url) throw new ConfigError("createClient needs the gateway `url`.");
86
+ if (!options.apiKey) throw new ConfigError("createClient needs an `apiKey`.");
87
+ let origin: URL;
88
+ try {
89
+ origin = new URL(options.url);
90
+ } catch {
91
+ throw new ConfigError(`"${options.url}" is not a valid URL.`);
92
+ }
93
+ if (origin.protocol !== "http:" && origin.protocol !== "https:") {
94
+ throw new ConfigError("The `url` must start with http:// or https://.");
95
+ }
96
+ if (isSecretKey(options.apiKey) && isBrowser() && !options.dangerouslyAllowBrowser) {
97
+ throw new ConfigError(
98
+ "A secret key (pb_sk_…) must never run in a browser: it bypasses every policy and anyone can read it. Use a publishable key (pb_pk_…) here, or set `dangerouslyAllowBrowser`.",
99
+ );
100
+ }
101
+ const fetchImpl: FetchLike | undefined =
102
+ options.fetch ?? (typeof fetch === "function" ? ((input, init) => fetch(input, init)) : undefined);
103
+ if (!fetchImpl) throw new ConfigError("No `fetch` is available. Pass one in the options.");
104
+
105
+ const stateless = options.accessToken !== undefined;
106
+ const config = {
107
+ baseUrl: trimSlash(options.url),
108
+ apiKey: options.apiKey,
109
+ fetch: fetchImpl,
110
+ headers: {
111
+ ...(options.project ? { "x-project-id": options.project } : {}),
112
+ ...(options.environment ? { "x-environment": options.environment } : {}),
113
+ ...options.headers,
114
+ },
115
+ timeoutMs: options.timeoutMs ?? 30_000,
116
+ retry: options.retry ?? ({} as RetryOptions),
117
+ hooks: options.hooks ?? {},
118
+ tokens: null as TokenProvider | null,
119
+ };
120
+ this.http = new HttpClient(config);
121
+ this.auth = new AuthClient(this.http, {
122
+ ...(stateless ? { persistSession: false, autoRefreshToken: false, storage: new MemoryStorage(), detectSessionInUrl: false } : {}),
123
+ ...options.auth,
124
+ ...(options.project ? { project: options.project } : {}),
125
+ ...(options.environment ? { environment: options.environment } : {}),
126
+ });
127
+ config.tokens = stateless ? staticTokens(options.accessToken as NonNullable<ClientOptions["accessToken"]>) : this.auth;
128
+ this.storage = new StorageClient(this.http);
129
+ this.functions = new FunctionsClient(this.http);
130
+ this.flows = new FlowsClient(this.http);
131
+ this.routes = new RoutesClient(this.http);
132
+ this.realtime = new RealtimeClient(this.http, stateless ? null : this.auth, {
133
+ ...options.realtime,
134
+ ...(options.project ? { project: options.project } : {}),
135
+ ...(options.environment ? { environment: options.environment } : {}),
136
+ });
137
+ }
138
+
139
+ /**
140
+ * Records of a resource. With a generated `Database` type the name and row types are checked;
141
+ * without one rows are `Record<string, unknown>`.
142
+ */
143
+ from<K extends keyof DB["resources"] & string>(
144
+ name: K,
145
+ ): ResourceClient<DB["resources"][K]["Row"], DB["resources"][K]["Insert"], DB["resources"][K]["Update"]> {
146
+ return new ResourceClient(this.http, name);
147
+ }
148
+
149
+ /** Records of a resource, typed by hand: `pawabase.resource<Post, NewPost>("posts")`. */
150
+ resource<Row = AnyRow, Insert = Partial<Row>, Update = Partial<Row>>(name: string): ResourceClient<Row, Insert, Update> {
151
+ return new ResourceClient<Row, Insert, Update>(this.http, name);
152
+ }
153
+
154
+ /** A client that acts as one user, from a token you hold (a server rendering a page, an edge function). It keeps no session. */
155
+ asUser(accessToken: string | (() => string | null | Promise<string | null>)): PawabaseClient<DB> {
156
+ return new PawabaseClient<DB>({ ...this.options, accessToken });
157
+ }
158
+
159
+ /**
160
+ * A raw request to any path on the gateway, with the key and the user's token attached,
161
+ * the retry policy and the typed errors applied. For endpoints the client has no method for.
162
+ */
163
+ request<T = unknown>(method: string, path: string, options: { body?: unknown; query?: Record<string, string | number | boolean | undefined | null>; headers?: Record<string, string>; signal?: AbortSignal } = {}): Promise<T> {
164
+ return this.http.request<T>({
165
+ method,
166
+ path,
167
+ ...(options.query ? { query: options.query } : {}),
168
+ ...(options.body !== undefined ? { body: options.body } : {}),
169
+ ...(options.headers ? { headers: options.headers } : {}),
170
+ signal: options.signal,
171
+ });
172
+ }
173
+
174
+ /** The health of every Pawabase service behind the gateway. */
175
+ status(): Promise<{ ok: boolean; services?: Record<string, { ok: boolean }> }> {
176
+ return this.http.request({ path: "/v1/status", auth: "none", headers: {} });
177
+ }
178
+
179
+ /** Stop timers and close the realtime connection. Call when discarding a client. */
180
+ dispose(): void {
181
+ this.realtime.disconnect();
182
+ this.auth.dispose();
183
+ }
184
+ }
185
+
186
+ /** Create a client. See {@link ClientOptions}. */
187
+ export function createClient<DB extends DatabaseShape = Untyped>(options: ClientOptions): PawabaseClient<DB> {
188
+ return new PawabaseClient<DB>(options);
189
+ }