/**
 * This file is part of the NocoBase (R) project.
 * Copyright (c) 2020-2024 NocoBase Co., Ltd.
 * Authors: NocoBase Team.
 *
 * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
 * For more information, please refer to: https://www.nocobase.com/agreement.
 */

var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var contexts_exports = {};
__export(contexts_exports, {
  GlobalContext: () => GlobalContext,
  HttpRequestContext: () => HttpRequestContext,
  ServerBaseContext: () => ServerBaseContext
});
module.exports = __toCommonJS(contexts_exports);
var import_lodash = __toESM(require("lodash"));
const BLOCKED_SANDBOX_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor", "then"]);
function isBlockedSandboxKey(key) {
  return BLOCKED_SANDBOX_KEYS.has(key);
}
class ServerBaseContext {
  _props = {};
  _methods = {};
  _cache = {};
  _delegates = [];
  _proxy;
  constructor() {
    return this.createProxy();
  }
  _getOwn(key, current) {
    const opt = this._props[key];
    if (!opt) return void 0;
    if (Object.prototype.hasOwnProperty.call(opt, "value")) return opt.value;
    if (opt.get) {
      if (opt.cache === false) return opt.get(current);
      if (key in this._cache) return this._cache[key];
      const p = opt.get(current);
      this._cache[key] = p;
      return p;
    }
    return void 0;
  }
  /**
   * 定义一个可枚举属性。
   * - value：固定值
   * - get：惰性 getter（默认带缓存）
   * - once：已存在时忽略重复定义
   */
  defineProperty(key, options) {
    var _a;
    if (this._props[key] && ((_a = this._props[key]) == null ? void 0 : _a.once)) return;
    this._props[key] = options;
    delete this._cache[key];
    Object.defineProperty(this, key, {
      configurable: true,
      enumerable: true,
      get: () => this._getOwn(key, this.createProxy())
    });
  }
  /** 定义一个方法（不可枚举、不可写），访问时会自动绑定到对应实例 */
  defineMethod(name, fn) {
    this._methods[name] = fn;
    Object.defineProperty(this, name, {
      configurable: true,
      enumerable: false,
      writable: false,
      value: fn
      // bind at proxy access to keep delegate binding consistent
    });
  }
  /**
   * 委托到另一个 ServerBaseContext：
   * - 访问属性/方法找不到时，会回退到被委托者进行解析
   */
  delegate(ctx) {
    if (!(ctx instanceof ServerBaseContext)) {
      throw new Error("Delegate must be a ServerBaseContext");
    }
    if (!this._delegates.includes(ctx)) this._delegates.unshift(ctx);
  }
  /** 清空所有委托 */
  clearDelegates() {
    this._delegates = [];
  }
  getSandboxKeys() {
    const keys = /* @__PURE__ */ new Set();
    for (const key of Object.keys(this._props)) {
      if (!isBlockedSandboxKey(key)) keys.add(key);
    }
    for (const key of Object.keys(this._methods)) {
      if (!isBlockedSandboxKey(key)) keys.add(key);
    }
    for (const d of this._delegates) {
      for (const key of d.getSandboxKeys()) {
        if (!isBlockedSandboxKey(key)) keys.add(key);
      }
    }
    return Array.from(keys);
  }
  getSandboxValue(key, current = this.createProxy()) {
    if (isBlockedSandboxKey(key)) return void 0;
    if (Object.prototype.hasOwnProperty.call(this._props, key)) {
      return this._getOwn(key, current);
    }
    if (Object.prototype.hasOwnProperty.call(this._methods, key)) {
      const fn = this._methods[key];
      return typeof fn === "function" ? fn.bind(this) : fn;
    }
    for (const d of this._delegates) {
      if (!d.getSandboxKeys().includes(key)) continue;
      return d.getSandboxValue(key, current);
    }
    return void 0;
  }
  /** 创建并返回代理对象（同一实例下保持稳定引用） */
  createProxy() {
    if (this._proxy) return this._proxy;
    this._proxy = new Proxy(this, {
      get: (target, key, receiver) => {
        var _a;
        if (typeof key !== "string") return Reflect.get(target, key, receiver);
        if (Reflect.has(target, key)) {
          const v = Reflect.get(target, key, receiver);
          return typeof v === "function" ? v.bind(target) : v;
        }
        if (Object.prototype.hasOwnProperty.call(target._props, key)) {
          return target._getOwn(key, this.createProxy());
        }
        if (Object.prototype.hasOwnProperty.call(target._methods, key)) {
          const fn = target._methods[key];
          return typeof fn === "function" ? fn.bind(target) : fn;
        }
        for (const d of target._delegates) {
          const candidate = (_a = d._getOwn) == null ? void 0 : _a.call(d, key, this.createProxy());
          if (typeof candidate !== "undefined") return candidate;
          if (Object.prototype.hasOwnProperty.call(d._methods || {}, key)) {
            const fn = d._methods[key];
            return typeof fn === "function" ? fn.bind(d) : fn;
          }
        }
        return void 0;
      },
      has: (target, key) => {
        if (typeof key !== "string") return Reflect.has(target, key);
        if (Reflect.has(target, key)) return true;
        if (Object.prototype.hasOwnProperty.call(target._props, key)) return true;
        if (Object.prototype.hasOwnProperty.call(target._methods, key)) return true;
        return target._delegates.some(
          (d) => Object.prototype.hasOwnProperty.call(d._props, key) || Object.prototype.hasOwnProperty.call(d._methods, key)
        );
      }
    });
    return this._proxy;
  }
}
class GlobalContext extends ServerBaseContext {
  constructor(env) {
    super();
    this.defineProperty("now", { get: () => (/* @__PURE__ */ new Date()).toISOString(), cache: false });
    this.defineProperty("timestamp", { get: () => Date.now(), cache: false });
    if (env) this.defineProperty("env", { value: filterEnv(env) });
  }
}
class HttpRequestContext extends ServerBaseContext {
  constructor(koaCtx) {
    var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
    super();
    this.koaCtx = koaCtx;
    this.defineProperty("user", { get: async () => {
      var _a2, _b2;
      return (_b2 = (_a2 = this.koaCtx) == null ? void 0 : _a2.auth) == null ? void 0 : _b2.user;
    }, cache: true });
    this.defineProperty("roleName", { value: (_b = (_a = this.koaCtx) == null ? void 0 : _a.auth) == null ? void 0 : _b.role });
    this.defineProperty("locale", { value: (_d = (_c = this.koaCtx) == null ? void 0 : _c.getCurrentLocale) == null ? void 0 : _d.call(_c) });
    this.defineProperty("ip", { value: ((_f = (_e = this.koaCtx) == null ? void 0 : _e.state) == null ? void 0 : _f.clientIp) || ((_h = (_g = this.koaCtx) == null ? void 0 : _g.request) == null ? void 0 : _h.ip) });
    this.defineProperty("headers", { value: (_i = this.koaCtx) == null ? void 0 : _i.headers });
    this.defineProperty("query", { value: (_k = (_j = this.koaCtx) == null ? void 0 : _j.request) == null ? void 0 : _k.query });
    this.defineProperty("params", { value: import_lodash.default.get(this.koaCtx, "action.params") });
  }
}
const DEFAULT_ENV_PREFIXES = ["PUBLIC_", "NEXT_PUBLIC_", "NCB_PUBLIC_"];
function filterEnv(env, allowedPrefixes = DEFAULT_ENV_PREFIXES) {
  try {
    const out = {};
    for (const [k, v] of Object.entries(env || {})) {
      if (allowedPrefixes.some((p) => k.startsWith(p))) {
        out[k] = v;
      }
    }
    return out;
  } catch (_2) {
    return {};
  }
}
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  GlobalContext,
  HttpRequestContext,
  ServerBaseContext
});
