@surf-ai/sdk 0.1.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.
package/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # @surf-ai/sdk
2
+
3
+ Surf platform SDK — data API client, Express server runtime, React hooks, and database helpers.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ bun add @surf-ai/sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Frontend (React hooks)
14
+
15
+ ```tsx
16
+ import { useMarketPrice, cn, useToast } from '@surf-ai/sdk/react'
17
+
18
+ function App() {
19
+ const { data, isLoading } = useMarketPrice({ symbol: 'BTC', time_range: '1d' })
20
+ return (
21
+ <div className={cn('p-4', isLoading && 'opacity-50')}>
22
+ BTC: ${data?.data?.[0]?.value}
23
+ </div>
24
+ )
25
+ }
26
+ ```
27
+
28
+ ### Backend (data API)
29
+
30
+ ```js
31
+ const { dataApi } = require('@surf-ai/sdk/server')
32
+
33
+ // Typed methods grouped by category
34
+ const btc = await dataApi.market.price({ symbol: 'BTC', time_range: '1d' })
35
+ const holders = await dataApi.token.holders({ address: '0x...', chain: 'ethereum' })
36
+ const trades = await dataApi.onchain.sql({ sql: 'SELECT ...', max_rows: 100 })
37
+
38
+ // Escape hatch for new endpoints
39
+ const data = await dataApi.get('newcategory/endpoint', { foo: 'bar' })
40
+ ```
41
+
42
+ ### Backend (Express server)
43
+
44
+ ```js
45
+ const { createServer } = require('@surf-ai/sdk/server')
46
+
47
+ // Starts Express with /proxy/*, route auto-loading, DB sync, cron, health check
48
+ createServer({ port: 3001 }).start()
49
+ ```
50
+
51
+ Routes in `routes/*.js` are auto-mounted at `/api/{name}`:
52
+
53
+ ```js
54
+ // routes/btc.js → /api/btc
55
+ const { dataApi } = require('@surf-ai/sdk/server')
56
+ const router = require('express').Router()
57
+
58
+ router.get('/', async (req, res) => {
59
+ const data = await dataApi.market.price({ symbol: 'BTC' })
60
+ res.json(data)
61
+ })
62
+
63
+ module.exports = router
64
+ ```
65
+
66
+ ## Subpath Exports
67
+
68
+ | Import | What |
69
+ |--------|------|
70
+ | `@surf-ai/sdk/server` | `createServer()`, `dataApi` — Express runtime + typed data API |
71
+ | `@surf-ai/sdk/react` | `useMarketPrice()`, `cn()`, `useToast()` — React hooks + utilities |
72
+ | `@surf-ai/sdk/db` | `dbQuery()`, `dbProvision()`, `dbTables()` — Drizzle/Neon database |
73
+
74
+ ## Built-in Endpoints
75
+
76
+ `createServer()` provides these automatically:
77
+
78
+ | Endpoint | Method | Purpose |
79
+ |----------|--------|---------|
80
+ | `/api/health` | GET | Health check — `{ status: 'ok' }` |
81
+ | `/api/__sync-schema` | POST | Sync `db/schema.js` tables to database |
82
+ | `/api/cron` | GET | List cron jobs and status |
83
+ | `/api/cron` | POST | Update cron.json and reload |
84
+ | `/proxy/*` | ANY | Data API passthrough to hermod |
85
+
86
+ Routes in `routes/*.js` are auto-loaded as `/api/{filename}`.
87
+
88
+ DB schema is auto-synced on startup and when `db/schema.js` changes (file watcher).
89
+
90
+ ## Environment Variables
91
+
92
+ The SDK auto-detects the runtime mode from environment variables. New prefixed names take priority; legacy names are supported for backward compatibility.
93
+
94
+ ### Data API routing
95
+
96
+ | Env Var | Legacy | Mode | Set By |
97
+ |---------|--------|------|--------|
98
+ | `SURF_SANDBOX_PROXY_BASE` | `DATA_PROXY_BASE` | Sandbox | urania executor |
99
+ | `SURF_DEPLOYED_GATEWAY_URL` | `GATEWAY_URL` | Deployed | Bifrost |
100
+ | `SURF_DEPLOYED_APP_TOKEN` | `APP_TOKEN` | Deployed | Bifrost |
101
+
102
+ **Routing logic:**
103
+ ```
104
+ if SURF_SANDBOX_PROXY_BASE → sandbox (OutboundProxy handles auth)
105
+ elif SURF_DEPLOYED_GATEWAY_URL + SURF_DEPLOYED_APP_TOKEN → deployed (hermod with Bearer)
106
+ else → public (api.ask.surf, no auth)
107
+ ```
108
+
109
+ ### Server
110
+
111
+ | Env Var | Default | Purpose |
112
+ |---------|---------|---------|
113
+ | `PORT` | `3001` | Express listen port |
114
+
115
+ ### Vite dev server (scaffold, not SDK)
116
+
117
+ | Env Var | Default | Purpose |
118
+ |---------|---------|---------|
119
+ | `VITE_PORT` | `5173` | Frontend dev server port |
120
+ | `VITE_BACKEND_PORT` | `3001` | Backend port for Vite proxy target |
121
+
122
+ ### How routing works
123
+
124
+ ```
125
+ Sandbox (urania preview):
126
+ Frontend hook: useMarketPrice()
127
+ → fetch /proxy/market/price (same-origin to Vite)
128
+ → Vite proxy → Express /proxy/* → OutboundProxy (JWT) → hermod
129
+
130
+ Backend route: dataApi.market.price()
131
+ → fetch SURF_SANDBOX_PROXY_BASE/market/price
132
+ → OutboundProxy (JWT) → hermod
133
+
134
+ Deployed (surf.computer):
135
+ Frontend hook: useMarketPrice()
136
+ → fetch /proxy/market/price (same-origin to Express)
137
+ → Express /proxy/* → hermod (APP_TOKEN)
138
+
139
+ Backend route: dataApi.market.price()
140
+ → fetch http://127.0.0.1:PORT/proxy/market/price (loopback)
141
+ → Express /proxy/* → hermod (APP_TOKEN)
142
+
143
+ Public (local dev):
144
+ Frontend hook: useMarketPrice()
145
+ → fetch /proxy/market/price (same-origin to Vite)
146
+ → Vite proxy → Express /proxy/* → hermod (GATEWAY_URL + APP_TOKEN)
147
+
148
+ Backend route: dataApi.market.price()
149
+ → fetch SURF_DEPLOYED_GATEWAY_URL/gateway/v1/market/price (Bearer APP_TOKEN)
150
+ ```
151
+
152
+ ## Available Categories
153
+
154
+ | Category | Example Methods |
155
+ |----------|----------------|
156
+ | `market` | `price`, `ranking`, `etf`, `futures`, `options`, `fear_greed` |
157
+ | `token` | `holders`, `transfers`, `dex_trades`, `tokenomics` |
158
+ | `wallet` | `detail`, `net_worth`, `labels_batch`, `transfers` |
159
+ | `onchain` | `sql`, `tx`, `gas_price`, `schema`, `structured_query` |
160
+ | `social` | `detail`, `mindshare`, `tweets`, `user`, `ranking` |
161
+ | `project` | `detail`, `defi_metrics`, `defi_ranking` |
162
+ | `news` | `detail`, `feed` |
163
+ | `exchange` | `price`, `depth`, `klines`, `funding_history`, `perp` |
164
+ | `fund` | `detail`, `portfolio`, `ranking` |
165
+ | `search` | `project`, `news`, `wallet`, `web` |
166
+ | `web` | `fetch` |
167
+ | `polymarket` | `events`, `markets`, `prices`, `volumes` |
168
+ | `kalshi` | `events`, `markets`, `prices`, `volumes` |
169
+ | `prediction_market` | `category_metrics` |
170
+
171
+ ## Codegen
172
+
173
+ API methods and React hooks are auto-generated from hermod's OpenAPI spec via the surf CLI:
174
+
175
+ ```bash
176
+ # Regenerate all endpoints
177
+ python scripts/gen_sdk.py
178
+
179
+ # Regenerate specific endpoints
180
+ python scripts/gen_sdk.py --ops market-price token-holders
181
+
182
+ # Build
183
+ bun run build
184
+ ```
185
+
186
+ Requires `surf` CLI installed and authenticated (`surf login`).
187
+
188
+ ## Development
189
+
190
+ ```bash
191
+ bun install
192
+ bun run build # compile TypeScript
193
+ bun test # run tests
194
+ bun run codegen # regenerate from OpenAPI spec
195
+ ```
196
+
197
+ ## Testing
198
+
199
+ ```bash
200
+ # Unit tests
201
+ bun test ./tests/data-client.test.ts
202
+
203
+ # E2E (auto-detects mode from env vars)
204
+ bun test ./tests/e2e-all-envs.test.ts
205
+
206
+ # E2E with specific mode:
207
+ SURF_SANDBOX_PROXY_BASE=http://127.0.0.1:9999/s/<session>/proxy bun test ./tests/e2e-all-envs.test.ts
208
+ SURF_DEPLOYED_GATEWAY_URL=https://api.ask.surf SURF_DEPLOYED_APP_TOKEN=<token> bun test ./tests/e2e-all-envs.test.ts
209
+ ```
@@ -0,0 +1,70 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
8
+ // src/data/client.ts
9
+ var DEFAULT_PUBLIC_URL = "https://api.ask.surf/gateway/v1";
10
+ function env(surfName, legacyName) {
11
+ return process.env[surfName] || process.env[legacyName];
12
+ }
13
+ function resolveConfig() {
14
+ const proxyBase = env("SURF_SANDBOX_PROXY_BASE", "DATA_PROXY_BASE");
15
+ if (proxyBase) {
16
+ return { baseUrl: proxyBase, headers: {} };
17
+ }
18
+ const gatewayUrl = env("SURF_DEPLOYED_GATEWAY_URL", "GATEWAY_URL");
19
+ const appToken = env("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
20
+ if (gatewayUrl && appToken) {
21
+ return {
22
+ baseUrl: `${gatewayUrl.replace(/\/$/, "")}/gateway/v1`,
23
+ headers: { Authorization: `Bearer ${appToken}` }
24
+ };
25
+ }
26
+ return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
27
+ }
28
+ function normalizePath(path) {
29
+ return String(path || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
30
+ }
31
+ async function fetchJson(url, init, retries = 1) {
32
+ for (let attempt = 0; attempt <= retries; attempt++) {
33
+ const res = await fetch(url, init);
34
+ if (!res.ok) {
35
+ const text2 = await res.text();
36
+ throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
37
+ }
38
+ const text = await res.text();
39
+ if (text) return JSON.parse(text);
40
+ if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
41
+ }
42
+ throw new Error(`Empty response from ${url}`);
43
+ }
44
+ async function get(path, params) {
45
+ const config = resolveConfig();
46
+ const cleaned = {};
47
+ if (params) {
48
+ for (const [k, v] of Object.entries(params)) {
49
+ if (v != null) cleaned[k] = String(v);
50
+ }
51
+ }
52
+ const qs = Object.keys(cleaned).length ? "?" + new URLSearchParams(cleaned).toString() : "";
53
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}${qs}`, {
54
+ headers: config.headers
55
+ });
56
+ }
57
+ async function post(path, body) {
58
+ const config = resolveConfig();
59
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}`, {
60
+ method: "POST",
61
+ headers: { ...config.headers, "Content-Type": "application/json" },
62
+ body: body ? JSON.stringify(body) : void 0
63
+ });
64
+ }
65
+
66
+ export {
67
+ __require,
68
+ get,
69
+ post
70
+ };
@@ -0,0 +1,8 @@
1
+ import {
2
+ get,
3
+ post
4
+ } from "./chunk-J4OMYO3F.js";
5
+ export {
6
+ get,
7
+ post
8
+ };
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/db/index.ts
21
+ var db_exports = {};
22
+ __export(db_exports, {
23
+ dbProvision: () => dbProvision,
24
+ dbQuery: () => dbQuery,
25
+ dbStatus: () => dbStatus,
26
+ dbTableSchema: () => dbTableSchema,
27
+ dbTables: () => dbTables
28
+ });
29
+ module.exports = __toCommonJS(db_exports);
30
+
31
+ // src/data/client.ts
32
+ var DEFAULT_PUBLIC_URL = "https://api.ask.surf/gateway/v1";
33
+ function env(surfName, legacyName) {
34
+ return process.env[surfName] || process.env[legacyName];
35
+ }
36
+ function resolveConfig() {
37
+ const proxyBase = env("SURF_SANDBOX_PROXY_BASE", "DATA_PROXY_BASE");
38
+ if (proxyBase) {
39
+ return { baseUrl: proxyBase, headers: {} };
40
+ }
41
+ const gatewayUrl = env("SURF_DEPLOYED_GATEWAY_URL", "GATEWAY_URL");
42
+ const appToken = env("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
43
+ if (gatewayUrl && appToken) {
44
+ return {
45
+ baseUrl: `${gatewayUrl.replace(/\/$/, "")}/gateway/v1`,
46
+ headers: { Authorization: `Bearer ${appToken}` }
47
+ };
48
+ }
49
+ return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
50
+ }
51
+ function normalizePath(path) {
52
+ return String(path || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
53
+ }
54
+ async function fetchJson(url, init, retries = 1) {
55
+ for (let attempt = 0; attempt <= retries; attempt++) {
56
+ const res = await fetch(url, init);
57
+ if (!res.ok) {
58
+ const text2 = await res.text();
59
+ throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
60
+ }
61
+ const text = await res.text();
62
+ if (text) return JSON.parse(text);
63
+ if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
64
+ }
65
+ throw new Error(`Empty response from ${url}`);
66
+ }
67
+ async function get(path, params) {
68
+ const config = resolveConfig();
69
+ const cleaned = {};
70
+ if (params) {
71
+ for (const [k, v] of Object.entries(params)) {
72
+ if (v != null) cleaned[k] = String(v);
73
+ }
74
+ }
75
+ const qs = Object.keys(cleaned).length ? "?" + new URLSearchParams(cleaned).toString() : "";
76
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}${qs}`, {
77
+ headers: config.headers
78
+ });
79
+ }
80
+ async function post(path, body) {
81
+ const config = resolveConfig();
82
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}`, {
83
+ method: "POST",
84
+ headers: { ...config.headers, "Content-Type": "application/json" },
85
+ body: body ? JSON.stringify(body) : void 0
86
+ });
87
+ }
88
+
89
+ // src/db/index.ts
90
+ async function dbProvision() {
91
+ return post("db/provision");
92
+ }
93
+ async function dbQuery(sql, params, options) {
94
+ return post("db/query", { sql, params, method: options?.arrayMode ? "all" : "execute" });
95
+ }
96
+ async function dbTables() {
97
+ return get("db/tables");
98
+ }
99
+ async function dbTableSchema(table) {
100
+ return get("db/table-schema", { table });
101
+ }
102
+ async function dbStatus() {
103
+ return get("db/status");
104
+ }
105
+ // Annotate the CommonJS export names for ESM import in node:
106
+ 0 && (module.exports = {
107
+ dbProvision,
108
+ dbQuery,
109
+ dbStatus,
110
+ dbTableSchema,
111
+ dbTables
112
+ });
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @surf-ai/sdk/db — Drizzle ORM + Neon PostgreSQL database helpers.
3
+ *
4
+ * Replaces scaffold lib/db.js and db/index.js.
5
+ *
6
+ * Usage:
7
+ * const { db, dbQuery, dbProvision } = require('@surf-ai/sdk/db')
8
+ *
9
+ * // In a backend route:
10
+ * const users = await db.select().from(schema.users)
11
+ *
12
+ * // Raw SQL:
13
+ * const result = await dbQuery('SELECT * FROM users WHERE id = $1', [userId])
14
+ */
15
+ /**
16
+ * Provision a database for the current user via /proxy/db/provision.
17
+ * Returns connection metadata. Neon auto-creates the DB if it doesn't exist.
18
+ */
19
+ declare function dbProvision(): Promise<{
20
+ host: string;
21
+ database: string;
22
+ user: string;
23
+ password: string;
24
+ }>;
25
+ /**
26
+ * Execute a SQL query via /proxy/db/query.
27
+ * Uses pg-proxy driver under the hood — Drizzle ORM calls this automatically.
28
+ */
29
+ declare function dbQuery(sql: string, params?: any[], options?: {
30
+ arrayMode?: boolean;
31
+ }): Promise<any>;
32
+ /**
33
+ * List tables in the user's database.
34
+ */
35
+ declare function dbTables(): Promise<string[]>;
36
+ /**
37
+ * Get schema for a specific table.
38
+ */
39
+ declare function dbTableSchema(table: string): Promise<any>;
40
+ /**
41
+ * Check database connection status.
42
+ */
43
+ declare function dbStatus(): Promise<{
44
+ connected: boolean;
45
+ database?: string;
46
+ }>;
47
+
48
+ export { dbProvision, dbQuery, dbStatus, dbTableSchema, dbTables };
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @surf-ai/sdk/db — Drizzle ORM + Neon PostgreSQL database helpers.
3
+ *
4
+ * Replaces scaffold lib/db.js and db/index.js.
5
+ *
6
+ * Usage:
7
+ * const { db, dbQuery, dbProvision } = require('@surf-ai/sdk/db')
8
+ *
9
+ * // In a backend route:
10
+ * const users = await db.select().from(schema.users)
11
+ *
12
+ * // Raw SQL:
13
+ * const result = await dbQuery('SELECT * FROM users WHERE id = $1', [userId])
14
+ */
15
+ /**
16
+ * Provision a database for the current user via /proxy/db/provision.
17
+ * Returns connection metadata. Neon auto-creates the DB if it doesn't exist.
18
+ */
19
+ declare function dbProvision(): Promise<{
20
+ host: string;
21
+ database: string;
22
+ user: string;
23
+ password: string;
24
+ }>;
25
+ /**
26
+ * Execute a SQL query via /proxy/db/query.
27
+ * Uses pg-proxy driver under the hood — Drizzle ORM calls this automatically.
28
+ */
29
+ declare function dbQuery(sql: string, params?: any[], options?: {
30
+ arrayMode?: boolean;
31
+ }): Promise<any>;
32
+ /**
33
+ * List tables in the user's database.
34
+ */
35
+ declare function dbTables(): Promise<string[]>;
36
+ /**
37
+ * Get schema for a specific table.
38
+ */
39
+ declare function dbTableSchema(table: string): Promise<any>;
40
+ /**
41
+ * Check database connection status.
42
+ */
43
+ declare function dbStatus(): Promise<{
44
+ connected: boolean;
45
+ database?: string;
46
+ }>;
47
+
48
+ export { dbProvision, dbQuery, dbStatus, dbTableSchema, dbTables };
@@ -0,0 +1,81 @@
1
+ // src/data/client.ts
2
+ var DEFAULT_PUBLIC_URL = "https://api.ask.surf/gateway/v1";
3
+ function env(surfName, legacyName) {
4
+ return process.env[surfName] || process.env[legacyName];
5
+ }
6
+ function resolveConfig() {
7
+ const proxyBase = env("SURF_SANDBOX_PROXY_BASE", "DATA_PROXY_BASE");
8
+ if (proxyBase) {
9
+ return { baseUrl: proxyBase, headers: {} };
10
+ }
11
+ const gatewayUrl = env("SURF_DEPLOYED_GATEWAY_URL", "GATEWAY_URL");
12
+ const appToken = env("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
13
+ if (gatewayUrl && appToken) {
14
+ return {
15
+ baseUrl: `${gatewayUrl.replace(/\/$/, "")}/gateway/v1`,
16
+ headers: { Authorization: `Bearer ${appToken}` }
17
+ };
18
+ }
19
+ return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
20
+ }
21
+ function normalizePath(path) {
22
+ return String(path || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
23
+ }
24
+ async function fetchJson(url, init, retries = 1) {
25
+ for (let attempt = 0; attempt <= retries; attempt++) {
26
+ const res = await fetch(url, init);
27
+ if (!res.ok) {
28
+ const text2 = await res.text();
29
+ throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
30
+ }
31
+ const text = await res.text();
32
+ if (text) return JSON.parse(text);
33
+ if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
34
+ }
35
+ throw new Error(`Empty response from ${url}`);
36
+ }
37
+ async function get(path, params) {
38
+ const config = resolveConfig();
39
+ const cleaned = {};
40
+ if (params) {
41
+ for (const [k, v] of Object.entries(params)) {
42
+ if (v != null) cleaned[k] = String(v);
43
+ }
44
+ }
45
+ const qs = Object.keys(cleaned).length ? "?" + new URLSearchParams(cleaned).toString() : "";
46
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}${qs}`, {
47
+ headers: config.headers
48
+ });
49
+ }
50
+ async function post(path, body) {
51
+ const config = resolveConfig();
52
+ return fetchJson(`${config.baseUrl}/${normalizePath(path)}`, {
53
+ method: "POST",
54
+ headers: { ...config.headers, "Content-Type": "application/json" },
55
+ body: body ? JSON.stringify(body) : void 0
56
+ });
57
+ }
58
+
59
+ // src/db/index.ts
60
+ async function dbProvision() {
61
+ return post("db/provision");
62
+ }
63
+ async function dbQuery(sql, params, options) {
64
+ return post("db/query", { sql, params, method: options?.arrayMode ? "all" : "execute" });
65
+ }
66
+ async function dbTables() {
67
+ return get("db/tables");
68
+ }
69
+ async function dbTableSchema(table) {
70
+ return get("db/table-schema", { table });
71
+ }
72
+ async function dbStatus() {
73
+ return get("db/status");
74
+ }
75
+ export {
76
+ dbProvision,
77
+ dbQuery,
78
+ dbStatus,
79
+ dbTableSchema,
80
+ dbTables
81
+ };