@budibase/backend-core 3.2.3 → 3.2.4

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/index.js CHANGED
@@ -61902,7 +61902,7 @@ __export(src_exports, {
61902
61902
  sql: () => sql_exports,
61903
61903
  tenancy: () => tenancy,
61904
61904
  timers: () => timers_exports,
61905
- userUtils: () => utils_exports6,
61905
+ userUtils: () => utils_exports5,
61906
61906
  users: () => users_exports3,
61907
61907
  utils: () => utils_exports4,
61908
61908
  withEnv: () => withEnv
@@ -63417,7 +63417,12 @@ function fixupFilterArrays(filters) {
63417
63417
  function search(docs, query) {
63418
63418
  let result = runQuery(docs, query.query);
63419
63419
  if (query.sort) {
63420
- result = sort(result, query.sort, query.sortOrder || "ascending" /* ASCENDING */);
63420
+ result = sort(
63421
+ result,
63422
+ query.sort,
63423
+ query.sortOrder || "ascending" /* ASCENDING */,
63424
+ query.sortType
63425
+ );
63421
63426
  }
63422
63427
  const totalRows = result.length;
63423
63428
  if (query.limit) {
@@ -64192,6 +64197,7 @@ function getAccountUserId(account) {
64192
64197
  // src/environment.ts
64193
64198
  var import_fs = require("fs");
64194
64199
  var import_lodash4 = require("lodash");
64200
+ var import_crypto = require("crypto");
64195
64201
  function isTest() {
64196
64202
  return isJest();
64197
64203
  }
@@ -64281,8 +64287,8 @@ var environment = {
64281
64287
  },
64282
64288
  BUDIBASE_ENVIRONMENT: process.env.BUDIBASE_ENVIRONMENT,
64283
64289
  JS_BCRYPT: process.env.JS_BCRYPT,
64284
- JWT_SECRET: process.env.JWT_SECRET,
64285
- JWT_SECRET_FALLBACK: process.env.JWT_SECRET_FALLBACK,
64290
+ JWT_SECRET: process.env.JWT_SECRET ? (0, import_crypto.createSecretKey)(Buffer.from(process.env.JWT_SECRET)) : void 0,
64291
+ JWT_SECRET_FALLBACK: process.env.JWT_SECRET_FALLBACK ? (0, import_crypto.createSecretKey)(Buffer.from(process.env.JWT_SECRET_FALLBACK)) : void 0,
64286
64292
  ENCRYPTION_KEY: process.env.ENCRYPTION_KEY,
64287
64293
  API_ENCRYPTION_KEY: getAPIEncryptionKey(),
64288
64294
  COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
@@ -64370,9 +64376,7 @@ var environment = {
64370
64376
  BB_ADMIN_USER_PASSWORD: process.env.BB_ADMIN_USER_PASSWORD,
64371
64377
  OPENAI_API_KEY: process.env.OPENAI_API_KEY,
64372
64378
  MIN_VERSION_WITHOUT_POWER_ROLE: process.env.MIN_VERSION_WITHOUT_POWER_ROLE || "3.0.0",
64373
- DISABLE_CONTENT_SECURITY_POLICY: process.env.DISABLE_CONTENT_SECURITY_POLICY,
64374
- // stopgap migration strategy until we can ensure backwards compat without unsafe-inline in CSP
64375
- DISABLE_CSP_UNSAFE_INLINE_SCRIPTS: process.env.DISABLE_CSP_UNSAFE_INLINE_SCRIPTS
64379
+ DISABLE_CONTENT_SECURITY_POLICY: process.env.DISABLE_CONTENT_SECURITY_POLICY
64376
64380
  };
64377
64381
  function setEnv(newEnvVars) {
64378
64382
  const oldEnv = (0, import_lodash4.cloneDeep)(environment);
@@ -67830,753 +67834,133 @@ function validateManyToMany(relationship) {
67830
67834
  return void 0;
67831
67835
  }
67832
67836
 
67833
- // src/features/index.ts
67834
- var features_exports = {};
67835
- __export(features_exports, {
67836
- Flag: () => Flag,
67837
- FlagSet: () => FlagSet,
67838
- flags: () => flags,
67839
- init: () => init4,
67840
- parseEnvFlags: () => parseEnvFlags,
67841
- shutdown: () => shutdown2,
67842
- testutils: () => utils_exports5
67843
- });
67844
-
67845
- // src/features/features.ts
67846
- var crypto = __toESM(require("crypto"));
67847
- var import_posthog_node = require("posthog-node");
67848
- var import_dd_trace3 = __toESM(require("dd-trace"));
67849
-
67850
- // src/utils/index.ts
67851
- var utils_exports4 = {};
67852
- __export(utils_exports4, {
67853
- Duration: () => Duration,
67854
- DurationType: () => DurationType,
67855
- clearCookie: () => clearCookie,
67856
- compare: () => compare,
67857
- getAppIdFromCtx: () => getAppIdFromCtx,
67858
- getCookie: () => getCookie,
67859
- hasCircularStructure: () => hasCircularStructure,
67860
- hash: () => hash,
67861
- isAudited: () => isAudited,
67862
- isClient: () => isClient,
67863
- isPublicApiRequest: () => isPublicApiRequest,
67864
- isServingApp: () => isServingApp,
67865
- isServingBuilder: () => isServingBuilder,
67866
- isServingBuilderPreview: () => isServingBuilderPreview,
67867
- isValidInternalAPIKey: () => isValidInternalAPIKey,
67868
- newid: () => newid,
67869
- openJwt: () => openJwt,
67870
- resolveAppUrl: () => resolveAppUrl,
67871
- setCookie: () => setCookie,
67872
- timeout: () => timeout,
67873
- validEmail: () => validEmail
67874
- });
67875
-
67876
- // src/utils/hashing.ts
67877
- var bcrypt = environment_default.JS_BCRYPT ? require("bcryptjs") : require("bcrypt");
67878
- var SALT_ROUNDS = environment_default.SALT_ROUNDS || 10;
67879
- async function hash(data) {
67880
- const salt = await bcrypt.genSalt(SALT_ROUNDS);
67881
- return bcrypt.hash(data, salt);
67882
- }
67883
- async function compare(data, encrypted) {
67884
- return bcrypt.compare(data, encrypted);
67885
- }
67886
-
67887
- // src/tenancy/index.ts
67888
- var tenancy_exports = {};
67889
- __export(tenancy_exports, {
67890
- addTenantToUrl: () => addTenantToUrl,
67891
- getTenantDB: () => getTenantDB,
67892
- getTenantIDFromCtx: () => getTenantIDFromCtx,
67893
- isUserInAppTenant: () => isUserInAppTenant
67894
- });
67895
-
67896
- // src/tenancy/db.ts
67897
- function getTenantDB(tenantId) {
67898
- return getDB(getGlobalDBName(tenantId));
67899
- }
67900
-
67901
- // src/tenancy/tenancy.ts
67902
- function addTenantToUrl(url) {
67903
- const tenantId = getTenantId();
67904
- if (isMultiTenant()) {
67905
- const char = url.indexOf("?") === -1 ? "?" : "&";
67906
- url += `${char}tenantId=${tenantId}`;
67907
- }
67908
- return url;
67837
+ // src/db/couch/DatabaseImpl.ts
67838
+ var DATABASE_NOT_FOUND = "Database does not exist.";
67839
+ function buildNano(couchInfo) {
67840
+ return (0, import_nano.default)({
67841
+ url: couchInfo.url,
67842
+ requestDefaults: {
67843
+ headers: {
67844
+ Authorization: couchInfo.cookie
67845
+ }
67846
+ },
67847
+ parseUrl: false
67848
+ });
67909
67849
  }
67910
- var isUserInAppTenant = (appId, user) => {
67911
- let userTenantId;
67912
- if (user) {
67913
- userTenantId = user.tenantId || DEFAULT_TENANT_ID;
67914
- } else {
67915
- userTenantId = getTenantId();
67850
+ var CouchDBError = class extends Error {
67851
+ constructor(message, info) {
67852
+ super(message);
67853
+ const statusCode = info.status || info.statusCode || 500;
67854
+ this.status = statusCode;
67855
+ this.statusCode = statusCode;
67856
+ this.reason = info.reason || "Unknown";
67857
+ this.name = info.name;
67858
+ this.errid = info.errid || "Unknown";
67859
+ this.description = info.description || "Unknown";
67860
+ this.error = info.error || "Not found";
67916
67861
  }
67917
- const tenantId = getTenantIDFromAppID(appId) || DEFAULT_TENANT_ID;
67918
- return tenantId === userTenantId;
67919
67862
  };
67920
- var ALL_STRATEGIES = Object.values(TenantResolutionStrategy);
67921
- var getTenantIDFromCtx = (ctx, opts) => {
67922
- if (!isMultiTenant()) {
67923
- return DEFAULT_TENANT_ID;
67924
- }
67925
- if (opts.allowNoTenant === void 0) {
67926
- opts.allowNoTenant = false;
67863
+ function DatabaseWithConnection(dbName, connection, opts) {
67864
+ if (!dbName || !connection) {
67865
+ throw new Error(
67866
+ "Unable to create database without database name or connection"
67867
+ );
67927
67868
  }
67928
- if (!opts.includeStrategies) {
67929
- opts.includeStrategies = ALL_STRATEGIES;
67869
+ const db = new DatabaseImpl(dbName, opts, connection);
67870
+ return new DDInstrumentedDatabase(db);
67871
+ }
67872
+ var DatabaseImpl = class _DatabaseImpl {
67873
+ constructor(dbName, opts, connection) {
67874
+ this.couchInfo = getCouchInfo();
67875
+ this.name = dbName;
67876
+ this.pouchOpts = opts || {};
67877
+ if (connection) {
67878
+ this.couchInfo = getCouchInfo(connection);
67879
+ this.instanceNano = buildNano(this.couchInfo);
67880
+ }
67881
+ if (!_DatabaseImpl.nano) {
67882
+ _DatabaseImpl.init();
67883
+ }
67930
67884
  }
67931
- if (!opts.excludeStrategies) {
67932
- opts.excludeStrategies = [];
67885
+ static init() {
67886
+ const couchInfo = getCouchInfo();
67887
+ _DatabaseImpl.nano = buildNano(couchInfo);
67933
67888
  }
67934
- const isAllowed = (strategy) => {
67935
- if (opts.excludeStrategies?.includes(strategy)) {
67936
- return false;
67889
+ exists(docId) {
67890
+ if (docId === void 0) {
67891
+ return this.dbExists();
67937
67892
  }
67938
- if (opts.includeStrategies?.includes(strategy)) {
67893
+ return this.docExists(docId);
67894
+ }
67895
+ async dbExists() {
67896
+ const response = await directCouchUrlCall({
67897
+ url: `${this.couchInfo.url}/${this.name}`,
67898
+ method: "HEAD",
67899
+ cookie: this.couchInfo.cookie
67900
+ });
67901
+ return response.status === 200;
67902
+ }
67903
+ async docExists(id) {
67904
+ try {
67905
+ await this.performCall((db) => () => db.head(id));
67939
67906
  return true;
67940
- }
67941
- };
67942
- if (isAllowed("user" /* USER */)) {
67943
- const userTenantId = ctx.user?.tenantId;
67944
- if (userTenantId) {
67945
- return userTenantId;
67907
+ } catch {
67908
+ return false;
67946
67909
  }
67947
67910
  }
67948
- if (isAllowed("header" /* HEADER */)) {
67949
- const headerTenantId = ctx.request.headers["x-budibase-tenant-id" /* TENANT_ID */];
67950
- if (headerTenantId) {
67951
- return headerTenantId;
67952
- }
67911
+ nano() {
67912
+ return this.instanceNano || _DatabaseImpl.nano;
67953
67913
  }
67954
- if (isAllowed("query" /* QUERY */)) {
67955
- const queryTenantId = ctx.request.query.tenantId;
67956
- if (queryTenantId) {
67957
- return queryTenantId;
67914
+ getDb() {
67915
+ return this.nano().db.use(this.name);
67916
+ }
67917
+ async checkAndCreateDb() {
67918
+ let shouldCreate = !this.pouchOpts?.skip_setup;
67919
+ let exists2 = await this.exists();
67920
+ if (!shouldCreate && !exists2) {
67921
+ throw new Error("DB does not exist");
67922
+ }
67923
+ if (!exists2) {
67924
+ try {
67925
+ await this.nano().db.create(this.name);
67926
+ } catch (err) {
67927
+ if (err.statusCode !== 412) {
67928
+ throw new CouchDBError(err.message, err);
67929
+ }
67930
+ }
67958
67931
  }
67932
+ return this.getDb();
67959
67933
  }
67960
- if (isAllowed("subdomain" /* SUBDOMAIN */)) {
67961
- let platformHost;
67934
+ // this function fetches the DB and handles if DB creation is needed
67935
+ async performCallWithDBCreation(call) {
67936
+ const db = this.getDb();
67937
+ const fnc = await call(db);
67962
67938
  try {
67963
- platformHost = new URL(getPlatformURL()).host.split(":")[0];
67939
+ return await fnc();
67964
67940
  } catch (err) {
67965
- if (err.code !== "ERR_INVALID_URL") {
67966
- throw err;
67967
- }
67968
- }
67969
- const requestHost = ctx.host;
67970
- if (platformHost && requestHost.includes(platformHost)) {
67971
- const tenantId = requestHost.substring(
67972
- 0,
67973
- requestHost.indexOf(`.${platformHost}`)
67974
- );
67975
- if (tenantId) {
67976
- return tenantId;
67941
+ if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {
67942
+ await this.checkAndCreateDb();
67943
+ return await this.performCallWithDBCreation(call);
67977
67944
  }
67945
+ throw new CouchDBError(`CouchDB error: ${err.message}`, err);
67978
67946
  }
67979
67947
  }
67980
- if (isAllowed("path" /* PATH */)) {
67981
- const match = ctx.matched.find(
67982
- (m) => !!m.paramNames.find((p) => p.name === "tenantId")
67983
- );
67984
- const ctxUrl = ctx.originalUrl;
67985
- let url;
67986
- if (ctxUrl.includes("?")) {
67987
- url = ctxUrl.split("?")[0];
67988
- } else {
67989
- url = ctxUrl;
67990
- }
67991
- if (match) {
67992
- const params2 = match.params(url, match.captures(url), {});
67993
- if (params2.tenantId) {
67994
- return params2.tenantId;
67995
- }
67948
+ async performCall(call) {
67949
+ const db = this.getDb();
67950
+ const fnc = await call(db);
67951
+ try {
67952
+ return await fnc();
67953
+ } catch (err) {
67954
+ throw new CouchDBError(`CouchDB error: ${err.message}`, err);
67996
67955
  }
67997
67956
  }
67998
- if (!opts.allowNoTenant) {
67999
- ctx.throw(403, "Tenant id not set");
68000
- }
68001
- return void 0;
68002
- };
68003
-
68004
- // src/utils/utils.ts
68005
- var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
68006
- var APP_PREFIX3 = "app" /* APP */ + SEPARATOR;
68007
- var PROD_APP_PREFIX = "/app/";
68008
- var BUILDER_PREVIEW_PATH = "/app/preview";
68009
- var BUILDER_PREFIX = "/builder";
68010
- var BUILDER_APP_PREFIX = `${BUILDER_PREFIX}/app/`;
68011
- var PUBLIC_API_PREFIX = "/api/public/v";
68012
- function confirmAppId(possibleAppId) {
68013
- return possibleAppId && possibleAppId.startsWith(APP_PREFIX3) ? possibleAppId : void 0;
68014
- }
68015
- async function resolveAppUrl(ctx) {
68016
- const appUrl = ctx.path.split("/")[2];
68017
- let possibleAppUrl = `/${appUrl.toLowerCase()}`;
68018
- let tenantId = getTenantId();
68019
- if (!environment_default.isDev() && environment_default.MULTI_TENANCY) {
68020
- tenantId = getTenantIDFromCtx(ctx, {
68021
- includeStrategies: ["subdomain" /* SUBDOMAIN */]
68022
- });
68023
- }
68024
- const apps = await doInTenant(
68025
- tenantId,
68026
- () => getAllApps({ dev: false })
68027
- );
68028
- const app = apps.filter(
68029
- (a) => a.url && a.url.toLowerCase() === possibleAppUrl
68030
- )[0];
68031
- return app && app.appId ? app.appId : void 0;
68032
- }
68033
- function isServingApp(ctx) {
68034
- if (ctx.path.startsWith(`/${APP_PREFIX3}`)) {
68035
- return true;
68036
- }
68037
- return ctx.path.startsWith(PROD_APP_PREFIX);
68038
- }
68039
- function isServingBuilder(ctx) {
68040
- return ctx.path.startsWith(BUILDER_APP_PREFIX);
68041
- }
68042
- function isServingBuilderPreview(ctx) {
68043
- return ctx.path.startsWith(BUILDER_PREVIEW_PATH);
68044
- }
68045
- function isPublicApiRequest(ctx) {
68046
- return ctx.path.startsWith(PUBLIC_API_PREFIX);
68047
- }
68048
- async function getAppIdFromCtx(ctx) {
68049
- const options2 = [ctx.request.headers["x-budibase-app-id" /* APP_ID */]];
68050
- let appId;
68051
- for (let option of options2) {
68052
- appId = confirmAppId(option);
68053
- if (appId) {
68054
- break;
68055
- }
68056
- }
68057
- if (!appId && ctx.request.body && ctx.request.body.appId) {
68058
- appId = confirmAppId(ctx.request.body.appId);
68059
- }
68060
- const pathId = parseAppIdFromUrlPath(ctx.path);
68061
- if (!appId && pathId) {
68062
- appId = confirmAppId(pathId);
68063
- }
68064
- const isBuilderPreview = ctx.path.startsWith(BUILDER_PREVIEW_PATH);
68065
- const isViewingProdApp = ctx.path.startsWith(PROD_APP_PREFIX) && !isBuilderPreview;
68066
- if (!appId && isViewingProdApp) {
68067
- appId = confirmAppId(await resolveAppUrl(ctx));
68068
- }
68069
- const referer = ctx.request.headers.referer;
68070
- if (!appId && referer?.includes(BUILDER_APP_PREFIX)) {
68071
- const refererId = parseAppIdFromUrlPath(ctx.request.headers.referer);
68072
- appId = confirmAppId(refererId);
68073
- }
68074
- return appId;
68075
- }
68076
- function parseAppIdFromUrlPath(url) {
68077
- if (!url) {
68078
- return;
68079
- }
68080
- return url.split("?")[0].split("/").find((subPath) => subPath.startsWith(APP_PREFIX3));
68081
- }
68082
- function openJwt(token) {
68083
- if (!token) {
68084
- return void 0;
68085
- }
68086
- try {
68087
- return import_jsonwebtoken.default.verify(token, environment_default.JWT_SECRET);
68088
- } catch (e) {
68089
- if (environment_default.JWT_SECRET_FALLBACK) {
68090
- return import_jsonwebtoken.default.verify(token, environment_default.JWT_SECRET_FALLBACK);
68091
- } else {
68092
- throw e;
68093
- }
68094
- }
68095
- }
68096
- function isValidInternalAPIKey(apiKey) {
68097
- if (environment_default.INTERNAL_API_KEY && environment_default.INTERNAL_API_KEY === apiKey) {
68098
- return true;
68099
- }
68100
- return !!(environment_default.INTERNAL_API_KEY_FALLBACK && environment_default.INTERNAL_API_KEY_FALLBACK === apiKey);
68101
- }
68102
- function getCookie(ctx, name) {
68103
- const cookie = ctx.cookies.get(name);
68104
- if (!cookie) {
68105
- return void 0;
68106
- }
68107
- return openJwt(cookie);
68108
- }
68109
- function setCookie(ctx, value, name = "builder", opts = { sign: true }) {
68110
- if (value && opts && opts.sign) {
68111
- value = import_jsonwebtoken.default.sign(value, environment_default.JWT_SECRET);
68112
- }
68113
- const config = {
68114
- expires: MAX_VALID_DATE,
68115
- path: "/",
68116
- httpOnly: false,
68117
- overwrite: true
68118
- };
68119
- if (environment_default.COOKIE_DOMAIN) {
68120
- config.domain = environment_default.COOKIE_DOMAIN;
68121
- }
68122
- ctx.cookies.set(name, value, config);
68123
- }
68124
- function clearCookie(ctx, name) {
68125
- setCookie(ctx, null, name);
68126
- }
68127
- function isClient(ctx) {
68128
- return ctx.headers["x-budibase-type" /* TYPE */] === "client";
68129
- }
68130
- function timeout(timeMs) {
68131
- return new Promise((resolve) => setTimeout(resolve, timeMs));
68132
- }
68133
- function isAudited(event) {
68134
- return !!AuditedEventFriendlyName[event];
68135
- }
68136
- function hasCircularStructure(json) {
68137
- if (typeof json !== "object") {
68138
- return false;
68139
- }
68140
- try {
68141
- JSON.stringify(json);
68142
- } catch (err) {
68143
- if (err instanceof Error && err?.message.includes("circular structure")) {
68144
- return true;
68145
- }
68146
- }
68147
- return false;
68148
- }
68149
-
68150
- // src/utils/stringUtils.ts
68151
- function validEmail(value) {
68152
- return value && !!value.match(
68153
- /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
68154
- );
68155
- }
68156
-
68157
- // src/utils/Duration.ts
68158
- var DurationType = /* @__PURE__ */ ((DurationType2) => {
68159
- DurationType2["MILLISECONDS"] = "milliseconds";
68160
- DurationType2["SECONDS"] = "seconds";
68161
- DurationType2["MINUTES"] = "minutes";
68162
- DurationType2["HOURS"] = "hours";
68163
- DurationType2["DAYS"] = "days";
68164
- return DurationType2;
68165
- })(DurationType || {});
68166
- var conversion = {
68167
- milliseconds: 1,
68168
- seconds: 1e3,
68169
- minutes: 60 * 1e3,
68170
- hours: 60 * 60 * 1e3,
68171
- days: 24 * 60 * 60 * 1e3
68172
- };
68173
- var Duration = class _Duration {
68174
- static convert(from, to, duration) {
68175
- const milliseconds = duration * conversion[from];
68176
- return milliseconds / conversion[to];
68177
- }
68178
- static from(from, duration) {
68179
- return {
68180
- to: (to) => {
68181
- return _Duration.convert(from, to, duration);
68182
- },
68183
- toMs: () => {
68184
- return _Duration.convert(from, "milliseconds" /* MILLISECONDS */, duration);
68185
- },
68186
- toSeconds: () => {
68187
- return _Duration.convert(from, "seconds" /* SECONDS */, duration);
68188
- }
68189
- };
68190
- }
68191
- static fromSeconds(duration) {
68192
- return _Duration.from("seconds" /* SECONDS */, duration);
68193
- }
68194
- static fromMinutes(duration) {
68195
- return _Duration.from("minutes" /* MINUTES */, duration);
68196
- }
68197
- static fromHours(duration) {
68198
- return _Duration.from("hours" /* HOURS */, duration);
68199
- }
68200
- static fromDays(duration) {
68201
- return _Duration.from("days" /* DAYS */, duration);
68202
- }
68203
- static fromMilliseconds(duration) {
68204
- return _Duration.from("milliseconds" /* MILLISECONDS */, duration);
68205
- }
68206
- };
68207
-
68208
- // src/features/features.ts
68209
- var posthog;
68210
- function init4(opts) {
68211
- if (environment_default.POSTHOG_TOKEN && environment_default.POSTHOG_API_HOST && !environment_default.SELF_HOSTED && environment_default.POSTHOG_FEATURE_FLAGS_ENABLED) {
68212
- console.log("initializing posthog client...");
68213
- posthog = new import_posthog_node.PostHog(environment_default.POSTHOG_TOKEN, {
68214
- host: environment_default.POSTHOG_API_HOST,
68215
- personalApiKey: environment_default.POSTHOG_PERSONAL_TOKEN,
68216
- featureFlagsPollingInterval: Duration.fromMinutes(3).toMs(),
68217
- ...opts
68218
- });
68219
- } else {
68220
- console.log("posthog disabled");
68221
- }
68222
- }
68223
- function shutdown2() {
68224
- posthog?.shutdown();
68225
- }
68226
- var Flag = class {
68227
- constructor(defaultValue) {
68228
- this.defaultValue = defaultValue;
68229
- }
68230
- static boolean(defaultValue) {
68231
- return new BooleanFlag(defaultValue);
68232
- }
68233
- static string(defaultValue) {
68234
- return new StringFlag(defaultValue);
68235
- }
68236
- static number(defaultValue) {
68237
- return new NumberFlag(defaultValue);
68238
- }
68239
- };
68240
- var BooleanFlag = class extends Flag {
68241
- parse(value) {
68242
- if (typeof value === "string") {
68243
- return ["true", "t", "1"].includes(value.toLowerCase());
68244
- }
68245
- if (typeof value === "boolean") {
68246
- return value;
68247
- }
68248
- throw new Error(`could not parse value "${value}" as boolean`);
68249
- }
68250
- };
68251
- var StringFlag = class extends Flag {
68252
- parse(value) {
68253
- if (typeof value === "string") {
68254
- return value;
68255
- }
68256
- throw new Error(`could not parse value "${value}" as string`);
68257
- }
68258
- };
68259
- var NumberFlag = class extends Flag {
68260
- parse(value) {
68261
- if (typeof value === "number") {
68262
- return value;
68263
- }
68264
- if (typeof value === "string") {
68265
- const parsed = parseFloat(value);
68266
- if (!isNaN(parsed)) {
68267
- return parsed;
68268
- }
68269
- }
68270
- throw new Error(`could not parse value "${value}" as number`);
68271
- }
68272
- };
68273
- function parseEnvFlags(flags2) {
68274
- const split = flags2.split(",").map((x) => x.split(":"));
68275
- const result = [];
68276
- for (const [tenantId, ...features] of split) {
68277
- for (let feature of features) {
68278
- let value = true;
68279
- if (feature.startsWith("!")) {
68280
- feature = feature.slice(1);
68281
- value = false;
68282
- }
68283
- result.push({ tenantId, key: feature, value });
68284
- }
68285
- }
68286
- return result;
68287
- }
68288
- var FlagSet = class {
68289
- constructor(flagSchema) {
68290
- this.flagSchema = flagSchema;
68291
- this.setId = crypto.randomUUID();
68292
- }
68293
- defaults() {
68294
- return Object.keys(this.flagSchema).reduce((acc, key) => {
68295
- const typedKey = key;
68296
- acc[typedKey] = this.flagSchema[key].defaultValue;
68297
- return acc;
68298
- }, {});
68299
- }
68300
- isFlagName(name) {
68301
- return this.flagSchema[name] !== void 0;
68302
- }
68303
- async get(key) {
68304
- const flags2 = await this.fetch();
68305
- return flags2[key];
68306
- }
68307
- async isEnabled(key) {
68308
- const flags2 = await this.fetch();
68309
- return flags2[key];
68310
- }
68311
- async fetch() {
68312
- return await import_dd_trace3.default.trace("features.fetch", async (span) => {
68313
- const cachedFlags = getFeatureFlags(this.setId);
68314
- if (cachedFlags) {
68315
- span?.addTags({ fromCache: true });
68316
- return cachedFlags;
68317
- }
68318
- const tags = {};
68319
- const flagValues = this.defaults();
68320
- const currentTenantId = getTenantId();
68321
- const specificallySetFalse = /* @__PURE__ */ new Set();
68322
- for (const { tenantId: tenantId2, key, value } of parseEnvFlags(
68323
- environment_default.TENANT_FEATURE_FLAGS || ""
68324
- )) {
68325
- if (!tenantId2 || tenantId2 !== "*" && tenantId2 !== currentTenantId) {
68326
- continue;
68327
- }
68328
- tags[`readFromEnvironmentVars`] = true;
68329
- if (value === false) {
68330
- specificallySetFalse.add(key);
68331
- }
68332
- if (!this.isFlagName(key)) {
68333
- continue;
68334
- }
68335
- if (typeof flagValues[key] !== "boolean") {
68336
- throw new Error(`Feature: ${key} is not a boolean`);
68337
- }
68338
- flagValues[key] = value;
68339
- tags[`flags.${key}.source`] = "environment";
68340
- }
68341
- const identity = getIdentity();
68342
- let userId = identity?._id;
68343
- if (!userId) {
68344
- const ip = getIP();
68345
- if (ip) {
68346
- userId = crypto.createHash("sha512").update(ip).digest("hex");
68347
- }
68348
- }
68349
- let tenantId = identity?.tenantId;
68350
- if (!tenantId) {
68351
- tenantId = currentTenantId;
68352
- }
68353
- tags[`identity.type`] = identity?.type;
68354
- tags[`identity._id`] = identity?._id;
68355
- tags[`tenantId`] = tenantId;
68356
- tags[`userId`] = userId;
68357
- if (posthog && userId) {
68358
- tags[`readFromPostHog`] = true;
68359
- const personProperties = { tenantId };
68360
- const posthogFlags = await posthog.getAllFlagsAndPayloads(userId, {
68361
- personProperties
68362
- });
68363
- for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
68364
- if (!this.isFlagName(name)) {
68365
- console.warn(`Unexpected posthog flag "${name}": ${value}`);
68366
- continue;
68367
- }
68368
- if (flagValues[name] === true || specificallySetFalse.has(name)) {
68369
- continue;
68370
- }
68371
- const payload = posthogFlags.featureFlagPayloads?.[name];
68372
- const flag = this.flagSchema[name];
68373
- try {
68374
- flagValues[name] = flag.parse(payload || value);
68375
- tags[`flags.${name}.source`] = "posthog";
68376
- } catch (err) {
68377
- console.warn(`Error parsing posthog flag "${name}": ${value}`, err);
68378
- }
68379
- }
68380
- }
68381
- setFeatureFlags(this.setId, flagValues);
68382
- for (const [key, value] of Object.entries(flagValues)) {
68383
- tags[`flags.${key}.value`] = value;
68384
- }
68385
- span?.addTags(tags);
68386
- return flagValues;
68387
- });
68388
- }
68389
- };
68390
- var flags = new FlagSet({
68391
- ["DEFAULT_VALUES" /* DEFAULT_VALUES */]: Flag.boolean(true),
68392
- ["AUTOMATION_BRANCHING" /* AUTOMATION_BRANCHING */]: Flag.boolean(true),
68393
- ["SQS" /* SQS */]: Flag.boolean(true),
68394
- ["ENRICHED_RELATIONSHIPS" /* ENRICHED_RELATIONSHIPS */]: Flag.boolean(true),
68395
- ["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(true),
68396
- ["BUDIBASE_AI" /* BUDIBASE_AI */]: Flag.boolean(true)
68397
- });
68398
-
68399
- // src/features/tests/utils.ts
68400
- var utils_exports5 = {};
68401
- __export(utils_exports5, {
68402
- setFeatureFlags: () => setFeatureFlags2,
68403
- withFeatureFlags: () => withFeatureFlags
68404
- });
68405
- function getCurrentFlags() {
68406
- const result = {};
68407
- for (const { tenantId, key, value } of parseEnvFlags(
68408
- process.env.TENANT_FEATURE_FLAGS || ""
68409
- )) {
68410
- const tenantFlags = result[tenantId] || {};
68411
- if (tenantFlags[key] === false) {
68412
- continue;
68413
- }
68414
- tenantFlags[key] = value;
68415
- result[tenantId] = tenantFlags;
68416
- }
68417
- return result;
68418
- }
68419
- function buildFlagString(flags2) {
68420
- const parts = [];
68421
- for (const [tenantId, tenantFlags] of Object.entries(flags2)) {
68422
- for (const [key, value] of Object.entries(tenantFlags)) {
68423
- if (value === false) {
68424
- parts.push(`${tenantId}:!${key}`);
68425
- } else {
68426
- parts.push(`${tenantId}:${key}`);
68427
- }
68428
- }
68429
- }
68430
- return parts.join(",");
68431
- }
68432
- function setFeatureFlags2(tenantId, flags2) {
68433
- const current = getCurrentFlags();
68434
- for (const [key, value] of Object.entries(flags2)) {
68435
- const tenantFlags = current[tenantId] || {};
68436
- tenantFlags[key] = value;
68437
- current[tenantId] = tenantFlags;
68438
- }
68439
- const flagString = buildFlagString(current);
68440
- return setEnv({ TENANT_FEATURE_FLAGS: flagString });
68441
- }
68442
- function withFeatureFlags(tenantId, flags2, f) {
68443
- const cleanup3 = setFeatureFlags2(tenantId, flags2);
68444
- const result = f();
68445
- if (result instanceof Promise) {
68446
- return result.finally(cleanup3);
68447
- } else {
68448
- cleanup3();
68449
- return result;
68450
- }
68451
- }
68452
-
68453
- // src/db/couch/DatabaseImpl.ts
68454
- var DATABASE_NOT_FOUND = "Database does not exist.";
68455
- function buildNano(couchInfo) {
68456
- return (0, import_nano.default)({
68457
- url: couchInfo.url,
68458
- requestDefaults: {
68459
- headers: {
68460
- Authorization: couchInfo.cookie
68461
- }
68462
- },
68463
- parseUrl: false
68464
- });
68465
- }
68466
- var CouchDBError = class extends Error {
68467
- constructor(message, info) {
68468
- super(message);
68469
- const statusCode = info.status || info.statusCode || 500;
68470
- this.status = statusCode;
68471
- this.statusCode = statusCode;
68472
- this.reason = info.reason || "Unknown";
68473
- this.name = info.name;
68474
- this.errid = info.errid || "Unknown";
68475
- this.description = info.description || "Unknown";
68476
- this.error = info.error || "Not found";
68477
- }
68478
- };
68479
- function DatabaseWithConnection(dbName, connection, opts) {
68480
- if (!dbName || !connection) {
68481
- throw new Error(
68482
- "Unable to create database without database name or connection"
68483
- );
68484
- }
68485
- const db = new DatabaseImpl(dbName, opts, connection);
68486
- return new DDInstrumentedDatabase(db);
68487
- }
68488
- var DatabaseImpl = class _DatabaseImpl {
68489
- constructor(dbName, opts, connection) {
68490
- this.couchInfo = getCouchInfo();
68491
- this.name = dbName;
68492
- this.pouchOpts = opts || {};
68493
- if (connection) {
68494
- this.couchInfo = getCouchInfo(connection);
68495
- this.instanceNano = buildNano(this.couchInfo);
68496
- }
68497
- if (!_DatabaseImpl.nano) {
68498
- _DatabaseImpl.init();
68499
- }
68500
- }
68501
- static init() {
68502
- const couchInfo = getCouchInfo();
68503
- _DatabaseImpl.nano = buildNano(couchInfo);
68504
- }
68505
- exists(docId) {
68506
- if (docId === void 0) {
68507
- return this.dbExists();
68508
- }
68509
- return this.docExists(docId);
68510
- }
68511
- async dbExists() {
68512
- const response = await directCouchUrlCall({
68513
- url: `${this.couchInfo.url}/${this.name}`,
68514
- method: "HEAD",
68515
- cookie: this.couchInfo.cookie
68516
- });
68517
- return response.status === 200;
68518
- }
68519
- async docExists(id) {
68520
- try {
68521
- await this.performCall((db) => () => db.head(id));
68522
- return true;
68523
- } catch {
68524
- return false;
68525
- }
68526
- }
68527
- nano() {
68528
- return this.instanceNano || _DatabaseImpl.nano;
68529
- }
68530
- getDb() {
68531
- return this.nano().db.use(this.name);
68532
- }
68533
- async checkAndCreateDb() {
68534
- let shouldCreate = !this.pouchOpts?.skip_setup;
68535
- let exists2 = await this.exists();
68536
- if (!shouldCreate && !exists2) {
68537
- throw new Error("DB does not exist");
68538
- }
68539
- if (!exists2) {
68540
- try {
68541
- await this.nano().db.create(this.name);
68542
- } catch (err) {
68543
- if (err.statusCode !== 412) {
68544
- throw new CouchDBError(err.message, err);
68545
- }
68546
- }
68547
- }
68548
- return this.getDb();
68549
- }
68550
- // this function fetches the DB and handles if DB creation is needed
68551
- async performCallWithDBCreation(call) {
68552
- const db = this.getDb();
68553
- const fnc = await call(db);
68554
- try {
68555
- return await fnc();
68556
- } catch (err) {
68557
- if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {
68558
- await this.checkAndCreateDb();
68559
- return await this.performCallWithDBCreation(call);
68560
- }
68561
- throw new CouchDBError(`CouchDB error: ${err.message}`, err);
68562
- }
68563
- }
68564
- async performCall(call) {
68565
- const db = this.getDb();
68566
- const fnc = await call(db);
68567
- try {
68568
- return await fnc();
68569
- } catch (err) {
68570
- throw new CouchDBError(`CouchDB error: ${err.message}`, err);
68571
- }
68572
- }
68573
- async get(id) {
68574
- return this.performCall((db) => {
68575
- if (!id) {
68576
- throw new Error("Unable to get doc without a valid _id.");
68577
- }
68578
- return () => db.get(id);
68579
- });
67957
+ async get(id) {
67958
+ return this.performCall((db) => {
67959
+ if (!id) {
67960
+ throw new Error("Unable to get doc without a valid _id.");
67961
+ }
67962
+ return () => db.get(id);
67963
+ });
68580
67964
  }
68581
67965
  async tryGet(id) {
68582
67966
  try {
@@ -68781,7 +68165,7 @@ var DatabaseImpl = class _DatabaseImpl {
68781
68165
  });
68782
68166
  }
68783
68167
  async destroy() {
68784
- if (await flags.isEnabled("SQS" /* SQS */) && await this.exists(SQLITE_DESIGN_DOC_ID)) {
68168
+ if (await this.exists(SQLITE_DESIGN_DOC_ID)) {
68785
68169
  const definition = await this.get(SQLITE_DESIGN_DOC_ID);
68786
68170
  definition.sql.tables = {};
68787
68171
  await this.put(definition);
@@ -69303,6 +68687,123 @@ __export(user_exports, {
69303
68687
  invalidateUser: () => invalidateUser
69304
68688
  });
69305
68689
 
68690
+ // src/tenancy/index.ts
68691
+ var tenancy_exports = {};
68692
+ __export(tenancy_exports, {
68693
+ addTenantToUrl: () => addTenantToUrl,
68694
+ getTenantDB: () => getTenantDB,
68695
+ getTenantIDFromCtx: () => getTenantIDFromCtx,
68696
+ isUserInAppTenant: () => isUserInAppTenant
68697
+ });
68698
+
68699
+ // src/tenancy/db.ts
68700
+ function getTenantDB(tenantId) {
68701
+ return getDB(getGlobalDBName(tenantId));
68702
+ }
68703
+
68704
+ // src/tenancy/tenancy.ts
68705
+ function addTenantToUrl(url) {
68706
+ const tenantId = getTenantId();
68707
+ if (isMultiTenant()) {
68708
+ const char = url.indexOf("?") === -1 ? "?" : "&";
68709
+ url += `${char}tenantId=${tenantId}`;
68710
+ }
68711
+ return url;
68712
+ }
68713
+ var isUserInAppTenant = (appId, user) => {
68714
+ let userTenantId;
68715
+ if (user) {
68716
+ userTenantId = user.tenantId || DEFAULT_TENANT_ID;
68717
+ } else {
68718
+ userTenantId = getTenantId();
68719
+ }
68720
+ const tenantId = getTenantIDFromAppID(appId) || DEFAULT_TENANT_ID;
68721
+ return tenantId === userTenantId;
68722
+ };
68723
+ var ALL_STRATEGIES = Object.values(TenantResolutionStrategy);
68724
+ var getTenantIDFromCtx = (ctx, opts) => {
68725
+ if (!isMultiTenant()) {
68726
+ return DEFAULT_TENANT_ID;
68727
+ }
68728
+ if (opts.allowNoTenant === void 0) {
68729
+ opts.allowNoTenant = false;
68730
+ }
68731
+ if (!opts.includeStrategies) {
68732
+ opts.includeStrategies = ALL_STRATEGIES;
68733
+ }
68734
+ if (!opts.excludeStrategies) {
68735
+ opts.excludeStrategies = [];
68736
+ }
68737
+ const isAllowed = (strategy) => {
68738
+ if (opts.excludeStrategies?.includes(strategy)) {
68739
+ return false;
68740
+ }
68741
+ if (opts.includeStrategies?.includes(strategy)) {
68742
+ return true;
68743
+ }
68744
+ };
68745
+ if (isAllowed("user" /* USER */)) {
68746
+ const userTenantId = ctx.user?.tenantId;
68747
+ if (userTenantId) {
68748
+ return userTenantId;
68749
+ }
68750
+ }
68751
+ if (isAllowed("header" /* HEADER */)) {
68752
+ const headerTenantId = ctx.request.headers["x-budibase-tenant-id" /* TENANT_ID */];
68753
+ if (headerTenantId) {
68754
+ return headerTenantId;
68755
+ }
68756
+ }
68757
+ if (isAllowed("query" /* QUERY */)) {
68758
+ const queryTenantId = ctx.request.query.tenantId;
68759
+ if (queryTenantId) {
68760
+ return queryTenantId;
68761
+ }
68762
+ }
68763
+ if (isAllowed("subdomain" /* SUBDOMAIN */)) {
68764
+ let platformHost;
68765
+ try {
68766
+ platformHost = new URL(getPlatformURL()).host.split(":")[0];
68767
+ } catch (err) {
68768
+ if (err.code !== "ERR_INVALID_URL") {
68769
+ throw err;
68770
+ }
68771
+ }
68772
+ const requestHost = ctx.host;
68773
+ if (platformHost && requestHost.includes(platformHost)) {
68774
+ const tenantId = requestHost.substring(
68775
+ 0,
68776
+ requestHost.indexOf(`.${platformHost}`)
68777
+ );
68778
+ if (tenantId) {
68779
+ return tenantId;
68780
+ }
68781
+ }
68782
+ }
68783
+ if (isAllowed("path" /* PATH */)) {
68784
+ const match = ctx.matched.find(
68785
+ (m) => !!m.paramNames.find((p) => p.name === "tenantId")
68786
+ );
68787
+ const ctxUrl = ctx.originalUrl;
68788
+ let url;
68789
+ if (ctxUrl.includes("?")) {
68790
+ url = ctxUrl.split("?")[0];
68791
+ } else {
68792
+ url = ctxUrl;
68793
+ }
68794
+ if (match) {
68795
+ const params2 = match.params(url, match.captures(url), {});
68796
+ if (params2.tenantId) {
68797
+ return params2.tenantId;
68798
+ }
68799
+ }
68800
+ }
68801
+ if (!opts.allowNoTenant) {
68802
+ ctx.throw(403, "Tenant id not set");
68803
+ }
68804
+ return void 0;
68805
+ };
68806
+
69306
68807
  // src/platform/index.ts
69307
68808
  var platform_exports = {};
69308
68809
  __export(platform_exports, {
@@ -69425,6 +68926,249 @@ __export(redlockImpl_exports, {
69425
68926
  newRedlock: () => newRedlock
69426
68927
  });
69427
68928
  var import_redlock = __toESM(require("redlock"));
68929
+
68930
+ // src/utils/index.ts
68931
+ var utils_exports4 = {};
68932
+ __export(utils_exports4, {
68933
+ Duration: () => Duration,
68934
+ DurationType: () => DurationType,
68935
+ clearCookie: () => clearCookie,
68936
+ compare: () => compare,
68937
+ getAppIdFromCtx: () => getAppIdFromCtx,
68938
+ getCookie: () => getCookie,
68939
+ hasCircularStructure: () => hasCircularStructure,
68940
+ hash: () => hash,
68941
+ isAudited: () => isAudited,
68942
+ isClient: () => isClient,
68943
+ isPublicApiRequest: () => isPublicApiRequest,
68944
+ isServingApp: () => isServingApp,
68945
+ isServingBuilder: () => isServingBuilder,
68946
+ isServingBuilderPreview: () => isServingBuilderPreview,
68947
+ isValidInternalAPIKey: () => isValidInternalAPIKey,
68948
+ newid: () => newid,
68949
+ openJwt: () => openJwt,
68950
+ resolveAppUrl: () => resolveAppUrl,
68951
+ setCookie: () => setCookie,
68952
+ timeout: () => timeout,
68953
+ validEmail: () => validEmail
68954
+ });
68955
+
68956
+ // src/utils/hashing.ts
68957
+ var bcrypt = environment_default.JS_BCRYPT ? require("bcryptjs") : require("bcrypt");
68958
+ var SALT_ROUNDS = environment_default.SALT_ROUNDS || 10;
68959
+ async function hash(data) {
68960
+ const salt = await bcrypt.genSalt(SALT_ROUNDS);
68961
+ return bcrypt.hash(data, salt);
68962
+ }
68963
+ async function compare(data, encrypted) {
68964
+ return bcrypt.compare(data, encrypted);
68965
+ }
68966
+
68967
+ // src/utils/utils.ts
68968
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"));
68969
+ var APP_PREFIX3 = "app" /* APP */ + SEPARATOR;
68970
+ var PROD_APP_PREFIX = "/app/";
68971
+ var BUILDER_PREVIEW_PATH = "/app/preview";
68972
+ var BUILDER_PREFIX = "/builder";
68973
+ var BUILDER_APP_PREFIX = `${BUILDER_PREFIX}/app/`;
68974
+ var PUBLIC_API_PREFIX = "/api/public/v";
68975
+ function confirmAppId(possibleAppId) {
68976
+ return possibleAppId && possibleAppId.startsWith(APP_PREFIX3) ? possibleAppId : void 0;
68977
+ }
68978
+ async function resolveAppUrl(ctx) {
68979
+ const appUrl = ctx.path.split("/")[2];
68980
+ let possibleAppUrl = `/${appUrl.toLowerCase()}`;
68981
+ let tenantId = getTenantId();
68982
+ if (!environment_default.isDev() && environment_default.MULTI_TENANCY) {
68983
+ tenantId = getTenantIDFromCtx(ctx, {
68984
+ includeStrategies: ["subdomain" /* SUBDOMAIN */]
68985
+ });
68986
+ }
68987
+ const apps = await doInTenant(
68988
+ tenantId,
68989
+ () => getAllApps({ dev: false })
68990
+ );
68991
+ const app = apps.filter(
68992
+ (a) => a.url && a.url.toLowerCase() === possibleAppUrl
68993
+ )[0];
68994
+ return app && app.appId ? app.appId : void 0;
68995
+ }
68996
+ function isServingApp(ctx) {
68997
+ if (ctx.path.startsWith(`/${APP_PREFIX3}`)) {
68998
+ return true;
68999
+ }
69000
+ return ctx.path.startsWith(PROD_APP_PREFIX);
69001
+ }
69002
+ function isServingBuilder(ctx) {
69003
+ return ctx.path.startsWith(BUILDER_APP_PREFIX);
69004
+ }
69005
+ function isServingBuilderPreview(ctx) {
69006
+ return ctx.path.startsWith(BUILDER_PREVIEW_PATH);
69007
+ }
69008
+ function isPublicApiRequest(ctx) {
69009
+ return ctx.path.startsWith(PUBLIC_API_PREFIX);
69010
+ }
69011
+ async function getAppIdFromCtx(ctx) {
69012
+ const options2 = [ctx.request.headers["x-budibase-app-id" /* APP_ID */]];
69013
+ let appId;
69014
+ for (let option of options2) {
69015
+ appId = confirmAppId(option);
69016
+ if (appId) {
69017
+ break;
69018
+ }
69019
+ }
69020
+ if (!appId && ctx.request.body && ctx.request.body.appId) {
69021
+ appId = confirmAppId(ctx.request.body.appId);
69022
+ }
69023
+ const pathId = parseAppIdFromUrlPath(ctx.path);
69024
+ if (!appId && pathId) {
69025
+ appId = confirmAppId(pathId);
69026
+ }
69027
+ const isBuilderPreview = ctx.path.startsWith(BUILDER_PREVIEW_PATH);
69028
+ const isViewingProdApp = ctx.path.startsWith(PROD_APP_PREFIX) && !isBuilderPreview;
69029
+ if (!appId && isViewingProdApp) {
69030
+ appId = confirmAppId(await resolveAppUrl(ctx));
69031
+ }
69032
+ const referer = ctx.request.headers.referer;
69033
+ if (!appId && referer?.includes(BUILDER_APP_PREFIX)) {
69034
+ const refererId = parseAppIdFromUrlPath(ctx.request.headers.referer);
69035
+ appId = confirmAppId(refererId);
69036
+ }
69037
+ return appId;
69038
+ }
69039
+ function parseAppIdFromUrlPath(url) {
69040
+ if (!url) {
69041
+ return;
69042
+ }
69043
+ return url.split("?")[0].split("/").find((subPath) => subPath.startsWith(APP_PREFIX3));
69044
+ }
69045
+ function openJwt(token) {
69046
+ if (!token) {
69047
+ return void 0;
69048
+ }
69049
+ try {
69050
+ return import_jsonwebtoken.default.verify(token, environment_default.JWT_SECRET);
69051
+ } catch (e) {
69052
+ if (environment_default.JWT_SECRET_FALLBACK) {
69053
+ return import_jsonwebtoken.default.verify(token, environment_default.JWT_SECRET_FALLBACK);
69054
+ } else {
69055
+ throw e;
69056
+ }
69057
+ }
69058
+ }
69059
+ function isValidInternalAPIKey(apiKey) {
69060
+ if (environment_default.INTERNAL_API_KEY && environment_default.INTERNAL_API_KEY === apiKey) {
69061
+ return true;
69062
+ }
69063
+ return !!(environment_default.INTERNAL_API_KEY_FALLBACK && environment_default.INTERNAL_API_KEY_FALLBACK === apiKey);
69064
+ }
69065
+ function getCookie(ctx, name) {
69066
+ const cookie = ctx.cookies.get(name);
69067
+ if (!cookie) {
69068
+ return void 0;
69069
+ }
69070
+ return openJwt(cookie);
69071
+ }
69072
+ function setCookie(ctx, value, name = "builder", opts = { sign: true }) {
69073
+ if (value && opts && opts.sign) {
69074
+ value = import_jsonwebtoken.default.sign(value, environment_default.JWT_SECRET);
69075
+ }
69076
+ const config = {
69077
+ expires: MAX_VALID_DATE,
69078
+ path: "/",
69079
+ httpOnly: false,
69080
+ overwrite: true
69081
+ };
69082
+ if (environment_default.COOKIE_DOMAIN) {
69083
+ config.domain = environment_default.COOKIE_DOMAIN;
69084
+ }
69085
+ ctx.cookies.set(name, value, config);
69086
+ }
69087
+ function clearCookie(ctx, name) {
69088
+ setCookie(ctx, null, name);
69089
+ }
69090
+ function isClient(ctx) {
69091
+ return ctx.headers["x-budibase-type" /* TYPE */] === "client";
69092
+ }
69093
+ function timeout(timeMs) {
69094
+ return new Promise((resolve) => setTimeout(resolve, timeMs));
69095
+ }
69096
+ function isAudited(event) {
69097
+ return !!AuditedEventFriendlyName[event];
69098
+ }
69099
+ function hasCircularStructure(json) {
69100
+ if (typeof json !== "object") {
69101
+ return false;
69102
+ }
69103
+ try {
69104
+ JSON.stringify(json);
69105
+ } catch (err) {
69106
+ if (err instanceof Error && err?.message.includes("circular structure")) {
69107
+ return true;
69108
+ }
69109
+ }
69110
+ return false;
69111
+ }
69112
+
69113
+ // src/utils/stringUtils.ts
69114
+ function validEmail(value) {
69115
+ return value && !!value.match(
69116
+ /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
69117
+ );
69118
+ }
69119
+
69120
+ // src/utils/Duration.ts
69121
+ var DurationType = /* @__PURE__ */ ((DurationType2) => {
69122
+ DurationType2["MILLISECONDS"] = "milliseconds";
69123
+ DurationType2["SECONDS"] = "seconds";
69124
+ DurationType2["MINUTES"] = "minutes";
69125
+ DurationType2["HOURS"] = "hours";
69126
+ DurationType2["DAYS"] = "days";
69127
+ return DurationType2;
69128
+ })(DurationType || {});
69129
+ var conversion = {
69130
+ milliseconds: 1,
69131
+ seconds: 1e3,
69132
+ minutes: 60 * 1e3,
69133
+ hours: 60 * 60 * 1e3,
69134
+ days: 24 * 60 * 60 * 1e3
69135
+ };
69136
+ var Duration = class _Duration {
69137
+ static convert(from, to, duration) {
69138
+ const milliseconds = duration * conversion[from];
69139
+ return milliseconds / conversion[to];
69140
+ }
69141
+ static from(from, duration) {
69142
+ return {
69143
+ to: (to) => {
69144
+ return _Duration.convert(from, to, duration);
69145
+ },
69146
+ toMs: () => {
69147
+ return _Duration.convert(from, "milliseconds" /* MILLISECONDS */, duration);
69148
+ },
69149
+ toSeconds: () => {
69150
+ return _Duration.convert(from, "seconds" /* SECONDS */, duration);
69151
+ }
69152
+ };
69153
+ }
69154
+ static fromSeconds(duration) {
69155
+ return _Duration.from("seconds" /* SECONDS */, duration);
69156
+ }
69157
+ static fromMinutes(duration) {
69158
+ return _Duration.from("minutes" /* MINUTES */, duration);
69159
+ }
69160
+ static fromHours(duration) {
69161
+ return _Duration.from("hours" /* HOURS */, duration);
69162
+ }
69163
+ static fromDays(duration) {
69164
+ return _Duration.from("days" /* DAYS */, duration);
69165
+ }
69166
+ static fromMilliseconds(duration) {
69167
+ return _Duration.from("milliseconds" /* MILLISECONDS */, duration);
69168
+ }
69169
+ };
69170
+
69171
+ // src/redis/redlockImpl.ts
69428
69172
  async function getClient(type, opts) {
69429
69173
  if (type === "custom" /* CUSTOM */) {
69430
69174
  return newRedlock(opts);
@@ -69759,8 +69503,8 @@ __export(users_exports3, {
69759
69503
  });
69760
69504
 
69761
69505
  // src/users/utils.ts
69762
- var utils_exports6 = {};
69763
- __export(utils_exports6, {
69506
+ var utils_exports5 = {};
69507
+ __export(utils_exports5, {
69764
69508
  getAccountHolderFromUsers: () => getAccountHolderFromUsers,
69765
69509
  hasAdminPermissions: () => hasAdminPermissions2,
69766
69510
  hasAppBuilderPermissions: () => hasAppBuilderPermissions2,
@@ -70561,7 +70305,7 @@ __export(events_exports, {
70561
70305
  rows: () => rows_default,
70562
70306
  screen: () => screen_default,
70563
70307
  serve: () => serve_default,
70564
- shutdown: () => shutdown5,
70308
+ shutdown: () => shutdown4,
70565
70309
  table: () => table_default,
70566
70310
  user: () => user_default,
70567
70311
  view: () => view_default
@@ -70571,7 +70315,7 @@ __export(events_exports, {
70571
70315
  var processors_exports = {};
70572
70316
  __export(processors_exports, {
70573
70317
  analyticsProcessor: () => analyticsProcessor,
70574
- init: () => init5,
70318
+ init: () => init4,
70575
70319
  processors: () => processors
70576
70320
  });
70577
70321
 
@@ -70585,7 +70329,7 @@ var enabled = async () => {
70585
70329
  };
70586
70330
 
70587
70331
  // src/events/processors/posthog/PosthogProcessor.ts
70588
- var import_posthog_node2 = require("posthog-node");
70332
+ var import_posthog_node = require("posthog-node");
70589
70333
 
70590
70334
  // src/events/processors/posthog/rateLimiting.ts
70591
70335
  var isRateLimited = (event) => {
@@ -70669,7 +70413,7 @@ var PosthogProcessor = class {
70669
70413
  if (!token) {
70670
70414
  throw new Error("Posthog token is not defined");
70671
70415
  }
70672
- this.posthog = new import_posthog_node2.PostHog(token);
70416
+ this.posthog = new import_posthog_node.PostHog(token);
70673
70417
  }
70674
70418
  async processEvent(event, identity, properties, timestamp) {
70675
70419
  if (EXCLUDED_EVENTS.includes(event)) {
@@ -70813,7 +70557,7 @@ __export(queue_exports, {
70813
70557
  Queue: () => import_bull2.Queue,
70814
70558
  QueueOptions: () => import_bull2.QueueOptions,
70815
70559
  createQueue: () => createQueue,
70816
- shutdown: () => shutdown3
70560
+ shutdown: () => shutdown2
70817
70561
  });
70818
70562
 
70819
70563
  // src/queue/inMemoryQueue.ts
@@ -71132,7 +70876,7 @@ function createQueue(jobQueue, opts = {}) {
71132
70876
  }
71133
70877
  return queue;
71134
70878
  }
71135
- async function shutdown3() {
70879
+ async function shutdown2() {
71136
70880
  if (cleanupInterval) {
71137
70881
  clear(cleanupInterval);
71138
70882
  }
@@ -71244,7 +70988,7 @@ var Processor = class {
71244
70988
  var analyticsProcessor = new AnalyticsProcessor();
71245
70989
  var loggingProcessor = new LoggingProcessor();
71246
70990
  var auditLogsProcessor = new AuditLogsProcessor();
71247
- function init5(auditingFn) {
70991
+ function init4(auditingFn) {
71248
70992
  return AuditLogsProcessor.init(auditingFn);
71249
70993
  }
71250
70994
  var processors = new Processor([
@@ -71722,10 +71466,10 @@ var getEventKey = (event, properties) => {
71722
71466
 
71723
71467
  // src/events/asyncEvents/queue.ts
71724
71468
  var asyncEventQueue;
71725
- function init6() {
71469
+ function init5() {
71726
71470
  asyncEventQueue = createQueue("systemEventQueue" /* SYSTEM_EVENT_QUEUE */);
71727
71471
  }
71728
- async function shutdown4() {
71472
+ async function shutdown3() {
71729
71473
  if (asyncEventQueue) {
71730
71474
  await asyncEventQueue.close();
71731
71475
  }
@@ -71734,7 +71478,7 @@ async function shutdown4() {
71734
71478
  // src/events/asyncEvents/publisher.ts
71735
71479
  async function publishAsyncEvent(payload) {
71736
71480
  if (!asyncEventQueue) {
71737
- init6();
71481
+ init5();
71738
71482
  }
71739
71483
  const { event, identity } = payload;
71740
71484
  if (AsyncEvents.indexOf(event) !== -1 && identity.tenantId) {
@@ -72881,7 +72625,7 @@ var group_default = {
72881
72625
  };
72882
72626
 
72883
72627
  // src/events/publishers/plugin.ts
72884
- async function init7(plugin) {
72628
+ async function init6(plugin) {
72885
72629
  const properties = {
72886
72630
  type: plugin.schema.type,
72887
72631
  name: plugin.name,
@@ -72912,7 +72656,7 @@ async function deleted13(plugin) {
72912
72656
  await publishEvent("plugin:deleted" /* PLUGIN_DELETED */, properties);
72913
72657
  }
72914
72658
  var plugin_default = {
72915
- init: init7,
72659
+ init: init6,
72916
72660
  imported: imported4,
72917
72661
  deleted: deleted13
72918
72662
  };
@@ -72992,7 +72736,7 @@ var auditLog_default = {
72992
72736
  // src/events/index.ts
72993
72737
  function initAsyncEvents() {
72994
72738
  }
72995
- var shutdown5 = () => {
72739
+ var shutdown4 = () => {
72996
72740
  processors.shutdown();
72997
72741
  console.log("Events shutdown");
72998
72742
  };
@@ -74109,7 +73853,7 @@ __export(docWritethrough_exports, {
74109
73853
  DocWritethrough: () => DocWritethrough,
74110
73854
  DocWritethroughProcessor: () => DocWritethroughProcessor,
74111
73855
  getProcessor: () => getProcessor,
74112
- init: () => init8
73856
+ init: () => init7
74113
73857
  });
74114
73858
  var PERSIST_MAX_ATTEMPTS = 100;
74115
73859
  var processor;
@@ -74174,13 +73918,13 @@ var DocWritethrough = class {
74174
73918
  });
74175
73919
  }
74176
73920
  };
74177
- function init8() {
73921
+ function init7() {
74178
73922
  processor = new DocWritethroughProcessor().init();
74179
73923
  return processor;
74180
73924
  }
74181
73925
  function getProcessor() {
74182
73926
  if (!processor) {
74183
- return init8();
73927
+ return init7();
74184
73928
  }
74185
73929
  return processor;
74186
73930
  }
@@ -74653,6 +74397,264 @@ var BUILDER = "builder" /* BUILDER */;
74653
74397
  var CREATOR = "creator" /* CREATOR */;
74654
74398
  var GLOBAL_BUILDER = "globalBuilder" /* GLOBAL_BUILDER */;
74655
74399
 
74400
+ // src/features/index.ts
74401
+ var features_exports = {};
74402
+ __export(features_exports, {
74403
+ Flag: () => Flag,
74404
+ FlagSet: () => FlagSet,
74405
+ flags: () => flags,
74406
+ init: () => init8,
74407
+ parseEnvFlags: () => parseEnvFlags,
74408
+ shutdown: () => shutdown5,
74409
+ testutils: () => utils_exports6
74410
+ });
74411
+
74412
+ // src/features/features.ts
74413
+ var crypto = __toESM(require("crypto"));
74414
+ var import_posthog_node2 = require("posthog-node");
74415
+ var import_dd_trace3 = __toESM(require("dd-trace"));
74416
+ var posthog;
74417
+ function init8(opts) {
74418
+ if (environment_default.POSTHOG_TOKEN && environment_default.POSTHOG_API_HOST && !environment_default.SELF_HOSTED && environment_default.POSTHOG_FEATURE_FLAGS_ENABLED) {
74419
+ console.log("initializing posthog client...");
74420
+ posthog = new import_posthog_node2.PostHog(environment_default.POSTHOG_TOKEN, {
74421
+ host: environment_default.POSTHOG_API_HOST,
74422
+ personalApiKey: environment_default.POSTHOG_PERSONAL_TOKEN,
74423
+ featureFlagsPollingInterval: Duration.fromMinutes(3).toMs(),
74424
+ ...opts
74425
+ });
74426
+ } else {
74427
+ console.log("posthog disabled");
74428
+ }
74429
+ }
74430
+ function shutdown5() {
74431
+ posthog?.shutdown();
74432
+ }
74433
+ var Flag = class {
74434
+ constructor(defaultValue) {
74435
+ this.defaultValue = defaultValue;
74436
+ }
74437
+ static boolean(defaultValue) {
74438
+ return new BooleanFlag(defaultValue);
74439
+ }
74440
+ static string(defaultValue) {
74441
+ return new StringFlag(defaultValue);
74442
+ }
74443
+ static number(defaultValue) {
74444
+ return new NumberFlag(defaultValue);
74445
+ }
74446
+ };
74447
+ var BooleanFlag = class extends Flag {
74448
+ parse(value) {
74449
+ if (typeof value === "string") {
74450
+ return ["true", "t", "1"].includes(value.toLowerCase());
74451
+ }
74452
+ if (typeof value === "boolean") {
74453
+ return value;
74454
+ }
74455
+ throw new Error(`could not parse value "${value}" as boolean`);
74456
+ }
74457
+ };
74458
+ var StringFlag = class extends Flag {
74459
+ parse(value) {
74460
+ if (typeof value === "string") {
74461
+ return value;
74462
+ }
74463
+ throw new Error(`could not parse value "${value}" as string`);
74464
+ }
74465
+ };
74466
+ var NumberFlag = class extends Flag {
74467
+ parse(value) {
74468
+ if (typeof value === "number") {
74469
+ return value;
74470
+ }
74471
+ if (typeof value === "string") {
74472
+ const parsed = parseFloat(value);
74473
+ if (!isNaN(parsed)) {
74474
+ return parsed;
74475
+ }
74476
+ }
74477
+ throw new Error(`could not parse value "${value}" as number`);
74478
+ }
74479
+ };
74480
+ function parseEnvFlags(flags2) {
74481
+ const split = flags2.split(",").map((x) => x.split(":"));
74482
+ const result = [];
74483
+ for (const [tenantId, ...features] of split) {
74484
+ for (let feature of features) {
74485
+ let value = true;
74486
+ if (feature.startsWith("!")) {
74487
+ feature = feature.slice(1);
74488
+ value = false;
74489
+ }
74490
+ result.push({ tenantId, key: feature, value });
74491
+ }
74492
+ }
74493
+ return result;
74494
+ }
74495
+ var FlagSet = class {
74496
+ constructor(flagSchema) {
74497
+ this.flagSchema = flagSchema;
74498
+ this.setId = crypto.randomUUID();
74499
+ }
74500
+ defaults() {
74501
+ return Object.keys(this.flagSchema).reduce((acc, key) => {
74502
+ const typedKey = key;
74503
+ acc[typedKey] = this.flagSchema[key].defaultValue;
74504
+ return acc;
74505
+ }, {});
74506
+ }
74507
+ isFlagName(name) {
74508
+ return this.flagSchema[name] !== void 0;
74509
+ }
74510
+ async get(key) {
74511
+ const flags2 = await this.fetch();
74512
+ return flags2[key];
74513
+ }
74514
+ async isEnabled(key) {
74515
+ const flags2 = await this.fetch();
74516
+ return flags2[key];
74517
+ }
74518
+ async fetch() {
74519
+ return await import_dd_trace3.default.trace("features.fetch", async (span) => {
74520
+ const cachedFlags = getFeatureFlags(this.setId);
74521
+ if (cachedFlags) {
74522
+ span?.addTags({ fromCache: true });
74523
+ return cachedFlags;
74524
+ }
74525
+ const tags = {};
74526
+ const flagValues = this.defaults();
74527
+ const currentTenantId = getTenantId();
74528
+ const specificallySetFalse = /* @__PURE__ */ new Set();
74529
+ for (const { tenantId: tenantId2, key, value } of parseEnvFlags(
74530
+ environment_default.TENANT_FEATURE_FLAGS || ""
74531
+ )) {
74532
+ if (!tenantId2 || tenantId2 !== "*" && tenantId2 !== currentTenantId) {
74533
+ continue;
74534
+ }
74535
+ tags[`readFromEnvironmentVars`] = true;
74536
+ if (value === false) {
74537
+ specificallySetFalse.add(key);
74538
+ }
74539
+ if (!this.isFlagName(key)) {
74540
+ continue;
74541
+ }
74542
+ if (typeof flagValues[key] !== "boolean") {
74543
+ throw new Error(`Feature: ${key} is not a boolean`);
74544
+ }
74545
+ flagValues[key] = value;
74546
+ tags[`flags.${key}.source`] = "environment";
74547
+ }
74548
+ const identity = getIdentity();
74549
+ let userId = identity?._id;
74550
+ if (!userId) {
74551
+ const ip = getIP();
74552
+ if (ip) {
74553
+ userId = crypto.createHash("sha512").update(ip).digest("hex");
74554
+ }
74555
+ }
74556
+ let tenantId = identity?.tenantId;
74557
+ if (!tenantId) {
74558
+ tenantId = currentTenantId;
74559
+ }
74560
+ tags[`identity.type`] = identity?.type;
74561
+ tags[`identity._id`] = identity?._id;
74562
+ tags[`tenantId`] = tenantId;
74563
+ tags[`userId`] = userId;
74564
+ if (posthog && userId) {
74565
+ tags[`readFromPostHog`] = true;
74566
+ const personProperties = { tenantId };
74567
+ const posthogFlags = await posthog.getAllFlagsAndPayloads(userId, {
74568
+ personProperties
74569
+ });
74570
+ for (const [name, value] of Object.entries(posthogFlags.featureFlags)) {
74571
+ if (!this.isFlagName(name)) {
74572
+ console.warn(`Unexpected posthog flag "${name}": ${value}`);
74573
+ continue;
74574
+ }
74575
+ if (flagValues[name] === true || specificallySetFalse.has(name)) {
74576
+ continue;
74577
+ }
74578
+ const payload = posthogFlags.featureFlagPayloads?.[name];
74579
+ const flag = this.flagSchema[name];
74580
+ try {
74581
+ flagValues[name] = flag.parse(payload || value);
74582
+ tags[`flags.${name}.source`] = "posthog";
74583
+ } catch (err) {
74584
+ console.warn(`Error parsing posthog flag "${name}": ${value}`, err);
74585
+ }
74586
+ }
74587
+ }
74588
+ setFeatureFlags(this.setId, flagValues);
74589
+ for (const [key, value] of Object.entries(flagValues)) {
74590
+ tags[`flags.${key}.value`] = value;
74591
+ }
74592
+ span?.addTags(tags);
74593
+ return flagValues;
74594
+ });
74595
+ }
74596
+ };
74597
+ var flags = new FlagSet({
74598
+ ["DEFAULT_VALUES" /* DEFAULT_VALUES */]: Flag.boolean(true),
74599
+ ["AUTOMATION_BRANCHING" /* AUTOMATION_BRANCHING */]: Flag.boolean(true),
74600
+ ["AI_CUSTOM_CONFIGS" /* AI_CUSTOM_CONFIGS */]: Flag.boolean(true),
74601
+ ["BUDIBASE_AI" /* BUDIBASE_AI */]: Flag.boolean(true)
74602
+ });
74603
+
74604
+ // src/features/tests/utils.ts
74605
+ var utils_exports6 = {};
74606
+ __export(utils_exports6, {
74607
+ setFeatureFlags: () => setFeatureFlags2,
74608
+ withFeatureFlags: () => withFeatureFlags
74609
+ });
74610
+ function getCurrentFlags() {
74611
+ const result = {};
74612
+ for (const { tenantId, key, value } of parseEnvFlags(
74613
+ process.env.TENANT_FEATURE_FLAGS || ""
74614
+ )) {
74615
+ const tenantFlags = result[tenantId] || {};
74616
+ if (tenantFlags[key] === false) {
74617
+ continue;
74618
+ }
74619
+ tenantFlags[key] = value;
74620
+ result[tenantId] = tenantFlags;
74621
+ }
74622
+ return result;
74623
+ }
74624
+ function buildFlagString(flags2) {
74625
+ const parts = [];
74626
+ for (const [tenantId, tenantFlags] of Object.entries(flags2)) {
74627
+ for (const [key, value] of Object.entries(tenantFlags)) {
74628
+ if (value === false) {
74629
+ parts.push(`${tenantId}:!${key}`);
74630
+ } else {
74631
+ parts.push(`${tenantId}:${key}`);
74632
+ }
74633
+ }
74634
+ }
74635
+ return parts.join(",");
74636
+ }
74637
+ function setFeatureFlags2(tenantId, flags2) {
74638
+ const current = getCurrentFlags();
74639
+ for (const [key, value] of Object.entries(flags2)) {
74640
+ const tenantFlags = current[tenantId] || {};
74641
+ tenantFlags[key] = value;
74642
+ current[tenantId] = tenantFlags;
74643
+ }
74644
+ const flagString = buildFlagString(current);
74645
+ return setEnv({ TENANT_FEATURE_FLAGS: flagString });
74646
+ }
74647
+ function withFeatureFlags(tenantId, flags2, f) {
74648
+ const cleanup3 = setFeatureFlags2(tenantId, flags2);
74649
+ const result = f();
74650
+ if (result instanceof Promise) {
74651
+ return result.finally(cleanup3);
74652
+ } else {
74653
+ cleanup3();
74654
+ return result;
74655
+ }
74656
+ }
74657
+
74656
74658
  // src/auth/index.ts
74657
74659
  var auth_exports = {};
74658
74660
  __export(auth_exports, {
@@ -75106,7 +75108,7 @@ __export(encryption_exports, {
75106
75108
  encryptFile: () => encryptFile,
75107
75109
  getSecret: () => getSecret
75108
75110
  });
75109
- var import_crypto = __toESM(require("crypto"));
75111
+ var import_crypto2 = __toESM(require("crypto"));
75110
75112
  var import_fs5 = __toESM(require("fs"));
75111
75113
  var import_zlib2 = __toESM(require("zlib"));
75112
75114
  var import_path4 = require("path");
@@ -75140,12 +75142,12 @@ function getSecret(secretOption) {
75140
75142
  return secret;
75141
75143
  }
75142
75144
  function stretchString(secret, salt) {
75143
- return import_crypto.default.pbkdf2Sync(secret, salt, ITERATIONS, STRETCH_LENGTH, "sha512");
75145
+ return import_crypto2.default.pbkdf2Sync(secret, salt, ITERATIONS, STRETCH_LENGTH, "sha512");
75144
75146
  }
75145
75147
  function encrypt(input, secretOption = "api" /* API */) {
75146
- const salt = import_crypto.default.randomBytes(SALT_LENGTH);
75148
+ const salt = import_crypto2.default.randomBytes(SALT_LENGTH);
75147
75149
  const stretched = stretchString(getSecret(secretOption), salt);
75148
- const cipher = import_crypto.default.createCipheriv(ALGO, stretched, salt);
75150
+ const cipher = import_crypto2.default.createCipheriv(ALGO, stretched, salt);
75149
75151
  const base2 = cipher.update(input);
75150
75152
  const final = cipher.final();
75151
75153
  const encrypted = Buffer.concat([base2, final]).toString("hex");
@@ -75155,7 +75157,7 @@ function decrypt(input, secretOption = "api" /* API */) {
75155
75157
  const [salt, encrypted] = input.split(SEPARATOR3);
75156
75158
  const saltBuffer = Buffer.from(salt, "hex");
75157
75159
  const stretched = stretchString(getSecret(secretOption), saltBuffer);
75158
- const decipher = import_crypto.default.createDecipheriv(ALGO, stretched, saltBuffer);
75160
+ const decipher = import_crypto2.default.createDecipheriv(ALGO, stretched, saltBuffer);
75159
75161
  const base2 = decipher.update(Buffer.from(encrypted, "hex"));
75160
75162
  const final = decipher.final();
75161
75163
  return Buffer.concat([base2, final]).toString();
@@ -75168,10 +75170,10 @@ async function encryptFile({ dir, filename }, secret) {
75168
75170
  }
75169
75171
  const inputFile = import_fs5.default.createReadStream(filePath);
75170
75172
  const outputFile = import_fs5.default.createWriteStream((0, import_path4.join)(dir, outputFileName));
75171
- const salt = import_crypto.default.randomBytes(SALT_LENGTH);
75172
- const iv = import_crypto.default.randomBytes(IV_LENGTH);
75173
+ const salt = import_crypto2.default.randomBytes(SALT_LENGTH);
75174
+ const iv = import_crypto2.default.randomBytes(IV_LENGTH);
75173
75175
  const stretched = stretchString(secret, salt);
75174
- const cipher = import_crypto.default.createCipheriv(ALGO, stretched, iv);
75176
+ const cipher = import_crypto2.default.createCipheriv(ALGO, stretched, iv);
75175
75177
  outputFile.write(salt);
75176
75178
  outputFile.write(iv);
75177
75179
  inputFile.pipe(import_zlib2.default.createGzip()).pipe(cipher).pipe(outputFile);
@@ -75201,7 +75203,7 @@ async function decryptFile(inputPath, outputPath, secret) {
75201
75203
  });
75202
75204
  const outputFile = import_fs5.default.createWriteStream(outputPath);
75203
75205
  const stretched = stretchString(secret, salt);
75204
- const decipher = import_crypto.default.createDecipheriv(ALGO, stretched, iv);
75206
+ const decipher = import_crypto2.default.createDecipheriv(ALGO, stretched, iv);
75205
75207
  const unzip = import_zlib2.default.createGunzip();
75206
75208
  inputFile.pipe(decipher).pipe(unzip).pipe(outputFile);
75207
75209
  return new Promise((res, rej) => {
@@ -75645,7 +75647,7 @@ function querystringToBody_default(ctx, next) {
75645
75647
  }
75646
75648
 
75647
75649
  // src/middleware/contentSecurityPolicy.ts
75648
- var import_crypto2 = __toESM(require("crypto"));
75650
+ var import_crypto3 = __toESM(require("crypto"));
75649
75651
  var CSP_DIRECTIVES = {
75650
75652
  "default-src": ["'self'"],
75651
75653
  "script-src": [
@@ -75733,15 +75735,12 @@ var CSP_DIRECTIVES = {
75733
75735
  };
75734
75736
  async function contentSecurityPolicy(ctx, next) {
75735
75737
  try {
75736
- const nonce = import_crypto2.default.randomBytes(16).toString("base64");
75738
+ const nonce = import_crypto3.default.randomBytes(16).toString("base64");
75737
75739
  const directives = { ...CSP_DIRECTIVES };
75738
75740
  directives["script-src"] = [
75739
75741
  ...CSP_DIRECTIVES["script-src"],
75740
75742
  `'nonce-${nonce}'`
75741
75743
  ];
75742
- if (!environment_default.DISABLE_CSP_UNSAFE_INLINE_SCRIPTS) {
75743
- directives["script-src"].push("'unsafe-inline'");
75744
- }
75745
75744
  ctx.state.nonce = nonce;
75746
75745
  const cspHeader = Object.entries(directives).map(([key, sources]) => `${key} ${sources.join(" ")}`).join("; ");
75747
75746
  ctx.set("Content-Security-Policy", cspHeader);
@@ -76196,7 +76195,7 @@ var DocumentUpdateProcessor = class {
76196
76195
  }
76197
76196
  }
76198
76197
  shutdown() {
76199
- return shutdown4();
76198
+ return shutdown3();
76200
76199
  }
76201
76200
  };
76202
76201
 
@@ -76205,7 +76204,7 @@ var processingPromise;
76205
76204
  var documentProcessor;
76206
76205
  function init9(processors2) {
76207
76206
  if (!asyncEventQueue) {
76208
- init6();
76207
+ init5();
76209
76208
  }
76210
76209
  if (!documentProcessor) {
76211
76210
  documentProcessor = new DocumentUpdateProcessor(processors2);