@forklaunch/core 1.6.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -175,15 +175,48 @@ var _tenantContext = new AsyncLocalStorage();
175
175
  function registerEncryptor(encryptor) {
176
176
  _encryptor = encryptor;
177
177
  }
178
+ var EmptyTenantError = class extends Error {
179
+ constructor(api) {
180
+ super(
181
+ `${api}: '' is not a tenant id. It used to mean "global", which made a deliberate global row indistinguishable from a tenant nobody resolved. Bind an explicit constant (for example '_internal') for rows that genuinely belong to no organization.`
182
+ );
183
+ this.name = "EmptyTenantError";
184
+ }
185
+ };
186
+ var UnboundTenantError = class extends Error {
187
+ constructor(operation) {
188
+ super(
189
+ `Cannot ${operation} an encrypted column with no tenant bound. Wrap the work in withEncryptionContext(tenantId, fn), or take the entity manager from a factory that calls wrapEmWithTenantContext. A raw em.fork() (or wrap(entity).__em) escapes the tenant proxy.`
190
+ );
191
+ this.name = "UnboundTenantError";
192
+ }
193
+ };
194
+ function assertBindableTenantId(tenantId, api) {
195
+ if (tenantId === "") {
196
+ throw new EmptyTenantError(api);
197
+ }
198
+ }
178
199
  function setEncryptionTenantId(tenantId) {
200
+ assertBindableTenantId(tenantId, "setEncryptionTenantId");
179
201
  _tenantContext.enterWith({ tenantId });
180
202
  }
181
203
  function withEncryptionContext(tenantId, fn) {
204
+ assertBindableTenantId(tenantId, "withEncryptionContext");
182
205
  return _tenantContext.run({ tenantId }, fn);
183
206
  }
184
207
  function getCurrentTenantId() {
185
208
  return _tenantContext.getStore()?.tenantId ?? "";
186
209
  }
210
+ function getBoundTenantId() {
211
+ return _tenantContext.getStore()?.tenantId;
212
+ }
213
+ function requireBoundTenantId(operation) {
214
+ const tenantId = _tenantContext.getStore()?.tenantId;
215
+ if (tenantId === void 0 || tenantId === "") {
216
+ throw new UnboundTenantError(operation);
217
+ }
218
+ return tenantId;
219
+ }
187
220
  function resolveTypeInstance(type) {
188
221
  if (type instanceof Type) return type;
189
222
  if (typeof type === "function") {
@@ -257,7 +290,7 @@ var EncryptedType = class extends Type {
257
290
  return value;
258
291
  }
259
292
  const serialized = this.serialize(value);
260
- return _encryptor.encrypt(serialized, getCurrentTenantId()) ?? serialized;
293
+ return _encryptor.encrypt(serialized, requireBoundTenantId("write")) ?? serialized;
261
294
  }
262
295
  convertToJSValue(value, _platform) {
263
296
  if (value === null || value === void 0) return null;
@@ -271,7 +304,7 @@ var EncryptedType = class extends Type {
271
304
  );
272
305
  }
273
306
  let decrypted;
274
- const tenantId = getCurrentTenantId();
307
+ const tenantId = requireBoundTenantId("read");
275
308
  try {
276
309
  decrypted = _encryptor.decrypt(value, tenantId);
277
310
  } catch (err) {
@@ -1197,9 +1230,8 @@ function wrapEmWithTenantContext(em, tenantId) {
1197
1230
  if (tenantId === void 0) {
1198
1231
  return em;
1199
1232
  }
1200
- if (tenantId) {
1201
- em.setFilterParams("tenant", { tenantId });
1202
- }
1233
+ assertBindableTenantId(tenantId, "wrapEmWithTenantContext");
1234
+ em.setFilterParams("tenant", { tenantId });
1203
1235
  const proxy = new Proxy(em, {
1204
1236
  get(target, prop, receiver) {
1205
1237
  const value = Reflect.get(target, prop, receiver);
@@ -1211,23 +1243,14 @@ function wrapEmWithTenantContext(em, tenantId) {
1211
1243
  tenantId,
1212
1244
  () => value.apply(target, args)
1213
1245
  );
1214
- return rebind(result, target, proxy, tenantId);
1246
+ return rebind(result, target, proxy);
1215
1247
  };
1216
1248
  }
1217
1249
  });
1218
1250
  return proxy;
1219
1251
  }
1220
- function rebind(result, target, proxy, tenantId) {
1221
- if (result === target) {
1222
- return proxy;
1223
- }
1224
- if (isEntityManager(result) && result !== proxy) {
1225
- return wrapEmWithTenantContext(result, tenantId);
1226
- }
1227
- return result;
1228
- }
1229
- function isEntityManager(value) {
1230
- return typeof value === "object" && value !== null && "fork" in value && typeof value.fork === "function" && "flush" in value && typeof value.flush === "function" && "persist" in value && typeof value.persist === "function";
1252
+ function rebind(result, target, proxy) {
1253
+ return result === target ? proxy : result;
1231
1254
  }
1232
1255
  export {
1233
1256
  ComplianceLevel,
@@ -1235,6 +1258,7 @@ export {
1235
1258
  ENCRYPTED_PREFIXES2 as ENCRYPTED_PREFIXES,
1236
1259
  ENCRYPTION_FORMAT_ENV,
1237
1260
  ENCRYPTION_KEY_ENV,
1261
+ EmptyTenantError,
1238
1262
  EncryptedType,
1239
1263
  EncryptionRequiredError,
1240
1264
  FieldEncryptor,
@@ -1245,7 +1269,9 @@ export {
1245
1269
  RetentionDuration,
1246
1270
  RlsEventSubscriber,
1247
1271
  TENANT_FILTER_NAME,
1272
+ UnboundTenantError,
1248
1273
  asEncryptionSafe,
1274
+ assertBindableTenantId,
1249
1275
  classifyEncryptedValue,
1250
1276
  collectFallbackTenantIds,
1251
1277
  countValuesByKeyId,
@@ -1258,6 +1284,7 @@ export {
1258
1284
  fp,
1259
1285
  getAllRetentionPolicies,
1260
1286
  getAllUserIdFields,
1287
+ getBoundTenantId,
1261
1288
  getComplianceMetadata,
1262
1289
  getCurrentTenantId,
1263
1290
  getEntityComplianceFields,