@surf-ai/sdk 0.1.6-beta → 1.0.0-alpha.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/dist/db/index.cjs CHANGED
@@ -28,28 +28,49 @@ __export(db_exports, {
28
28
  });
29
29
  module.exports = __toCommonJS(db_exports);
30
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
- };
31
+ // src/core/config.ts
32
+ var DEFAULT_API_BASE_URL = "https://api.ask.surf/gateway/v1";
33
+ function trimTrailingSlashes(value) {
34
+ return String(value || "").replace(/\/+$/, "");
35
+ }
36
+ function readSurfApiConfig() {
37
+ return {
38
+ baseUrl: trimTrailingSlashes(process.env.SURF_API_BASE_URL || DEFAULT_API_BASE_URL),
39
+ apiKey: process.env.SURF_API_KEY
40
+ };
41
+ }
42
+ function requireSurfApiConfig() {
43
+ const config = readSurfApiConfig();
44
+ if (!config.apiKey) {
45
+ throw new Error("SURF_API_KEY is required");
48
46
  }
49
- return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
47
+ return { baseUrl: config.baseUrl, apiKey: config.apiKey };
48
+ }
49
+
50
+ // src/core/transport.ts
51
+ function sleep(ms) {
52
+ return new Promise((resolve) => setTimeout(resolve, ms));
50
53
  }
51
54
  function normalizePath(path) {
52
- return String(path || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
55
+ return String(path || "").replace(/^\/+/, "");
56
+ }
57
+ function buildUrl(path, params) {
58
+ const { baseUrl } = requireSurfApiConfig();
59
+ const url = new URL(`${baseUrl}/${normalizePath(path)}`);
60
+ if (params) {
61
+ for (const [key, value] of Object.entries(params)) {
62
+ if (value != null) {
63
+ url.searchParams.set(key, String(value));
64
+ }
65
+ }
66
+ }
67
+ return url.toString();
68
+ }
69
+ function buildHeaders(extra) {
70
+ const { apiKey } = requireSurfApiConfig();
71
+ const headers = new Headers(extra);
72
+ headers.set("Authorization", `Bearer ${apiKey}`);
73
+ return headers;
53
74
  }
54
75
  async function fetchJson(url, init, retries = 1) {
55
76
  for (let attempt = 0; attempt <= retries; attempt++) {
@@ -59,33 +80,38 @@ async function fetchJson(url, init, retries = 1) {
59
80
  throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
60
81
  }
61
82
  const text = await res.text();
62
- if (text) return JSON.parse(text);
63
- if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
83
+ if (text) {
84
+ return JSON.parse(text);
85
+ }
86
+ if (attempt < retries) {
87
+ await sleep(1e3);
88
+ }
64
89
  }
65
90
  throw new Error(`Empty response from ${url}`);
66
91
  }
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
92
+ async function getJson(path, params) {
93
+ return fetchJson(buildUrl(path, params), {
94
+ headers: buildHeaders()
78
95
  });
79
96
  }
80
- async function post(path, body) {
81
- const config = resolveConfig();
82
- return fetchJson(`${config.baseUrl}/${normalizePath(path)}`, {
97
+ async function postJson(path, body) {
98
+ return fetchJson(buildUrl(path), {
83
99
  method: "POST",
84
- headers: { ...config.headers, "Content-Type": "application/json" },
100
+ headers: buildHeaders({
101
+ "Content-Type": "application/json"
102
+ }),
85
103
  body: body ? JSON.stringify(body) : void 0
86
104
  });
87
105
  }
88
106
 
107
+ // src/data/client.ts
108
+ async function get(path, params) {
109
+ return getJson(path, params);
110
+ }
111
+ async function post(path, body) {
112
+ return postJson(path, body);
113
+ }
114
+
89
115
  // src/db/index.ts
90
116
  async function dbProvision() {
91
117
  return post("db/provision");
@@ -13,7 +13,7 @@
13
13
  * const result = await dbQuery('SELECT * FROM users WHERE id = $1', [userId])
14
14
  */
15
15
  /**
16
- * Provision a database for the current user via /proxy/db/provision.
16
+ * Provision a database for the current user via db/provision.
17
17
  * Returns connection metadata. Neon auto-creates the DB if it doesn't exist.
18
18
  */
19
19
  declare function dbProvision(): Promise<{
@@ -23,7 +23,7 @@ declare function dbProvision(): Promise<{
23
23
  password: string;
24
24
  }>;
25
25
  /**
26
- * Execute a SQL query via /proxy/db/query.
26
+ * Execute a SQL query via db/query.
27
27
  * Uses pg-proxy driver under the hood — Drizzle ORM calls this automatically.
28
28
  *
29
29
  * @param options.arrayMode - When true, rows are returned as positional arrays
@@ -13,7 +13,7 @@
13
13
  * const result = await dbQuery('SELECT * FROM users WHERE id = $1', [userId])
14
14
  */
15
15
  /**
16
- * Provision a database for the current user via /proxy/db/provision.
16
+ * Provision a database for the current user via db/provision.
17
17
  * Returns connection metadata. Neon auto-creates the DB if it doesn't exist.
18
18
  */
19
19
  declare function dbProvision(): Promise<{
@@ -23,7 +23,7 @@ declare function dbProvision(): Promise<{
23
23
  password: string;
24
24
  }>;
25
25
  /**
26
- * Execute a SQL query via /proxy/db/query.
26
+ * Execute a SQL query via db/query.
27
27
  * Uses pg-proxy driver under the hood — Drizzle ORM calls this automatically.
28
28
  *
29
29
  * @param options.arrayMode - When true, rows are returned as positional arrays
package/dist/db/index.js CHANGED
@@ -1,25 +1,46 @@
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
- };
1
+ // src/core/config.ts
2
+ var DEFAULT_API_BASE_URL = "https://api.ask.surf/gateway/v1";
3
+ function trimTrailingSlashes(value) {
4
+ return String(value || "").replace(/\/+$/, "");
5
+ }
6
+ function readSurfApiConfig() {
7
+ return {
8
+ baseUrl: trimTrailingSlashes(process.env.SURF_API_BASE_URL || DEFAULT_API_BASE_URL),
9
+ apiKey: process.env.SURF_API_KEY
10
+ };
11
+ }
12
+ function requireSurfApiConfig() {
13
+ const config = readSurfApiConfig();
14
+ if (!config.apiKey) {
15
+ throw new Error("SURF_API_KEY is required");
18
16
  }
19
- return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
17
+ return { baseUrl: config.baseUrl, apiKey: config.apiKey };
18
+ }
19
+
20
+ // src/core/transport.ts
21
+ function sleep(ms) {
22
+ return new Promise((resolve) => setTimeout(resolve, ms));
20
23
  }
21
24
  function normalizePath(path) {
22
- return String(path || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
25
+ return String(path || "").replace(/^\/+/, "");
26
+ }
27
+ function buildUrl(path, params) {
28
+ const { baseUrl } = requireSurfApiConfig();
29
+ const url = new URL(`${baseUrl}/${normalizePath(path)}`);
30
+ if (params) {
31
+ for (const [key, value] of Object.entries(params)) {
32
+ if (value != null) {
33
+ url.searchParams.set(key, String(value));
34
+ }
35
+ }
36
+ }
37
+ return url.toString();
38
+ }
39
+ function buildHeaders(extra) {
40
+ const { apiKey } = requireSurfApiConfig();
41
+ const headers = new Headers(extra);
42
+ headers.set("Authorization", `Bearer ${apiKey}`);
43
+ return headers;
23
44
  }
24
45
  async function fetchJson(url, init, retries = 1) {
25
46
  for (let attempt = 0; attempt <= retries; attempt++) {
@@ -29,33 +50,38 @@ async function fetchJson(url, init, retries = 1) {
29
50
  throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
30
51
  }
31
52
  const text = await res.text();
32
- if (text) return JSON.parse(text);
33
- if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
53
+ if (text) {
54
+ return JSON.parse(text);
55
+ }
56
+ if (attempt < retries) {
57
+ await sleep(1e3);
58
+ }
34
59
  }
35
60
  throw new Error(`Empty response from ${url}`);
36
61
  }
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
62
+ async function getJson(path, params) {
63
+ return fetchJson(buildUrl(path, params), {
64
+ headers: buildHeaders()
48
65
  });
49
66
  }
50
- async function post(path, body) {
51
- const config = resolveConfig();
52
- return fetchJson(`${config.baseUrl}/${normalizePath(path)}`, {
67
+ async function postJson(path, body) {
68
+ return fetchJson(buildUrl(path), {
53
69
  method: "POST",
54
- headers: { ...config.headers, "Content-Type": "application/json" },
70
+ headers: buildHeaders({
71
+ "Content-Type": "application/json"
72
+ }),
55
73
  body: body ? JSON.stringify(body) : void 0
56
74
  });
57
75
  }
58
76
 
77
+ // src/data/client.ts
78
+ async function get(path, params) {
79
+ return getJson(path, params);
80
+ }
81
+ async function post(path, body) {
82
+ return postJson(path, body);
83
+ }
84
+
59
85
  // src/db/index.ts
60
86
  async function dbProvision() {
61
87
  return post("db/provision");
@@ -30,32 +30,58 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/data/client.ts
34
- var client_exports = {};
35
- __export(client_exports, {
36
- get: () => get,
37
- post: () => post
38
- });
39
- function env(surfName, legacyName) {
40
- return process.env[surfName] || process.env[legacyName];
33
+ // src/core/config.ts
34
+ function trimTrailingSlashes(value) {
35
+ return String(value || "").replace(/\/+$/, "");
36
+ }
37
+ function readSurfApiConfig() {
38
+ return {
39
+ baseUrl: trimTrailingSlashes(process.env.SURF_API_BASE_URL || DEFAULT_API_BASE_URL),
40
+ apiKey: process.env.SURF_API_KEY
41
+ };
41
42
  }
42
- function resolveConfig() {
43
- const proxyBase = env("SURF_SANDBOX_PROXY_BASE", "DATA_PROXY_BASE");
44
- if (proxyBase) {
45
- return { baseUrl: proxyBase, headers: {} };
43
+ function requireSurfApiConfig() {
44
+ const config = readSurfApiConfig();
45
+ if (!config.apiKey) {
46
+ throw new Error("SURF_API_KEY is required");
46
47
  }
47
- const gatewayUrl = env("SURF_DEPLOYED_GATEWAY_URL", "GATEWAY_URL");
48
- const appToken = env("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
49
- if (gatewayUrl && appToken) {
50
- return {
51
- baseUrl: `${gatewayUrl.replace(/\/$/, "")}/gateway/v1`,
52
- headers: { Authorization: `Bearer ${appToken}` }
53
- };
48
+ return { baseUrl: config.baseUrl, apiKey: config.apiKey };
49
+ }
50
+ function readAdminApiKey() {
51
+ return process.env.SURF_API_KEY;
52
+ }
53
+ var DEFAULT_API_BASE_URL;
54
+ var init_config = __esm({
55
+ "src/core/config.ts"() {
56
+ "use strict";
57
+ DEFAULT_API_BASE_URL = "https://api.ask.surf/gateway/v1";
54
58
  }
55
- return { baseUrl: DEFAULT_PUBLIC_URL, headers: {} };
59
+ });
60
+
61
+ // src/core/transport.ts
62
+ function sleep(ms) {
63
+ return new Promise((resolve) => setTimeout(resolve, ms));
56
64
  }
57
65
  function normalizePath(path2) {
58
- return String(path2 || "").replace(/^\/+/, "").replace(/^(?:proxy\/)+/, "");
66
+ return String(path2 || "").replace(/^\/+/, "");
67
+ }
68
+ function buildUrl(path2, params) {
69
+ const { baseUrl } = requireSurfApiConfig();
70
+ const url = new URL(`${baseUrl}/${normalizePath(path2)}`);
71
+ if (params) {
72
+ for (const [key, value] of Object.entries(params)) {
73
+ if (value != null) {
74
+ url.searchParams.set(key, String(value));
75
+ }
76
+ }
77
+ }
78
+ return url.toString();
79
+ }
80
+ function buildHeaders(extra) {
81
+ const { apiKey } = requireSurfApiConfig();
82
+ const headers = new Headers(extra);
83
+ headers.set("Authorization", `Bearer ${apiKey}`);
84
+ return headers;
59
85
  }
60
86
  async function fetchJson(url, init, retries = 1) {
61
87
  for (let attempt = 0; attempt <= retries; attempt++) {
@@ -65,37 +91,52 @@ async function fetchJson(url, init, retries = 1) {
65
91
  throw new Error(`API error ${res.status}: ${text2.slice(0, 200)}`);
66
92
  }
67
93
  const text = await res.text();
68
- if (text) return JSON.parse(text);
69
- if (attempt < retries) await new Promise((r) => setTimeout(r, 1e3));
94
+ if (text) {
95
+ return JSON.parse(text);
96
+ }
97
+ if (attempt < retries) {
98
+ await sleep(1e3);
99
+ }
70
100
  }
71
101
  throw new Error(`Empty response from ${url}`);
72
102
  }
73
- async function get(path2, params) {
74
- const config = resolveConfig();
75
- const cleaned = {};
76
- if (params) {
77
- for (const [k, v] of Object.entries(params)) {
78
- if (v != null) cleaned[k] = String(v);
79
- }
80
- }
81
- const qs = Object.keys(cleaned).length ? "?" + new URLSearchParams(cleaned).toString() : "";
82
- return fetchJson(`${config.baseUrl}/${normalizePath(path2)}${qs}`, {
83
- headers: config.headers
103
+ async function getJson(path2, params) {
104
+ return fetchJson(buildUrl(path2, params), {
105
+ headers: buildHeaders()
84
106
  });
85
107
  }
86
- async function post(path2, body) {
87
- const config = resolveConfig();
88
- return fetchJson(`${config.baseUrl}/${normalizePath(path2)}`, {
108
+ async function postJson(path2, body) {
109
+ return fetchJson(buildUrl(path2), {
89
110
  method: "POST",
90
- headers: { ...config.headers, "Content-Type": "application/json" },
111
+ headers: buildHeaders({
112
+ "Content-Type": "application/json"
113
+ }),
91
114
  body: body ? JSON.stringify(body) : void 0
92
115
  });
93
116
  }
94
- var DEFAULT_PUBLIC_URL;
117
+ var init_transport = __esm({
118
+ "src/core/transport.ts"() {
119
+ "use strict";
120
+ init_config();
121
+ }
122
+ });
123
+
124
+ // src/data/client.ts
125
+ var client_exports = {};
126
+ __export(client_exports, {
127
+ get: () => get,
128
+ post: () => post
129
+ });
130
+ async function get(path2, params) {
131
+ return getJson(path2, params);
132
+ }
133
+ async function post(path2, body) {
134
+ return postJson(path2, body);
135
+ }
95
136
  var init_client = __esm({
96
137
  "src/data/client.ts"() {
97
138
  "use strict";
98
- DEFAULT_PUBLIC_URL = "https://api.ask.surf/gateway/v1";
139
+ init_transport();
99
140
  }
100
141
  });
101
142
 
@@ -112,18 +153,27 @@ var import_express = __toESM(require("express"), 1);
112
153
  var import_cors = __toESM(require("cors"), 1);
113
154
  var import_fs = __toESM(require("fs"), 1);
114
155
  var import_path = __toESM(require("path"), 1);
115
- var import_http_proxy_middleware = require("http-proxy-middleware");
116
156
  var import_croner = require("croner");
157
+ init_config();
158
+ function requireBearerAuth(req, res, next) {
159
+ const apiKey = readAdminApiKey();
160
+ if (!apiKey) {
161
+ return res.status(503).json({ error: "SURF_API_KEY is not configured" });
162
+ }
163
+ if (req.headers.authorization !== `Bearer ${apiKey}`) {
164
+ return res.status(401).json({ error: "Unauthorized" });
165
+ }
166
+ next();
167
+ }
117
168
  function createServer(options = {}) {
118
- const port = options.port || parseInt(process.env.PORT || "3001", 10);
169
+ const port = options.port ?? (process.env.PORT ? Number.parseInt(process.env.PORT, 10) : void 0);
170
+ if (!Number.isInteger(port)) {
171
+ throw new Error("createServer requires a port via options.port or process.env.PORT");
172
+ }
119
173
  const routesDir = options.routesDir || import_path.default.join(process.cwd(), "routes");
120
174
  const cronDir = options.cronDir || process.cwd();
121
- const enableProxy = options.proxy !== false;
122
175
  const app = (0, import_express.default)();
123
176
  app.use((0, import_cors.default)());
124
- if (enableProxy) {
125
- setupProxy(app, port);
126
- }
127
177
  app.use(import_express.default.json());
128
178
  app.get("/api/health", (_req, res) => {
129
179
  res.json({ status: "ok" });
@@ -133,12 +183,13 @@ function createServer(options = {}) {
133
183
  if (!file.endsWith(".js") && !file.endsWith(".ts")) continue;
134
184
  const name = file.replace(/\.(js|ts)$/, "");
135
185
  try {
136
- const route = require(import_path.default.join(routesDir, file));
137
- const handler = route.default || route;
186
+ const handler = require(import_path.default.join(routesDir, file));
138
187
  if (typeof handler === "function") {
139
188
  app.use(`/api/${name}`, handler);
140
189
  console.log(`Route registered: /api/${name}`);
190
+ continue;
141
191
  }
192
+ throw new Error(`Route module must export a handler function via module.exports`);
142
193
  } catch (err) {
143
194
  console.error(`Failed to load route ${file}: ${err.message}`);
144
195
  }
@@ -162,51 +213,6 @@ function createServer(options = {}) {
162
213
  }
163
214
  };
164
215
  }
165
- function env2(surfName, legacyName) {
166
- return process.env[surfName] || process.env[legacyName];
167
- }
168
- function setupProxy(app, port) {
169
- const gatewayUrl = env2("SURF_DEPLOYED_GATEWAY_URL", "GATEWAY_URL");
170
- const appToken = env2("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
171
- const proxyBase = env2("SURF_SANDBOX_PROXY_BASE", "DATA_PROXY_BASE");
172
- const isDeployed = Boolean(gatewayUrl && appToken);
173
- const bufferResponse = (0, import_http_proxy_middleware.responseInterceptor)(async (buf) => buf);
174
- if (isDeployed) {
175
- app.use("/proxy", (0, import_http_proxy_middleware.createProxyMiddleware)({
176
- target: gatewayUrl,
177
- changeOrigin: true,
178
- selfHandleResponse: true,
179
- pathRewrite: (p) => "/gateway/v1" + p,
180
- headers: {
181
- Authorization: `Bearer ${appToken}`,
182
- "Accept-Encoding": "identity"
183
- },
184
- on: { proxyRes: bufferResponse }
185
- }));
186
- const loopback = `http://127.0.0.1:${port}/proxy`;
187
- process.env.SURF_SANDBOX_PROXY_BASE = loopback;
188
- process.env.DATA_PROXY_BASE = loopback;
189
- } else if (proxyBase) {
190
- const target = proxyBase.replace(/\/proxy$/, "");
191
- app.use((0, import_http_proxy_middleware.createProxyMiddleware)({
192
- target,
193
- changeOrigin: true,
194
- pathFilter: "/proxy",
195
- on: {
196
- proxyReq: (proxyReq, req) => {
197
- console.log(`[proxy] >> ${req.method} ${req.originalUrl}`);
198
- },
199
- proxyRes: (proxyRes, req) => {
200
- console.log(`[proxy] << ${proxyRes.statusCode} ${req.method} ${req.originalUrl}`);
201
- },
202
- error: (err, req, res) => {
203
- console.error(`[proxy] !! ${req.method} ${req.originalUrl} error: ${err.message}`);
204
- if (!res.headersSent) res.status(502).json({ error: err.message });
205
- }
206
- }
207
- }));
208
- }
209
- }
210
216
  var schemaSync = { run: async () => {
211
217
  }, watch: () => {
212
218
  } };
@@ -310,7 +316,7 @@ function setupSchemaSync(app, schemaDir) {
310
316
  }
311
317
  console.error("DB schema sync failed after all retries");
312
318
  }
313
- app.post("/api/__sync-schema", async (_req, res) => {
319
+ app.post("/api/__sync-schema", requireBearerAuth, async (_req, res) => {
314
320
  try {
315
321
  await syncWithRetry(2, 1500);
316
322
  res.json({ ok: true });
@@ -414,16 +420,7 @@ function setupCron(app, cronDir) {
414
420
  console.log(`Cron registered: [${task.id}] ${task.name} (${task.schedule})`);
415
421
  }
416
422
  }
417
- const envFn = (s, l) => process.env[s] || process.env[l];
418
- app.use("/api/cron", (req, res, next) => {
419
- const appToken = envFn("SURF_DEPLOYED_APP_TOKEN", "APP_TOKEN");
420
- if (!appToken) return next();
421
- const auth = req.headers.authorization;
422
- if (!auth || auth !== `Bearer ${appToken}`) {
423
- return res.status(401).json({ error: "Unauthorized" });
424
- }
425
- next();
426
- });
423
+ app.use("/api/cron", requireBearerAuth);
427
424
  app.get("/api/cron", (_req, res) => {
428
425
  res.json(cronTasks.map((t) => {
429
426
  const state = cronState.get(t.id) || { lastRunAt: null, lastStatus: null, lastError: null };
@@ -1,10 +1,9 @@
1
1
  import express from 'express';
2
2
 
3
3
  /**
4
- * Express server runtime — replaces scaffold server.js + routes/proxy.js.
4
+ * Express server runtime — replaces scaffold server.js.
5
5
  *
6
6
  * Handles:
7
- * - /proxy/* passthrough (env-aware: sandbox → OutboundProxy, deployed → hermod)
8
7
  * - Auto-loading routes from routes/*.js → /api/{name}
9
8
  * - Cron job system from cron.json
10
9
  * - DB schema sync on startup
@@ -12,18 +11,16 @@ import express from 'express';
12
11
  */
13
12
 
14
13
  interface ServerOptions {
15
- /** Port to listen on (default: PORT env, fallback 3001) */
14
+ /** Port to listen on. Falls back to the PORT env var when omitted. */
16
15
  port?: number;
17
16
  /** Directory containing route files (default: ./routes) */
18
17
  routesDir?: string;
19
18
  /** Directory containing cron.json (default: .) */
20
19
  cronDir?: string;
21
- /** Enable /proxy/* passthrough (default: true) */
22
- proxy?: boolean;
23
20
  }
24
21
  declare function createServer(options?: ServerOptions): {
25
22
  app: express.Express;
26
- port: number;
23
+ port: number | undefined;
27
24
  start(): Promise<void>;
28
25
  };
29
26
 
@@ -3454,17 +3451,14 @@ interface V2PolymarketVolumeChartParams {
3454
3451
  }
3455
3452
 
3456
3453
  /**
3457
- * Environment-aware data API client.
3454
+ * 1.0 data API client.
3458
3455
  *
3459
- * Reads env vars to determine routing (prefixed vars take priority):
3460
- * - SURF_SANDBOX_PROXY_BASE → sandbox (OutboundProxy handles auth)
3461
- * - SURF_DEPLOYED_GATEWAY_URL + SURF_DEPLOYED_APP_TOKEN → deployed (hermod with Bearer)
3462
- * - Neither → public (api.ask.surf, caller provides own auth)
3456
+ * Reads:
3457
+ * - SURF_API_BASE_URL (default: https://api.asksurf.ai/gateway/v1)
3458
+ * - SURF_API_KEY (required)
3463
3459
  *
3464
- * Backward-compatible aliases:
3465
- * DATA_PROXY_BASE SURF_SANDBOX_PROXY_BASE
3466
- * GATEWAY_URL → SURF_DEPLOYED_GATEWAY_URL
3467
- * APP_TOKEN → SURF_DEPLOYED_APP_TOKEN
3460
+ * All requests are sent directly to the configured API base URL using
3461
+ * Authorization: Bearer <SURF_API_KEY>.
3468
3462
  */
3469
3463
  /** Low-level GET — escape hatch for endpoints not yet in the SDK. */
3470
3464
  declare function get<T = any>(path: string, params?: Record<string, any>): Promise<T>;
@@ -1,10 +1,9 @@
1
1
  import express from 'express';
2
2
 
3
3
  /**
4
- * Express server runtime — replaces scaffold server.js + routes/proxy.js.
4
+ * Express server runtime — replaces scaffold server.js.
5
5
  *
6
6
  * Handles:
7
- * - /proxy/* passthrough (env-aware: sandbox → OutboundProxy, deployed → hermod)
8
7
  * - Auto-loading routes from routes/*.js → /api/{name}
9
8
  * - Cron job system from cron.json
10
9
  * - DB schema sync on startup
@@ -12,18 +11,16 @@ import express from 'express';
12
11
  */
13
12
 
14
13
  interface ServerOptions {
15
- /** Port to listen on (default: PORT env, fallback 3001) */
14
+ /** Port to listen on. Falls back to the PORT env var when omitted. */
16
15
  port?: number;
17
16
  /** Directory containing route files (default: ./routes) */
18
17
  routesDir?: string;
19
18
  /** Directory containing cron.json (default: .) */
20
19
  cronDir?: string;
21
- /** Enable /proxy/* passthrough (default: true) */
22
- proxy?: boolean;
23
20
  }
24
21
  declare function createServer(options?: ServerOptions): {
25
22
  app: express.Express;
26
- port: number;
23
+ port: number | undefined;
27
24
  start(): Promise<void>;
28
25
  };
29
26
 
@@ -3454,17 +3451,14 @@ interface V2PolymarketVolumeChartParams {
3454
3451
  }
3455
3452
 
3456
3453
  /**
3457
- * Environment-aware data API client.
3454
+ * 1.0 data API client.
3458
3455
  *
3459
- * Reads env vars to determine routing (prefixed vars take priority):
3460
- * - SURF_SANDBOX_PROXY_BASE → sandbox (OutboundProxy handles auth)
3461
- * - SURF_DEPLOYED_GATEWAY_URL + SURF_DEPLOYED_APP_TOKEN → deployed (hermod with Bearer)
3462
- * - Neither → public (api.ask.surf, caller provides own auth)
3456
+ * Reads:
3457
+ * - SURF_API_BASE_URL (default: https://api.asksurf.ai/gateway/v1)
3458
+ * - SURF_API_KEY (required)
3463
3459
  *
3464
- * Backward-compatible aliases:
3465
- * DATA_PROXY_BASE SURF_SANDBOX_PROXY_BASE
3466
- * GATEWAY_URL → SURF_DEPLOYED_GATEWAY_URL
3467
- * APP_TOKEN → SURF_DEPLOYED_APP_TOKEN
3460
+ * All requests are sent directly to the configured API base URL using
3461
+ * Authorization: Bearer <SURF_API_KEY>.
3468
3462
  */
3469
3463
  /** Low-level GET — escape hatch for endpoints not yet in the SDK. */
3470
3464
  declare function get<T = any>(path: string, params?: Record<string, any>): Promise<T>;