@rebasepro/server 0.9.1-canary.ad25bc0 → 0.9.1-canary.ad870eb

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.
@@ -5,15 +5,12 @@ import { HonoEnv } from "../types";
5
5
  * Lightweight REST API generator that leverages existing Rebase DataDriver.
6
6
  * Supports `include` query parameter for eager-loading relations via Drizzle.
7
7
  */
8
- /** Rows accepted by a single POST /<collection>/bulk. See `maxBulkRows`. */
9
- export declare const DEFAULT_MAX_BULK_ROWS = 1000;
10
8
  export declare class RestApiGenerator {
11
9
  private collections;
12
10
  private router;
13
11
  private driver;
14
- private maxBulkRows;
15
12
  private authAdapter?;
16
- constructor(collections: CollectionConfig[], driver: DataDriver, authAdapter?: AuthAdapter, maxBulkRows?: number);
13
+ constructor(collections: CollectionConfig[], driver: DataDriver, authAdapter?: AuthAdapter);
17
14
  /**
18
15
  * Generate REST routes using existing DataDriver
19
16
  */
package/dist/env.d.ts CHANGED
@@ -42,7 +42,6 @@ declare const rebaseEnvSchema: z.ZodObject<{
42
42
  STORAGE_TYPE: z.ZodDefault<z.ZodEnum<{
43
43
  local: "local";
44
44
  s3: "s3";
45
- gcs: "gcs";
46
45
  }>>;
47
46
  STORAGE_PATH: z.ZodOptional<z.ZodString>;
48
47
  S3_BUCKET: z.ZodOptional<z.ZodString>;
package/dist/index.es.js CHANGED
@@ -2,7 +2,7 @@ import { createRequire as __createRequire } from "module";
2
2
  import process from "process";
3
3
  __createRequire(import.meta.url);
4
4
  import { a as __require, i as __exportAll, n as __commonJSMin, s as __toESM } from "./ms-DnYXB-Wd.js";
5
- import { _ as RebaseApiError, a as policy, c as isPostgresCollectionConfig, d as REST_TO_CANONICAL, f as toCanonicalOp, g as Vector, h as GeoPoint, i as isSQLAdmin, l as CANONICAL_TO_REST, m as EntityRelation, o as getCollectionDataPath, p as EntityReference, r as getDataSourceCapabilities, s as getDeclaredSubcollections, t as DEFAULT_STORAGE_SOURCE_KEY, u as NULL_OPS, v as RebaseClientError } from "./src-CsHhSKbi.js";
5
+ import { _ as RebaseClientError, a as getCollectionDataPath, c as CANONICAL_TO_REST, d as toCanonicalOp, f as EntityReference, g as RebaseApiError, h as Vector, i as isSQLAdmin, l as NULL_OPS, m as GeoPoint, o as getDeclaredSubcollections, p as EntityRelation, r as getDataSourceCapabilities, s as isPostgresCollectionConfig, t as DEFAULT_STORAGE_SOURCE_KEY, u as REST_TO_CANONICAL } from "./src-B4OLmNVa.js";
6
6
  import { t as logger } from "./logger-BYU66ENZ.js";
7
7
  import { a as getAccessTokenExpiry, d as require_jsonwebtoken, i as generateRefreshToken, l as verifyAccessToken, n as generateAccessToken, o as getRefreshTokenExpiry, r as generateDownloadToken, s as hashRefreshToken, t as configureJwt, u as verifyDownloadToken } from "./jwt-BwIn8xmk.js";
8
8
  import { t as nativeDynamicImport } from "./dynamic-import-Dvh-K5fl.js";
@@ -18,7 +18,6 @@ import * as crypto from "crypto";
18
18
  import { createCipheriv, createDecipheriv, createHash as createHash$1, createHmac, randomBytes as randomBytes$1, randomUUID as randomUUID$1, scrypt, timingSafeEqual } from "crypto";
19
19
  import { bodyLimit } from "hono/body-limit";
20
20
  import { csrf } from "hono/csrf";
21
- import { compress } from "hono/compress";
22
21
  import fs$1 from "node:fs";
23
22
  import fsp from "node:fs/promises";
24
23
  import { mkdir, open, unlink, writeFile } from "fs/promises";
@@ -1109,65 +1108,6 @@ function normalizeToEntityRelation(value, propertyType) {
1109
1108
  if (!(obj.__type === "relation" || obj.__type === "reference" || typeof obj.isEntityRelation === "function" && obj.isEntityRelation() || typeof obj.isEntityReference === "function" && obj.isEntityReference() || propertyType === "relation" && typeof obj.id !== "undefined" && typeof obj.path === "string")) return null;
1110
1109
  return new EntityRelation(obj.id, obj.path, obj.data);
1111
1110
  }
1112
- /**
1113
- * Derive a row's address from its key columns.
1114
- *
1115
- * Single key → the value as a string. Composite → each part joined by
1116
- * {@link COMPOSITE_ID_SEPARATOR}, in primary-key order, which is what
1117
- * {@link parseIdValues} expects to invert.
1118
- */
1119
- function buildCompositeId(values, primaryKeys) {
1120
- if (primaryKeys.length === 0) return "";
1121
- if (primaryKeys.length === 1) return String(values[primaryKeys[0].fieldName] ?? "");
1122
- return primaryKeys.map((pk) => String(values[pk.fieldName] ?? "")).join(":::");
1123
- }
1124
- /**
1125
- * The primary keys of a collection, as declared by its properties.
1126
- *
1127
- * The driver can also infer keys from the Drizzle schema, which the browser
1128
- * cannot see — so the server normalizes what it resolved onto the config it
1129
- * serves (see `stampPrimaryKeys`), and this reads that back. Returns an empty
1130
- * array when a collection declares none, which callers must treat as "not
1131
- * addressable" rather than defaulting to `id`: guessing a key that is not the
1132
- * real one produces confidently wrong addresses.
1133
- */
1134
- function getDeclaredPrimaryKeys(collection) {
1135
- const properties = collection.properties;
1136
- if (!properties) return [];
1137
- const keys = [];
1138
- for (const [fieldName, propRaw] of Object.entries(properties)) {
1139
- const prop = propRaw;
1140
- if (!prop || typeof prop !== "object") continue;
1141
- if (!("isId" in prop) || !prop.isId) continue;
1142
- keys.push({
1143
- fieldName,
1144
- type: prop.type === "number" ? "number" : "string",
1145
- isUUID: prop.isId === "uuid"
1146
- });
1147
- }
1148
- return keys;
1149
- }
1150
- /**
1151
- * The keys to address a collection's rows with, resolved the way the driver
1152
- * resolves them — minus the tier the browser cannot reach.
1153
- *
1154
- * The postgres driver tries, in order: properties marked `isId`; the primary
1155
- * keys of the Drizzle schema; and finally a column literally named `id`. Only
1156
- * the first and last are visible in a `CollectionConfig`, which is what both
1157
- * sides share — so a collection whose key is *only* known to Drizzle, and is
1158
- * not named `id`, resolves to nothing here. That is reported rather than
1159
- * guessed: inventing a key produces addresses that look right and route wrong.
1160
- */
1161
- function resolvePrimaryKeys(collection) {
1162
- const declared = getDeclaredPrimaryKeys(collection);
1163
- if (declared.length > 0) return declared;
1164
- const idProp = collection.properties?.id;
1165
- if (idProp && typeof idProp === "object") return [{
1166
- fieldName: "id",
1167
- type: idProp.type === "number" ? "number" : "string"
1168
- }];
1169
- return [];
1170
- }
1171
1111
  //#endregion
1172
1112
  //#region ../common/src/util/enums.ts
1173
1113
  function enumToObjectEntries(enumValues) {
@@ -1380,7 +1320,6 @@ function getSubcollections(collection) {
1380
1320
  }
1381
1321
  return [];
1382
1322
  }
1383
- policy.or(policy.serverContext(), policy.rolesOverlap(["admin"]));
1384
1323
  (/* @__PURE__ */ __commonJSMin(((exports, module) => {
1385
1324
  (function(root, factory) {
1386
1325
  if (typeof define === "function" && define.amd) define(factory);
@@ -2813,45 +2752,18 @@ function deserializeLogicalCondition(str) {
2813
2752
  }
2814
2753
  //#endregion
2815
2754
  //#region ../common/src/data/buildRebaseData.ts
2816
- function createPrimaryKeyResolver(options) {
2817
- const cache = /* @__PURE__ */ new Map();
2818
- const warned = /* @__PURE__ */ new Set();
2819
- return function primaryKeysFor(slug) {
2820
- const cached = cache.get(slug);
2821
- if (cached) return cached;
2822
- const collection = options?.resolveCollection?.(slug);
2823
- if (!collection) return [];
2824
- const keys = resolvePrimaryKeys(collection);
2825
- if (keys.length > 0) {
2826
- cache.set(slug, keys);
2827
- return keys;
2828
- }
2829
- if (!warned.has(slug)) {
2830
- warned.add(slug);
2831
- console.warn(`[rebase] Collection '${slug}' declares no primary key, so its rows have no address: detail links, caching and relations will not work for it. Mark the key property with \`isId\` in its collection config.`);
2832
- }
2833
- return keys;
2834
- };
2835
- }
2836
2755
  /**
2837
- * Give a flat row the Entity view-model the admin renders.
2838
- *
2839
- * The address is *derived here* — it is not a column, and the row it came from
2840
- * does not contain one. Rows carry exactly what the table has, with the types
2841
- * Postgres returned; the id is this layer's invention, and this is the only
2842
- * place it is minted.
2843
- *
2844
- * `primaryKeys` empty falls back to a literal `id` on the row: drivers other
2845
- * than postgres still serve rows with one, and this keeps them working.
2756
+ * Convert a flat REST record (e.g. from RestFetchService) to Entity<M> format.
2757
+ * Mirrors the client SDK's rowToEntity conversion.
2846
2758
  */
2847
- function rowToEntity(row, slug, primaryKeys = []) {
2759
+ function rowToEntity(row, slug) {
2848
2760
  return {
2849
- id: primaryKeys.length > 0 ? buildCompositeId(row, primaryKeys) : row.id,
2761
+ id: row.id,
2850
2762
  path: slug,
2851
2763
  values: row
2852
2764
  };
2853
2765
  }
2854
- function createDriverAccessor(driver, slug, getPks = () => []) {
2766
+ function createDriverAccessor(driver, slug) {
2855
2767
  const accessor = {
2856
2768
  async find(params) {
2857
2769
  const filter = params?.where ? deserializeFilter(params.where) : void 0;
@@ -2884,7 +2796,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
2884
2796
  hasMore = offset + rows.length < total;
2885
2797
  }
2886
2798
  return {
2887
- data: rows.map((row) => rowToEntity(row, slug, getPks())),
2799
+ data: rows.map((row) => rowToEntity(row, slug)),
2888
2800
  meta: {
2889
2801
  total,
2890
2802
  limit,
@@ -2898,7 +2810,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
2898
2810
  path: slug,
2899
2811
  id
2900
2812
  });
2901
- return row ? rowToEntity(row, slug, getPks()) : void 0;
2813
+ return row ? rowToEntity(row, slug) : void 0;
2902
2814
  },
2903
2815
  async create(data, id) {
2904
2816
  return rowToEntity(await driver.save({
@@ -2906,22 +2818,15 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
2906
2818
  values: data,
2907
2819
  id,
2908
2820
  status: "new"
2909
- }), slug, getPks());
2821
+ }), slug);
2910
2822
  },
2911
- createMany: driver.saveMany ? async (data, options) => {
2912
- return (await driver.saveMany({
2913
- path: slug,
2914
- rows: data,
2915
- upsert: options?.upsert
2916
- })).map((row) => rowToEntity(row, slug, getPks()));
2917
- } : void 0,
2918
2823
  async update(id, data) {
2919
2824
  return rowToEntity(await driver.save({
2920
2825
  path: slug,
2921
2826
  values: data,
2922
2827
  id,
2923
2828
  status: "existing"
2924
- }), slug, getPks());
2829
+ }), slug);
2925
2830
  },
2926
2831
  async delete(id) {
2927
2832
  return driver.delete({ row: {
@@ -2950,7 +2855,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
2950
2855
  searchString: params?.searchString,
2951
2856
  onUpdate: (entities) => {
2952
2857
  onUpdate({
2953
- data: entities.map((row) => rowToEntity(row, slug, getPks())),
2858
+ data: entities.map((row) => rowToEntity(row, slug)),
2954
2859
  meta: {
2955
2860
  total: entities.length,
2956
2861
  limit,
@@ -2966,7 +2871,7 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
2966
2871
  return driver.listenOne({
2967
2872
  path: slug,
2968
2873
  id,
2969
- onUpdate: (entity) => onUpdate(entity ? rowToEntity(entity, slug, getPks()) : void 0),
2874
+ onUpdate: (entity) => onUpdate(entity ? rowToEntity(entity, slug) : void 0),
2970
2875
  onError
2971
2876
  });
2972
2877
  } : void 0,
@@ -3005,13 +2910,12 @@ function createDriverAccessor(driver, slug, getPks = () => []) {
3005
2910
  * await data.products.create({ name: "Camera", price: 299 });
3006
2911
  * const { data: items } = await data.products.find({ where: { status: ["==", "published"] } });
3007
2912
  */
3008
- function buildRebaseData(driver, options) {
2913
+ function buildRebaseData(driver) {
3009
2914
  const cache = /* @__PURE__ */ new Map();
3010
- const primaryKeysFor = createPrimaryKeyResolver(options);
3011
2915
  function getAccessor(slug) {
3012
2916
  let accessor = cache.get(slug);
3013
2917
  if (!accessor) {
3014
- accessor = createDriverAccessor(driver, slug, () => primaryKeysFor(slug));
2918
+ accessor = createDriverAccessor(driver, slug);
3015
2919
  cache.set(slug, accessor);
3016
2920
  }
3017
2921
  return accessor;
@@ -3024,9 +2928,8 @@ function buildRebaseData(driver, options) {
3024
2928
  } });
3025
2929
  }
3026
2930
  /**
3027
- * Unwrap a Entity back into the flat row it was built from. `rowToEntity` keeps
3028
- * the row untouched under `.values` and derives `.id` alongside it, so dropping
3029
- * the wrapper is the whole operation — the address was never part of the row.
2931
+ * Unwrap a Entity into a flat row. `rowToEntity` stores the whole flat row
2932
+ * (id included) under `.values`, so this is just that payload.
3030
2933
  */
3031
2934
  function entityToRow(entity) {
3032
2935
  return entity.values;
@@ -3113,12 +3016,6 @@ function toSdkCollectionClient(snap) {
3113
3016
  async create(data, id) {
3114
3017
  return entityToRow(await snap.create(data, id));
3115
3018
  },
3116
- async createMany(data, options) {
3117
- if (!Array.isArray(data)) throw new TypeError("createMany expects an array of records.");
3118
- if (data.length === 0) return [];
3119
- if (!snap.createMany) throw new Error("Bulk writes are not supported by this collection's data source. Fall back to create() per record.");
3120
- return (await snap.createMany(data, options)).map(entityToRow);
3121
- },
3122
3019
  async update(id, data) {
3123
3020
  return entityToRow(await snap.update(id, data));
3124
3021
  },
@@ -3827,19 +3724,15 @@ async function parseJsonBody(c) {
3827
3724
  * Lightweight REST API generator that leverages existing Rebase DataDriver.
3828
3725
  * Supports `include` query parameter for eager-loading relations via Drizzle.
3829
3726
  */
3830
- /** Rows accepted by a single POST /<collection>/bulk. See `maxBulkRows`. */
3831
- var DEFAULT_MAX_BULK_ROWS = 1e3;
3832
3727
  var RestApiGenerator = class {
3833
3728
  collections;
3834
3729
  router;
3835
3730
  driver;
3836
- maxBulkRows;
3837
3731
  authAdapter;
3838
- constructor(collections, driver, authAdapter, maxBulkRows = DEFAULT_MAX_BULK_ROWS) {
3732
+ constructor(collections, driver, authAdapter) {
3839
3733
  this.collections = collections;
3840
3734
  this.driver = driver;
3841
3735
  this.authAdapter = authAdapter;
3842
- this.maxBulkRows = maxBulkRows;
3843
3736
  this.router = new Hono();
3844
3737
  }
3845
3738
  /**
@@ -3924,32 +3817,6 @@ var RestApiGenerator = class {
3924
3817
  if (!entity) throw ApiError.notFound("Entity not found");
3925
3818
  return c.json(entity);
3926
3819
  });
3927
- this.router.post(`${basePath}/bulk`, async (c) => {
3928
- this.enforceApiKeyPermission(c, collection.slug);
3929
- const driver = this.getScopedDriver(c);
3930
- const path = collection.slug;
3931
- const body = await parseJsonBody(c);
3932
- if (!Array.isArray(body?.rows)) throw ApiError.badRequest("Expected a JSON body of { rows: [...] }.", "INVALID_BULK_BODY");
3933
- if (body.rows.length === 0) return c.json({
3934
- data: [],
3935
- meta: { written: 0 }
3936
- });
3937
- if (body.rows.some((row) => typeof row !== "object" || row === null || Array.isArray(row))) throw ApiError.badRequest("Every entry in `rows` must be an object.", "INVALID_BULK_BODY");
3938
- if (body.upsert !== void 0 && typeof body.upsert !== "boolean") throw ApiError.badRequest("`upsert` must be a boolean.", "INVALID_BULK_BODY");
3939
- const maxRows = this.maxBulkRows;
3940
- if (body.rows.length > maxRows) throw ApiError.badRequest(`Too many rows: ${body.rows.length} exceeds the ${maxRows}-row limit for a single bulk write. Send it in chunks of ${maxRows} or fewer.`, "BULK_TOO_LARGE");
3941
- if (!driver.saveMany) throw ApiError.badRequest("This collection's data source does not support bulk writes.", "BULK_UNSUPPORTED");
3942
- const rows = await driver.saveMany({
3943
- path,
3944
- rows: body.rows,
3945
- collection: resolvedCollection,
3946
- upsert: body.upsert === true
3947
- });
3948
- return c.json({
3949
- data: rows.map((row) => this.formatResponse(row)),
3950
- meta: { written: rows.length }
3951
- });
3952
- });
3953
3820
  this.router.post(basePath, async (c) => {
3954
3821
  try {
3955
3822
  this.enforceApiKeyPermission(c, collection.slug);
@@ -10996,33 +10863,6 @@ function configureLogLevel(logLevel) {
10996
10863
  if (currentLevel < 0) console.error = () => {};
10997
10864
  }
10998
10865
  //#endregion
10999
- //#region src/utils/compression.ts
11000
- /**
11001
- * Response compression (gzip/deflate), negotiated from `Accept-Encoding`.
11002
- *
11003
- * Wraps Hono's `compress` with two corrections it does not make itself:
11004
- *
11005
- * - **`Vary: Accept-Encoding`** on every response it guards. Without it a shared
11006
- * cache may hand a gzipped body to a client that asked for identity.
11007
- * - **Range responses are left alone.** `Content-Range` describes offsets into
11008
- * the identity body, so compressing a 206 desyncs the framing from the bytes
11009
- * actually sent.
11010
- *
11011
- * No brotli: `CompressionStream` has no "br", so a br-only client would fall
11012
- * back to identity — every real client sends gzip too.
11013
- */
11014
- function responseCompression() {
11015
- const gzip = compress();
11016
- return async (c, next) => {
11017
- await next();
11018
- const vary = c.res.headers.get("Vary");
11019
- if (!vary) c.res.headers.set("Vary", "Accept-Encoding");
11020
- else if (!/\baccept-encoding\b/i.test(vary)) c.res.headers.append("Vary", "Accept-Encoding");
11021
- if (c.res.status === 206 || c.res.headers.has("Content-Range")) return;
11022
- await gzip(c, async () => {});
11023
- };
11024
- }
11025
- //#endregion
11026
10866
  //#region src/utils/request-id.ts
11027
10867
  /**
11028
10868
  * X-Request-ID Middleware for Hono.
@@ -11085,105 +10925,9 @@ function requestLogger(options) {
11085
10925
  };
11086
10926
  }
11087
10927
  //#endregion
11088
- //#region src/api/logs-routes.ts
11089
- var logs_routes_exports = /* @__PURE__ */ __exportAll({
11090
- addLog: () => addLog,
11091
- default: () => app,
11092
- logBuffer: () => logBuffer,
11093
- logMiddleware: () => logMiddleware
11094
- });
11095
- var LogRingBuffer = class {
11096
- buffer = [];
11097
- maxSize;
11098
- idCounter = 0;
11099
- constructor(maxSize = 1e4) {
11100
- this.maxSize = maxSize;
11101
- }
11102
- push(entry) {
11103
- const id = `log_${++this.idCounter}`;
11104
- this.buffer.push({
11105
- ...entry,
11106
- id
11107
- });
11108
- if (this.buffer.length > this.maxSize) this.buffer.shift();
11109
- }
11110
- query(options) {
11111
- let filtered = this.buffer;
11112
- if (options.level) filtered = filtered.filter((e) => e.level === options.level);
11113
- if (options.source) filtered = filtered.filter((e) => e.source === options.source);
11114
- if (options.search) {
11115
- const searchLower = options.search.toLowerCase();
11116
- filtered = filtered.filter((e) => e.message.toLowerCase().includes(searchLower));
11117
- }
11118
- if (options.since) {
11119
- const sinceValue = options.since;
11120
- filtered = filtered.filter((e) => e.timestamp >= sinceValue);
11121
- }
11122
- const sorted = [...filtered].reverse();
11123
- const total = sorted.length;
11124
- const limit = options.limit || 100;
11125
- const offset = options.offset || 0;
11126
- return {
11127
- entries: sorted.slice(offset, offset + limit),
11128
- total
11129
- };
11130
- }
11131
- getLatest(count = 50) {
11132
- return this.buffer.slice(-count).reverse();
11133
- }
11134
- };
11135
- var logBuffer = new LogRingBuffer();
11136
- /** Add a log entry */
11137
- function addLog(level, source, message, metadata) {
11138
- logBuffer.push({
11139
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
11140
- level,
11141
- source,
11142
- message,
11143
- metadata
11144
- });
11145
- }
11146
- /** Hono middleware to log API requests */
11147
- function logMiddleware() {
11148
- return async (c, next) => {
11149
- const start = Date.now();
11150
- await next();
11151
- const duration = Date.now() - start;
11152
- const reqId = c.get("requestId");
11153
- addLog("info", "api", `${c.req.method} ${c.req.path} ${c.res.status} ${duration}ms`, {
11154
- method: c.req.method,
11155
- path: c.req.path,
11156
- status: c.res.status,
11157
- duration,
11158
- ...reqId && { requestId: reqId }
11159
- });
11160
- };
11161
- }
11162
- var app = new Hono();
11163
- app.get("/", (c) => {
11164
- const query = c.req.query();
11165
- const result = logBuffer.query({
11166
- level: query.level,
11167
- source: query.source,
11168
- search: query.search,
11169
- limit: query.limit ? parseInt(query.limit) : void 0,
11170
- offset: query.offset ? parseInt(query.offset) : void 0,
11171
- since: query.since
11172
- });
11173
- return c.json(result);
11174
- });
11175
- app.get("/latest", (c) => {
11176
- const count = parseInt(c.req.query("count") || "50");
11177
- return c.json({ entries: logBuffer.getLatest(count) });
11178
- });
11179
- //#endregion
11180
10928
  //#region src/init/middlewares.ts
11181
10929
  function configureMiddlewares(app, basePath, isProduction, config) {
11182
10930
  app.use(`${basePath}/*`, requestId());
11183
- if (config.compression !== false) {
11184
- app.use(`${basePath}/*`, responseCompression());
11185
- logger.info("Response compression enabled");
11186
- }
11187
10931
  const maxBodySize = config.maxBodySize ?? 10 * 1024 * 1024;
11188
10932
  if (maxBodySize > 0) {
11189
10933
  app.use(`${basePath}/*`, bodyLimit({
@@ -11203,7 +10947,6 @@ function configureMiddlewares(app, basePath, isProduction, config) {
11203
10947
  }
11204
10948
  if (!isProduction && !process.env.CORS_ORIGINS && !process.env.FRONTEND_URL) logger.warn("No CORS configuration detected (CORS_ORIGINS / FRONTEND_URL not set). The API will accept requests from any origin. Set CORS_ORIGINS in your .env file to restrict access.");
11205
10949
  app.use(`${basePath}/*`, requestLogger());
11206
- app.use(`${basePath}/*`, logMiddleware());
11207
10950
  }
11208
10951
  //#endregion
11209
10952
  //#region src/storage/types.ts
@@ -15190,7 +14933,7 @@ var SDKQueryBuilder = class {
15190
14933
  * Listen to realtime updates matching this query.
15191
14934
  */
15192
14935
  listen(onUpdate, onError) {
15193
- if (!this.collection.listen) throw new Error("Listen is only available when RebaseClient is configured with a websocketUrl, and not when it was created with realtime: false.");
14936
+ if (!this.collection.listen) throw new Error("Listen is only available when RebaseClient is configured with a websocketUrl.");
15194
14937
  return this.collection.listen(this.params, onUpdate, onError);
15195
14938
  }
15196
14939
  };
@@ -15223,17 +14966,6 @@ function createCollectionClient(transport, slug, ws) {
15223
14966
  body: JSON.stringify(body)
15224
14967
  });
15225
14968
  },
15226
- async createMany(data, options) {
15227
- if (!Array.isArray(data)) throw new TypeError("createMany expects an array of records.");
15228
- if (data.length === 0) return [];
15229
- return (await transport.request(`${basePath}/bulk`, {
15230
- method: "POST",
15231
- body: JSON.stringify({
15232
- rows: data,
15233
- ...options?.upsert ? { upsert: true } : {}
15234
- })
15235
- })).data || [];
15236
- },
15237
14969
  async update(id, data) {
15238
14970
  return await transport.request(`${basePath}/${encodeURIComponent(String(id))}`, {
15239
14971
  method: "PUT",
@@ -16485,7 +16217,7 @@ function createRebaseClient(options) {
16485
16217
  });
16486
16218
  return storageSourcesPromise;
16487
16219
  };
16488
- const resolvedWsUrl = options.realtime !== false ? options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl) : void 0;
16220
+ const resolvedWsUrl = options.websocketUrl ?? deriveWebSocketUrl(options.baseUrl);
16489
16221
  let ws;
16490
16222
  if (resolvedWsUrl) {
16491
16223
  ws = new RebaseWebSocketClient({
@@ -16597,16 +16329,6 @@ function createRebaseClient(options) {
16597
16329
  createStorageSource,
16598
16330
  fetchStorageSources,
16599
16331
  ws,
16600
- /**
16601
- * Release the realtime socket and its reconnect timer.
16602
- *
16603
- * Until this returns, the open socket keeps the Node event loop alive
16604
- * and the process will not exit on its own. Safe to call when realtime
16605
- * was never started, and safe to call twice.
16606
- */
16607
- close: () => {
16608
- ws?.disconnect();
16609
- },
16610
16332
  setToken: transport.setToken,
16611
16333
  setAuthTokenGetter: transport.setAuthTokenGetter,
16612
16334
  setOnUnauthorized: transport.setOnUnauthorized,
@@ -17415,17 +17137,6 @@ async function _initializeRebaseBackend(config) {
17415
17137
  config.app.route(`${basePath}/admin/backups`, backupRouter);
17416
17138
  logger.info("Backup admin routes mounted", { path: `${basePath}/admin/backups` });
17417
17139
  }
17418
- {
17419
- const { default: logsRoutes } = await Promise.resolve().then(() => logs_routes_exports);
17420
- const logsRouter = new Hono();
17421
- if (authAdapter && !isAuthAdapter(config.auth)) {
17422
- const safeAuth = config.auth;
17423
- if (safeAuth.requireAuth !== false && !!safeAuth.jwtSecret) logsRouter.use("/*", requireAuth, requireAdmin);
17424
- } else if (authAdapter) logsRouter.use("/*", requireAuth, requireAdmin);
17425
- logsRouter.route("/", logsRoutes);
17426
- config.app.route(`${basePath}/logs`, logsRouter);
17427
- logger.info("Logs routes mounted", { path: `${basePath}/logs` });
17428
- }
17429
17140
  const effectiveRealtimeService = Object.keys(realtimeServices).length > 1 ? createRoutedRealtimeService({
17430
17141
  providers: realtimeServices,
17431
17142
  defaultKey: defaultDriverId,
@@ -18536,11 +18247,7 @@ var rebaseEnvSchema = object({
18536
18247
  DATABASE_DIRECT_URL: string().url().optional(),
18537
18248
  DATABASE_READ_URL: string().url().optional(),
18538
18249
  FORCE_LOCAL_STORAGE: optionalBoolString,
18539
- STORAGE_TYPE: _enum([
18540
- "local",
18541
- "s3",
18542
- "gcs"
18543
- ]).default("local"),
18250
+ STORAGE_TYPE: _enum(["local", "s3"]).default("local"),
18544
18251
  STORAGE_PATH: string().optional(),
18545
18252
  S3_BUCKET: string().optional(),
18546
18253
  S3_REGION: string().optional(),
@@ -18729,11 +18436,7 @@ function serveSPA(app, config) {
18729
18436
  logger.warn(" SPA serving is disabled. Build your frontend first.");
18730
18437
  return;
18731
18438
  }
18732
- app.use("/*", responseCompression());
18733
- app.use("/*", serveStatic({
18734
- root: path$1.relative(process.cwd(), frontendPath),
18735
- precompressed: true
18736
- }));
18439
+ app.use("/*", serveStatic({ root: path$1.relative(process.cwd(), frontendPath) }));
18737
18440
  const allExcludePaths = [apiBasePath, ...excludePaths];
18738
18441
  let cachedHtml = null;
18739
18442
  app.get("*", async (c, next) => {