@infuro/cms-core 1.0.16 → 1.0.18

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.
Files changed (46) hide show
  1. package/README.md +739 -724
  2. package/dist/admin.cjs +1 -1
  3. package/dist/admin.cjs.map +1 -1
  4. package/dist/admin.js +1 -1
  5. package/dist/admin.js.map +1 -1
  6. package/dist/api.cjs +132 -57
  7. package/dist/api.cjs.map +1 -1
  8. package/dist/api.d.cts +1 -1
  9. package/dist/api.d.ts +1 -1
  10. package/dist/api.js +132 -57
  11. package/dist/api.js.map +1 -1
  12. package/dist/auth.cjs.map +1 -1
  13. package/dist/auth.js.map +1 -1
  14. package/dist/cli.cjs +21 -6
  15. package/dist/cli.cjs.map +1 -1
  16. package/dist/cli.js +21 -6
  17. package/dist/cli.js.map +1 -1
  18. package/dist/hooks.cjs.map +1 -1
  19. package/dist/hooks.js.map +1 -1
  20. package/dist/{index-h42MoUNq.d.cts → index-D2C1O9b4.d.cts} +8 -1
  21. package/dist/{index-C85X7cc7.d.ts → index-GMn7-9PX.d.ts} +8 -1
  22. package/dist/index.cjs +135 -57
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +2 -2
  25. package/dist/index.d.ts +2 -2
  26. package/dist/index.js +135 -57
  27. package/dist/index.js.map +1 -1
  28. package/dist/migrations/1772178563554-InitialSchema.ts +304 -304
  29. package/dist/migrations/1772178563555-ChatAndKnowledgeBase.ts +55 -55
  30. package/dist/migrations/1772178563556-KnowledgeBaseVector.ts +16 -16
  31. package/dist/migrations/1774300000000-RbacSeedGroupsAndPermissionUnique.ts +24 -24
  32. package/dist/migrations/1774300000001-SeedAdministratorUsersPermission.ts +35 -35
  33. package/dist/migrations/1774400000000-CustomerAdminAccessContactUser.ts +37 -37
  34. package/dist/migrations/1774400000001-StorefrontCartWishlist.ts +100 -100
  35. package/dist/migrations/1774400000002-WishlistGuestId.ts +29 -29
  36. package/dist/migrations/1774500000000-ProductCollectionHsn.ts +15 -15
  37. package/dist/migrations/1774600000000-OrderKindParentOrderNumber.ts +36 -36
  38. package/dist/migrations/1774800000000-OtpChallengesUserPhone.ts +41 -41
  39. package/dist/migrations/1774900000000-MessageTemplates.ts +39 -39
  40. package/dist/migrations/1775000000000-ProductUomTypeOrderItemSnapshots.ts +29 -29
  41. package/dist/migrations/1775200000000-MediaDriveFolders.ts +38 -38
  42. package/dist/migrations/README.md +3 -3
  43. package/dist/theme.cjs.map +1 -1
  44. package/dist/theme.js.map +1 -1
  45. package/package.json +13 -6
  46. package/src/admin/admin.css +72 -72
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-h42MoUNq.cjs';
2
- export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-h42MoUNq.cjs';
1
+ import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-D2C1O9b4.cjs';
2
+ export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-D2C1O9b4.cjs';
3
3
  import { ClassValue } from 'clsx';
4
4
  import * as typeorm from 'typeorm';
5
5
  import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-C85X7cc7.js';
2
- export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-C85X7cc7.js';
1
+ import { C as CompanyDetails, T as TemplateContext, E as EmailTemplateResult, a as EmailTemplateName, O as OrderPlacedLineItem, S as StorageService, b as EntityMap$2 } from './index-GMn7-9PX.js';
2
+ export { A as AnalyticsHandlerConfig, c as AuthHandlersConfig, B as BlogBySlugConfig, d as ChangePasswordConfig, e as CmsApiHandlerConfig, f as CmsGetter, g as CrudHandlerOptions, D as DashboardStatsConfig, h as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, i as FormBySlugConfig, G as GetPublicSettingsGroupConfig, j as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, k as SetPasswordConfig, l as SettingsApiConfig, m as SocialLinkItem, n as StorefrontApiConfig, o as StorefrontOtpFlags, U as UploadHandlerConfig, p as UserAuthApiConfig, q as UserAvatarConfig, r as UserProfileConfig, s as UsersApiConfig, t as createAnalyticsHandlers, u as createBlogBySlugHandler, v as createChangePasswordHandler, w as createCmsApiHandler, x as createCrudByIdHandler, y as createCrudHandler, z as createDashboardStatsHandler, H as createEcommerceAnalyticsHandler, J as createForgotPasswordHandler, K as createFormBySlugHandler, L as createInviteAcceptHandler, M as createMediaZipExtractHandler, N as createSetPasswordHandler, P as createSettingsApiHandlers, Q as createStorefrontApiHandler, R as createUploadHandler, V as createUserAuthApiRouter, W as createUserAvatarHandler, X as createUserProfileHandler, Y as createUsersApiHandlers, Z as getCompanyDetailsFromSettings, _ as getPublicSettingsGroup, $ as mergeEmailLayoutCompanyDetails } from './index-GMn7-9PX.js';
3
3
  import { ClassValue } from 'clsx';
4
4
  import * as typeorm from 'typeorm';
5
5
  import { DataSource, EntityTarget, ObjectLiteral } from 'typeorm';
package/dist/index.js CHANGED
@@ -4371,7 +4371,7 @@ function createFormSubmissionHandler(config) {
4371
4371
  };
4372
4372
  }
4373
4373
  function createUsersApiHandlers(config) {
4374
- const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails } = config;
4374
+ const { dataSource, entityMap, json, requireAuth, requireEntityPermission, baseUrl, getCms, getCompanyDetails, getSessionUser } = config;
4375
4375
  async function trySendInviteEmail(toEmail, inviteLink, inviteeName) {
4376
4376
  if (!getCms) return;
4377
4377
  try {
@@ -4407,7 +4407,10 @@ function createUsersApiHandlers(config) {
4407
4407
  const sortField = url.searchParams.get("sortField") || "createdAt";
4408
4408
  const sortOrder = url.searchParams.get("sortOrder") === "desc" ? "DESC" : "ASC";
4409
4409
  const search = url.searchParams.get("search");
4410
- const where = search ? [{ name: ILike(`%${search}%`) }, { email: ILike(`%${search}%`) }] : {};
4410
+ const where = search ? [
4411
+ { name: ILike(`%${search}%`), deleted: false },
4412
+ { email: ILike(`%${search}%`), deleted: false }
4413
+ ] : { deleted: false };
4411
4414
  const [data, total] = await userRepo().findAndCount({
4412
4415
  skip,
4413
4416
  take: limit,
@@ -4472,7 +4475,7 @@ function createUsersApiHandlers(config) {
4472
4475
  }
4473
4476
  try {
4474
4477
  const user = await userRepo().findOne({
4475
- where: { id: parseInt(id, 10) },
4478
+ where: { id: parseInt(id, 10), deleted: false },
4476
4479
  relations: ["group"],
4477
4480
  select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
4478
4481
  });
@@ -4490,11 +4493,14 @@ function createUsersApiHandlers(config) {
4490
4493
  if (pe) return pe;
4491
4494
  }
4492
4495
  try {
4496
+ const uid = parseInt(id, 10);
4497
+ const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
4498
+ if (!existing) return json({ error: "Not found" }, { status: 404 });
4493
4499
  const body = await req.json();
4494
4500
  const { password: _p, ...safe } = body;
4495
- await userRepo().update(parseInt(id, 10), safe);
4501
+ await userRepo().update(uid, safe);
4496
4502
  const updated = await userRepo().findOne({
4497
- where: { id: parseInt(id, 10) },
4503
+ where: { id: uid, deleted: false },
4498
4504
  relations: ["group"],
4499
4505
  select: ["id", "name", "email", "blocked", "createdAt", "updatedAt", "groupId"]
4500
4506
  });
@@ -4511,8 +4517,23 @@ function createUsersApiHandlers(config) {
4511
4517
  if (pe) return pe;
4512
4518
  }
4513
4519
  try {
4514
- const r = await userRepo().delete(parseInt(id, 10));
4515
- if (r.affected === 0) return json({ error: "User not found" }, { status: 404 });
4520
+ const uid = parseInt(id, 10);
4521
+ const existing = await userRepo().findOne({ where: { id: uid, deleted: false } });
4522
+ if (!existing) return json({ error: "User not found" }, { status: 404 });
4523
+ let deletedBy = null;
4524
+ if (getSessionUser) {
4525
+ try {
4526
+ const u = await getSessionUser();
4527
+ if (u?.id) {
4528
+ const n = Number(u.id);
4529
+ if (Number.isFinite(n)) deletedBy = n;
4530
+ }
4531
+ } catch {
4532
+ }
4533
+ }
4534
+ const payload = { deleted: true, deletedAt: /* @__PURE__ */ new Date() };
4535
+ if (deletedBy != null) payload.deletedBy = deletedBy;
4536
+ await userRepo().update(uid, payload);
4516
4537
  return json({ message: "User deleted successfully" });
4517
4538
  } catch {
4518
4539
  return json({ error: "Server Error" }, { status: 500 });
@@ -4526,7 +4547,10 @@ function createUsersApiHandlers(config) {
4526
4547
  if (pe) return pe;
4527
4548
  }
4528
4549
  try {
4529
- const user = await userRepo().findOne({ where: { id: parseInt(id, 10) }, select: ["email", "name"] });
4550
+ const user = await userRepo().findOne({
4551
+ where: { id: parseInt(id, 10), deleted: false },
4552
+ select: ["email", "name"]
4553
+ });
4530
4554
  if (!user) return json({ error: "User not found" }, { status: 404 });
4531
4555
  const emailToken = Buffer.from(user.email).toString("base64");
4532
4556
  const inviteLink = `${baseUrl}/admin/invite?token=${emailToken}`;
@@ -7781,6 +7805,28 @@ function buildSearchWhereClause(repo, search) {
7781
7805
  if (ors.length === 0) return {};
7782
7806
  return ors.length === 1 ? ors[0] : ors;
7783
7807
  }
7808
+ function entityHasSoftDelete(repo) {
7809
+ return repo.metadata.columns.some((c) => c.propertyName === "deleted");
7810
+ }
7811
+ function mergeDeletedFalseWhere(repo, where) {
7812
+ if (!entityHasSoftDelete(repo)) return where;
7813
+ const d = { deleted: false };
7814
+ if (Array.isArray(where)) {
7815
+ if (where.length === 0) return [d];
7816
+ return where.map((w) => ({ ...w, ...d }));
7817
+ }
7818
+ return Object.keys(where).length > 0 ? { ...where, ...d } : d;
7819
+ }
7820
+ function buildSoftDeletePayload(meta, deletedBy) {
7821
+ const payload = { deleted: true };
7822
+ if (meta.columns.some((c) => c.propertyName === "deletedAt")) {
7823
+ payload.deletedAt = /* @__PURE__ */ new Date();
7824
+ }
7825
+ if (deletedBy != null && meta.columns.some((c) => c.propertyName === "deletedBy")) {
7826
+ payload.deletedBy = deletedBy;
7827
+ }
7828
+ return payload;
7829
+ }
7784
7830
  function makeContactErpSync(dataSource, entityMap, getCms) {
7785
7831
  return async function syncContactRowToErp(row) {
7786
7832
  if (!getCms) return;
@@ -7805,10 +7851,11 @@ function createCrudHandler(dataSource, entityMap, options) {
7805
7851
  async function authz(req, resource, action) {
7806
7852
  const authError = await requireAuth(req);
7807
7853
  if (authError) return authError;
7808
- if (reqPerm) {
7809
- const pe = await reqPerm(req, resource, action);
7810
- if (pe) return pe;
7854
+ if (!reqPerm) {
7855
+ return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
7811
7856
  }
7857
+ const pe = await reqPerm(req, resource, action);
7858
+ if (pe) return pe;
7812
7859
  return null;
7813
7860
  }
7814
7861
  return {
@@ -7844,7 +7891,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7844
7891
  return json({ total: 0, page, limit, totalPages: 0, data: [] });
7845
7892
  }
7846
7893
  }
7847
- const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").orderBy(`order.${sortField2}`, sortOrderOrders).skip(skip).take(limit);
7894
+ const qb = repo2.createQueryBuilder("order").leftJoinAndSelect("order.contact", "contact").leftJoinAndSelect("order.items", "items").leftJoinAndSelect("items.product", "product").leftJoinAndSelect("product.collection", "collection").andWhere("order.deleted = :orderDel", { orderDel: false }).orderBy(`order.${sortField2}`, sortOrderOrders).skip(skip).take(limit);
7848
7895
  if (search && typeof search === "string" && search.trim()) {
7849
7896
  const term = `%${search.trim()}%`;
7850
7897
  qb.andWhere(
@@ -7882,7 +7929,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7882
7929
  const dateTo = searchParams.get("dateTo")?.trim();
7883
7930
  const methodFilter = searchParams.get("method")?.trim();
7884
7931
  const orderNumberParam = searchParams.get("orderNumber")?.trim();
7885
- const qb = repo2.createQueryBuilder("payment").leftJoinAndSelect("payment.order", "ord").leftJoinAndSelect("ord.contact", "orderContact").leftJoinAndSelect("payment.contact", "contact").orderBy(`payment.${sortField2}`, sortOrderPayments).skip(skip).take(limit);
7932
+ const qb = repo2.createQueryBuilder("payment").leftJoinAndSelect("payment.order", "ord").leftJoinAndSelect("ord.contact", "orderContact").leftJoinAndSelect("payment.contact", "contact").andWhere("payment.deleted = :payDel", { payDel: false }).orderBy(`payment.${sortField2}`, sortOrderPayments).skip(skip).take(limit);
7886
7933
  if (search && typeof search === "string" && search.trim()) {
7887
7934
  const term = `%${search.trim()}%`;
7888
7935
  qb.andWhere(
@@ -7913,7 +7960,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7913
7960
  const repo2 = dataSource.getRepository(entity);
7914
7961
  const statusFilter = searchParams.get("status")?.trim();
7915
7962
  const inventory = searchParams.get("inventory")?.trim();
7916
- const productWhere = {};
7963
+ const productWhere = { deleted: false };
7917
7964
  if (statusFilter) productWhere.status = statusFilter;
7918
7965
  if (inventory === "in_stock") productWhere.quantity = MoreThan2(0);
7919
7966
  if (inventory === "out_of_stock") productWhere.quantity = 0;
@@ -7936,7 +7983,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7936
7983
  const typeFilter2 = searchParams.get("type")?.trim();
7937
7984
  const orderIdParam = searchParams.get("orderId")?.trim();
7938
7985
  const includeSummary = searchParams.get("includeSummary") === "1";
7939
- const qb = repo2.createQueryBuilder("contact").orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
7986
+ const qb = repo2.createQueryBuilder("contact").andWhere("contact.deleted = :contactDel", { contactDel: false }).orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
7940
7987
  if (search && typeof search === "string" && search.trim()) {
7941
7988
  const term = `%${search.trim()}%`;
7942
7989
  qb.andWhere("(contact.name ILIKE :term OR contact.email ILIKE :term OR contact.phone ILIKE :term)", { term });
@@ -7977,9 +8024,9 @@ function createCrudHandler(dataSource, entityMap, options) {
7977
8024
  if (parentIdParam != null && parentIdParam !== "") {
7978
8025
  const n = Number(parentIdParam);
7979
8026
  if (!Number.isFinite(n)) return json({ error: "Invalid parentId" }, { status: 400 });
7980
- qb.where("m.parentId = :pid", { pid: n });
8027
+ qb.where("m.deleted = :mediaDel AND m.parentId = :pid", { mediaDel: false, pid: n });
7981
8028
  } else {
7982
- qb.where("m.parentId IS NULL");
8029
+ qb.where("m.deleted = :mediaDel AND m.parentId IS NULL", { mediaDel: false });
7983
8030
  }
7984
8031
  if (search && typeof search === "string" && search.trim()) {
7985
8032
  qb.andWhere("m.filename ILIKE :search", { search: `%${search.trim()}%` });
@@ -8023,6 +8070,7 @@ function createCrudHandler(dataSource, entityMap, options) {
8023
8070
  where = extraWhere;
8024
8071
  }
8025
8072
  }
8073
+ where = mergeDeletedFalseWhere(repo, where);
8026
8074
  const [data, total] = await repo.findAndCount({
8027
8075
  skip,
8028
8076
  take: limit,
@@ -8190,15 +8238,16 @@ function createCrudHandler(dataSource, entityMap, options) {
8190
8238
  };
8191
8239
  }
8192
8240
  function createCrudByIdHandler(dataSource, entityMap, options) {
8193
- const { requireAuth, json, requireEntityPermission: reqPerm, getCms } = options;
8241
+ const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId } = options;
8194
8242
  const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
8195
8243
  async function authz(req, resource, action) {
8196
8244
  const authError = await requireAuth(req);
8197
8245
  if (authError) return authError;
8198
- if (reqPerm) {
8199
- const pe = await reqPerm(req, resource, action);
8200
- if (pe) return pe;
8246
+ if (!reqPerm) {
8247
+ return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
8201
8248
  }
8249
+ const pe = await reqPerm(req, resource, action);
8250
+ if (pe) return pe;
8202
8251
  return null;
8203
8252
  }
8204
8253
  return {
@@ -8210,7 +8259,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8210
8259
  const repo = dataSource.getRepository(entity);
8211
8260
  if (resource === "orders") {
8212
8261
  const order = await repo.findOne({
8213
- where: { id: Number(id) },
8262
+ where: { id: Number(id), deleted: false },
8214
8263
  relations: ["contact", "billingAddress", "shippingAddress", "items", "items.product", "items.product.collection", "payments"]
8215
8264
  });
8216
8265
  if (!order) return json({ message: "Not found" }, { status: 404 });
@@ -8222,7 +8271,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8222
8271
  }
8223
8272
  if (resource === "contacts") {
8224
8273
  const contact = await repo.findOne({
8225
- where: { id: Number(id) },
8274
+ where: { id: Number(id), deleted: false },
8226
8275
  relations: ["form_submissions", "form_submissions.form", "orders", "payments", "addresses"]
8227
8276
  });
8228
8277
  if (!contact) return json({ message: "Not found" }, { status: 404 });
@@ -8244,7 +8293,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8244
8293
  }
8245
8294
  if (resource === "payments") {
8246
8295
  const payment = await repo.findOne({
8247
- where: { id: Number(id) },
8296
+ where: { id: Number(id), deleted: false },
8248
8297
  relations: ["order", "order.contact", "contact"]
8249
8298
  });
8250
8299
  if (!payment) return json({ message: "Not found" }, { status: 404 });
@@ -8252,12 +8301,13 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8252
8301
  }
8253
8302
  if (resource === "blogs") {
8254
8303
  const blog = await repo.findOne({
8255
- where: { id: Number(id) },
8304
+ where: { id: Number(id), deleted: false },
8256
8305
  relations: ["category", "seo", "tags"]
8257
8306
  });
8258
8307
  return blog ? json(blog) : json({ message: "Not found" }, { status: 404 });
8259
8308
  }
8260
- const item = await repo.findOne({ where: { id: Number(id) } });
8309
+ const idWhere = entityHasSoftDelete(repo) ? { id: Number(id), deleted: false } : { id: Number(id) };
8310
+ const item = await repo.findOne({ where: idWhere });
8261
8311
  return item ? json(item) : json({ message: "Not found" }, { status: 404 });
8262
8312
  },
8263
8313
  async PUT(req, resource, id) {
@@ -8269,7 +8319,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8269
8319
  const repo = dataSource.getRepository(entity);
8270
8320
  const numericId = Number(id);
8271
8321
  if (resource === "blogs" && rawBody && typeof rawBody === "object" && entityMap.categories && entityMap.seos && entityMap.tags) {
8272
- const existing = await repo.findOne({ where: { id: numericId } });
8322
+ const existing = await repo.findOne({
8323
+ where: { id: numericId, deleted: false }
8324
+ });
8273
8325
  if (!existing) return json({ message: "Not found" }, { status: 404 });
8274
8326
  const updatePayload2 = pickColumnUpdates(repo, rawBody);
8275
8327
  if ("category" in rawBody) {
@@ -8345,6 +8397,12 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8345
8397
  });
8346
8398
  return updated2 ? json(updated2) : json({ message: "Not found" }, { status: 404 });
8347
8399
  }
8400
+ if (entityHasSoftDelete(repo)) {
8401
+ const cur = await repo.findOne({
8402
+ where: { id: numericId, deleted: false }
8403
+ });
8404
+ if (!cur) return json({ message: "Not found" }, { status: 404 });
8405
+ }
8348
8406
  const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
8349
8407
  if (resource === "media") {
8350
8408
  const u = updatePayload;
@@ -8371,7 +8429,24 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8371
8429
  const entity = entityMap[resource];
8372
8430
  if (!entity) return json({ error: "Invalid resource" }, { status: 400 });
8373
8431
  const repo = dataSource.getRepository(entity);
8374
- const result = await repo.delete(Number(id));
8432
+ const numericId = Number(id);
8433
+ if (entityHasSoftDelete(repo)) {
8434
+ const existing = await repo.findOne({
8435
+ where: { id: numericId, deleted: false }
8436
+ });
8437
+ if (!existing) return json({ message: "Not found" }, { status: 404 });
8438
+ let deletedBy = null;
8439
+ if (getDeletedByUserId) {
8440
+ try {
8441
+ deletedBy = await getDeletedByUserId(req);
8442
+ } catch {
8443
+ deletedBy = null;
8444
+ }
8445
+ }
8446
+ await repo.update(numericId, buildSoftDeletePayload(repo.metadata, deletedBy));
8447
+ return json({ message: "Deleted successfully" }, { status: 200 });
8448
+ }
8449
+ const result = await repo.delete(numericId);
8375
8450
  if (result.affected === 0) return json({ message: "Not found" }, { status: 404 });
8376
8451
  return json({ message: "Deleted successfully" }, { status: 200 });
8377
8452
  }
@@ -8799,9 +8874,10 @@ function createCmsApiHandler(config) {
8799
8874
  userProfile,
8800
8875
  settings: settingsConfig,
8801
8876
  chat: chatConfig,
8802
- requireEntityPermission: reqEntityPerm,
8877
+ requireEntityPermission: userRequireEntityPermission,
8803
8878
  getSessionUser
8804
8879
  } = config;
8880
+ const requireEntityPermissionEffective = userRequireEntityPermission ?? (async (_req, entity, action) => config.json({ error: "Forbidden", reason: "entity_rbac_required", entity, action }, { status: 403 }));
8805
8881
  const analytics = analyticsConfig ?? (getCms ? {
8806
8882
  json: config.json,
8807
8883
  requireAuth: async () => null,
@@ -8839,12 +8915,20 @@ function createCmsApiHandler(config) {
8839
8915
  const crudOpts = {
8840
8916
  requireAuth: config.requireAuth,
8841
8917
  json: config.json,
8842
- requireEntityPermission: reqEntityPerm,
8843
- getCms
8918
+ requireEntityPermission: requireEntityPermissionEffective,
8919
+ getCms,
8920
+ ...getSessionUser ? {
8921
+ getDeletedByUserId: async () => {
8922
+ const u = await getSessionUser();
8923
+ if (!u?.id) return null;
8924
+ const n = Number(u.id);
8925
+ return Number.isFinite(n) ? n : null;
8926
+ }
8927
+ } : {}
8844
8928
  };
8845
8929
  const crud = createCrudHandler(dataSource, entityMap, crudOpts);
8846
8930
  const crudById = createCrudByIdHandler(dataSource, entityMap, crudOpts);
8847
- const mergePerm = (c) => !c ? void 0 : reqEntityPerm ? { ...c, requireEntityPermission: reqEntityPerm } : c;
8931
+ const mergePerm = (c) => !c ? void 0 : { ...c, requireEntityPermission: requireEntityPermissionEffective };
8848
8932
  const adminRoles = getSessionUser && createAdminRolesHandlers({
8849
8933
  dataSource,
8850
8934
  entityMap,
@@ -8860,12 +8944,7 @@ function createCmsApiHandler(config) {
8860
8944
  json: config.json,
8861
8945
  requireAuth: config.requireAuth
8862
8946
  }
8863
- ) ?? {
8864
- dataSource,
8865
- entityMap,
8866
- json: config.json,
8867
- requireAuth: config.requireAuth
8868
- };
8947
+ );
8869
8948
  const ecommerceAnalyticsGet = createEcommerceAnalyticsHandler(ecommerceAnalyticsResolved);
8870
8949
  const analyticsHandlers = analytics ? createAnalyticsHandlers(analytics) : null;
8871
8950
  const uploadMerged = upload ? {
@@ -8884,7 +8963,11 @@ function createCmsApiHandler(config) {
8884
8963
  const usersApiMerged = usersApi && getCms ? {
8885
8964
  ...usersApi,
8886
8965
  getCms: usersApi.getCms ?? getCms,
8887
- getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails
8966
+ getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails,
8967
+ ...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
8968
+ } : usersApi ? {
8969
+ ...usersApi,
8970
+ ...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
8888
8971
  } : usersApi;
8889
8972
  const usersHandlers = usersApiMerged ? createUsersApiHandlers(mergePerm(usersApiMerged) ?? usersApiMerged) : null;
8890
8973
  const avatarPost = userAvatar ? createUserAvatarHandler(userAvatar) : null;
@@ -8895,7 +8978,7 @@ function createCmsApiHandler(config) {
8895
8978
  entityMap,
8896
8979
  json: config.json,
8897
8980
  requireAuth: config.requireAuth,
8898
- requireEntityPermission: reqEntityPerm
8981
+ requireEntityPermission: requireEntityPermissionEffective
8899
8982
  });
8900
8983
  const chatHandlers = chatConfig ? createChatHandlers(chatConfig) : null;
8901
8984
  function resolveResource(segment) {
@@ -8904,12 +8987,10 @@ function createCmsApiHandler(config) {
8904
8987
  }
8905
8988
  return {
8906
8989
  async handle(method, path, req) {
8907
- const perm = reqEntityPerm;
8908
8990
  async function analyticsGate() {
8909
8991
  const a = await config.requireAuth(req);
8910
8992
  if (a) return a;
8911
- if (perm) return perm(req, "analytics", "read");
8912
- return null;
8993
+ return requireEntityPermissionEffective(req, "analytics", "read");
8913
8994
  }
8914
8995
  if (path[0] === "admin" && path[1] === "roles") {
8915
8996
  if (!adminRoles) return config.json({ error: "Not found" }, { status: 404 });
@@ -8993,19 +9074,17 @@ function createCmsApiHandler(config) {
8993
9074
  const group = path[1];
8994
9075
  const isPublic = settingsConfig?.publicGetGroups?.includes(group);
8995
9076
  if (method === "GET") {
8996
- if (!isPublic && perm) {
9077
+ if (!isPublic) {
8997
9078
  const a = await config.requireAuth(req);
8998
9079
  if (a) return a;
8999
- const pe = await perm(req, "settings", "read");
9080
+ const pe = await requireEntityPermissionEffective(req, "settings", "read");
9000
9081
  if (pe) return pe;
9001
9082
  }
9002
9083
  return settingsHandlers.GET(req, group);
9003
9084
  }
9004
9085
  if (method === "PUT") {
9005
- if (perm) {
9006
- const pe = await perm(req, "settings", "update");
9007
- if (pe) return pe;
9008
- }
9086
+ const pe = await requireEntityPermissionEffective(req, "settings", "update");
9087
+ if (pe) return pe;
9009
9088
  return settingsHandlers.PUT(req, group);
9010
9089
  }
9011
9090
  }
@@ -9021,10 +9100,8 @@ function createCmsApiHandler(config) {
9021
9100
  if (path[0] === "orders" && path.length === 3 && path[2] === "invoice" && method === "GET" && getCms) {
9022
9101
  const a = await config.requireAuth(req);
9023
9102
  if (a) return a;
9024
- if (perm) {
9025
- const pe = await perm(req, "orders", "read");
9026
- if (pe) return pe;
9027
- }
9103
+ const pe = await requireEntityPermissionEffective(req, "orders", "read");
9104
+ if (pe) return pe;
9028
9105
  const cms = await getCms();
9029
9106
  const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await Promise.resolve().then(() => (init_erp_order_invoice(), erp_order_invoice_exports));
9030
9107
  const oid = Number(path[1]);
@@ -9034,10 +9111,8 @@ function createCmsApiHandler(config) {
9034
9111
  if (path[0] === "orders" && path.length === 3 && path[2] === "repost-erp" && getCms) {
9035
9112
  const a = await config.requireAuth(req);
9036
9113
  if (a) return a;
9037
- if (perm) {
9038
- const pe = await perm(req, "orders", method === "GET" ? "read" : "update");
9039
- if (pe) return pe;
9040
- }
9114
+ const pe = await requireEntityPermissionEffective(req, "orders", method === "GET" ? "read" : "update");
9115
+ if (pe) return pe;
9041
9116
  const oid = Number(path[1]);
9042
9117
  if (!Number.isFinite(oid)) return config.json({ error: "Invalid id" }, { status: 400 });
9043
9118
  const cms = await getCms();
@@ -10494,6 +10569,9 @@ var DEFAULT_ADMIN_NAV = [
10494
10569
  { href: "/admin/submissions", label: "Submissions" },
10495
10570
  { href: "/admin/pages", label: "Pages" }
10496
10571
  ];
10572
+
10573
+ // src/index.ts
10574
+ console.log("\u{1F525} USING LOCAL CMS CORE (index.ts loaded) \u{1F525}");
10497
10575
  export {
10498
10576
  ADMIN_GROUP_NAME,
10499
10577
  Address,