@infuro/cms-core 1.0.16 → 1.0.19

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 (47) 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 +139 -57
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +3 -2
  25. package/dist/index.d.ts +3 -2
  26. package/dist/index.js +139 -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/1774700000000-CollectionVariants.ts +13 -0
  39. package/dist/migrations/1774800000000-OtpChallengesUserPhone.ts +41 -41
  40. package/dist/migrations/1774900000000-MessageTemplates.ts +39 -39
  41. package/dist/migrations/1775000000000-ProductUomTypeOrderItemSnapshots.ts +29 -29
  42. package/dist/migrations/1775200000000-MediaDriveFolders.ts +38 -38
  43. package/dist/migrations/README.md +3 -3
  44. package/dist/theme.cjs.map +1 -1
  45. package/dist/theme.js.map +1 -1
  46. package/package.json +13 -6
  47. 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';
@@ -1048,6 +1048,7 @@ declare class Collection {
1048
1048
  description: string | null;
1049
1049
  image: string | null;
1050
1050
  metadata: Record<string, unknown> | null;
1051
+ variants: Array<Record<string, unknown>> | null;
1051
1052
  active: boolean;
1052
1053
  sortOrder: number;
1053
1054
  createdAt: Date;
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';
@@ -1048,6 +1048,7 @@ declare class Collection {
1048
1048
  description: string | null;
1049
1049
  image: string | null;
1050
1050
  metadata: Record<string, unknown> | null;
1051
+ variants: Array<Record<string, unknown>> | null;
1051
1052
  active: boolean;
1052
1053
  sortOrder: number;
1053
1054
  createdAt: Date;
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}`;
@@ -6581,6 +6605,7 @@ var Collection = class {
6581
6605
  description;
6582
6606
  image;
6583
6607
  metadata;
6608
+ variants;
6584
6609
  active;
6585
6610
  sortOrder;
6586
6611
  createdAt;
@@ -6623,6 +6648,9 @@ __decorateClass([
6623
6648
  __decorateClass([
6624
6649
  Column26("jsonb", { nullable: true })
6625
6650
  ], Collection.prototype, "metadata", 2);
6651
+ __decorateClass([
6652
+ Column26("jsonb", { nullable: true })
6653
+ ], Collection.prototype, "variants", 2);
6626
6654
  __decorateClass([
6627
6655
  Column26("boolean", { default: true })
6628
6656
  ], Collection.prototype, "active", 2);
@@ -7781,6 +7809,28 @@ function buildSearchWhereClause(repo, search) {
7781
7809
  if (ors.length === 0) return {};
7782
7810
  return ors.length === 1 ? ors[0] : ors;
7783
7811
  }
7812
+ function entityHasSoftDelete(repo) {
7813
+ return repo.metadata.columns.some((c) => c.propertyName === "deleted");
7814
+ }
7815
+ function mergeDeletedFalseWhere(repo, where) {
7816
+ if (!entityHasSoftDelete(repo)) return where;
7817
+ const d = { deleted: false };
7818
+ if (Array.isArray(where)) {
7819
+ if (where.length === 0) return [d];
7820
+ return where.map((w) => ({ ...w, ...d }));
7821
+ }
7822
+ return Object.keys(where).length > 0 ? { ...where, ...d } : d;
7823
+ }
7824
+ function buildSoftDeletePayload(meta, deletedBy) {
7825
+ const payload = { deleted: true };
7826
+ if (meta.columns.some((c) => c.propertyName === "deletedAt")) {
7827
+ payload.deletedAt = /* @__PURE__ */ new Date();
7828
+ }
7829
+ if (deletedBy != null && meta.columns.some((c) => c.propertyName === "deletedBy")) {
7830
+ payload.deletedBy = deletedBy;
7831
+ }
7832
+ return payload;
7833
+ }
7784
7834
  function makeContactErpSync(dataSource, entityMap, getCms) {
7785
7835
  return async function syncContactRowToErp(row) {
7786
7836
  if (!getCms) return;
@@ -7805,10 +7855,11 @@ function createCrudHandler(dataSource, entityMap, options) {
7805
7855
  async function authz(req, resource, action) {
7806
7856
  const authError = await requireAuth(req);
7807
7857
  if (authError) return authError;
7808
- if (reqPerm) {
7809
- const pe = await reqPerm(req, resource, action);
7810
- if (pe) return pe;
7858
+ if (!reqPerm) {
7859
+ return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
7811
7860
  }
7861
+ const pe = await reqPerm(req, resource, action);
7862
+ if (pe) return pe;
7812
7863
  return null;
7813
7864
  }
7814
7865
  return {
@@ -7844,7 +7895,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7844
7895
  return json({ total: 0, page, limit, totalPages: 0, data: [] });
7845
7896
  }
7846
7897
  }
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);
7898
+ 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
7899
  if (search && typeof search === "string" && search.trim()) {
7849
7900
  const term = `%${search.trim()}%`;
7850
7901
  qb.andWhere(
@@ -7882,7 +7933,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7882
7933
  const dateTo = searchParams.get("dateTo")?.trim();
7883
7934
  const methodFilter = searchParams.get("method")?.trim();
7884
7935
  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);
7936
+ 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
7937
  if (search && typeof search === "string" && search.trim()) {
7887
7938
  const term = `%${search.trim()}%`;
7888
7939
  qb.andWhere(
@@ -7913,7 +7964,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7913
7964
  const repo2 = dataSource.getRepository(entity);
7914
7965
  const statusFilter = searchParams.get("status")?.trim();
7915
7966
  const inventory = searchParams.get("inventory")?.trim();
7916
- const productWhere = {};
7967
+ const productWhere = { deleted: false };
7917
7968
  if (statusFilter) productWhere.status = statusFilter;
7918
7969
  if (inventory === "in_stock") productWhere.quantity = MoreThan2(0);
7919
7970
  if (inventory === "out_of_stock") productWhere.quantity = 0;
@@ -7936,7 +7987,7 @@ function createCrudHandler(dataSource, entityMap, options) {
7936
7987
  const typeFilter2 = searchParams.get("type")?.trim();
7937
7988
  const orderIdParam = searchParams.get("orderId")?.trim();
7938
7989
  const includeSummary = searchParams.get("includeSummary") === "1";
7939
- const qb = repo2.createQueryBuilder("contact").orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
7990
+ const qb = repo2.createQueryBuilder("contact").andWhere("contact.deleted = :contactDel", { contactDel: false }).orderBy(`contact.${sortField2}`, sortOrderContacts).skip(skip).take(limit);
7940
7991
  if (search && typeof search === "string" && search.trim()) {
7941
7992
  const term = `%${search.trim()}%`;
7942
7993
  qb.andWhere("(contact.name ILIKE :term OR contact.email ILIKE :term OR contact.phone ILIKE :term)", { term });
@@ -7977,9 +8028,9 @@ function createCrudHandler(dataSource, entityMap, options) {
7977
8028
  if (parentIdParam != null && parentIdParam !== "") {
7978
8029
  const n = Number(parentIdParam);
7979
8030
  if (!Number.isFinite(n)) return json({ error: "Invalid parentId" }, { status: 400 });
7980
- qb.where("m.parentId = :pid", { pid: n });
8031
+ qb.where("m.deleted = :mediaDel AND m.parentId = :pid", { mediaDel: false, pid: n });
7981
8032
  } else {
7982
- qb.where("m.parentId IS NULL");
8033
+ qb.where("m.deleted = :mediaDel AND m.parentId IS NULL", { mediaDel: false });
7983
8034
  }
7984
8035
  if (search && typeof search === "string" && search.trim()) {
7985
8036
  qb.andWhere("m.filename ILIKE :search", { search: `%${search.trim()}%` });
@@ -8023,6 +8074,7 @@ function createCrudHandler(dataSource, entityMap, options) {
8023
8074
  where = extraWhere;
8024
8075
  }
8025
8076
  }
8077
+ where = mergeDeletedFalseWhere(repo, where);
8026
8078
  const [data, total] = await repo.findAndCount({
8027
8079
  skip,
8028
8080
  take: limit,
@@ -8190,15 +8242,16 @@ function createCrudHandler(dataSource, entityMap, options) {
8190
8242
  };
8191
8243
  }
8192
8244
  function createCrudByIdHandler(dataSource, entityMap, options) {
8193
- const { requireAuth, json, requireEntityPermission: reqPerm, getCms } = options;
8245
+ const { requireAuth, json, requireEntityPermission: reqPerm, getCms, getDeletedByUserId } = options;
8194
8246
  const syncContactRowToErp = makeContactErpSync(dataSource, entityMap, getCms);
8195
8247
  async function authz(req, resource, action) {
8196
8248
  const authError = await requireAuth(req);
8197
8249
  if (authError) return authError;
8198
- if (reqPerm) {
8199
- const pe = await reqPerm(req, resource, action);
8200
- if (pe) return pe;
8250
+ if (!reqPerm) {
8251
+ return json({ error: "Forbidden", reason: "entity_rbac_required", entity: resource, action }, { status: 403 });
8201
8252
  }
8253
+ const pe = await reqPerm(req, resource, action);
8254
+ if (pe) return pe;
8202
8255
  return null;
8203
8256
  }
8204
8257
  return {
@@ -8210,7 +8263,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8210
8263
  const repo = dataSource.getRepository(entity);
8211
8264
  if (resource === "orders") {
8212
8265
  const order = await repo.findOne({
8213
- where: { id: Number(id) },
8266
+ where: { id: Number(id), deleted: false },
8214
8267
  relations: ["contact", "billingAddress", "shippingAddress", "items", "items.product", "items.product.collection", "payments"]
8215
8268
  });
8216
8269
  if (!order) return json({ message: "Not found" }, { status: 404 });
@@ -8222,7 +8275,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8222
8275
  }
8223
8276
  if (resource === "contacts") {
8224
8277
  const contact = await repo.findOne({
8225
- where: { id: Number(id) },
8278
+ where: { id: Number(id), deleted: false },
8226
8279
  relations: ["form_submissions", "form_submissions.form", "orders", "payments", "addresses"]
8227
8280
  });
8228
8281
  if (!contact) return json({ message: "Not found" }, { status: 404 });
@@ -8244,7 +8297,7 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8244
8297
  }
8245
8298
  if (resource === "payments") {
8246
8299
  const payment = await repo.findOne({
8247
- where: { id: Number(id) },
8300
+ where: { id: Number(id), deleted: false },
8248
8301
  relations: ["order", "order.contact", "contact"]
8249
8302
  });
8250
8303
  if (!payment) return json({ message: "Not found" }, { status: 404 });
@@ -8252,12 +8305,13 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8252
8305
  }
8253
8306
  if (resource === "blogs") {
8254
8307
  const blog = await repo.findOne({
8255
- where: { id: Number(id) },
8308
+ where: { id: Number(id), deleted: false },
8256
8309
  relations: ["category", "seo", "tags"]
8257
8310
  });
8258
8311
  return blog ? json(blog) : json({ message: "Not found" }, { status: 404 });
8259
8312
  }
8260
- const item = await repo.findOne({ where: { id: Number(id) } });
8313
+ const idWhere = entityHasSoftDelete(repo) ? { id: Number(id), deleted: false } : { id: Number(id) };
8314
+ const item = await repo.findOne({ where: idWhere });
8261
8315
  return item ? json(item) : json({ message: "Not found" }, { status: 404 });
8262
8316
  },
8263
8317
  async PUT(req, resource, id) {
@@ -8269,7 +8323,9 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8269
8323
  const repo = dataSource.getRepository(entity);
8270
8324
  const numericId = Number(id);
8271
8325
  if (resource === "blogs" && rawBody && typeof rawBody === "object" && entityMap.categories && entityMap.seos && entityMap.tags) {
8272
- const existing = await repo.findOne({ where: { id: numericId } });
8326
+ const existing = await repo.findOne({
8327
+ where: { id: numericId, deleted: false }
8328
+ });
8273
8329
  if (!existing) return json({ message: "Not found" }, { status: 404 });
8274
8330
  const updatePayload2 = pickColumnUpdates(repo, rawBody);
8275
8331
  if ("category" in rawBody) {
@@ -8345,6 +8401,12 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8345
8401
  });
8346
8402
  return updated2 ? json(updated2) : json({ message: "Not found" }, { status: 404 });
8347
8403
  }
8404
+ if (entityHasSoftDelete(repo)) {
8405
+ const cur = await repo.findOne({
8406
+ where: { id: numericId, deleted: false }
8407
+ });
8408
+ if (!cur) return json({ message: "Not found" }, { status: 404 });
8409
+ }
8348
8410
  const updatePayload = rawBody && typeof rawBody === "object" ? pickColumnUpdates(repo, rawBody) : {};
8349
8411
  if (resource === "media") {
8350
8412
  const u = updatePayload;
@@ -8371,7 +8433,24 @@ function createCrudByIdHandler(dataSource, entityMap, options) {
8371
8433
  const entity = entityMap[resource];
8372
8434
  if (!entity) return json({ error: "Invalid resource" }, { status: 400 });
8373
8435
  const repo = dataSource.getRepository(entity);
8374
- const result = await repo.delete(Number(id));
8436
+ const numericId = Number(id);
8437
+ if (entityHasSoftDelete(repo)) {
8438
+ const existing = await repo.findOne({
8439
+ where: { id: numericId, deleted: false }
8440
+ });
8441
+ if (!existing) return json({ message: "Not found" }, { status: 404 });
8442
+ let deletedBy = null;
8443
+ if (getDeletedByUserId) {
8444
+ try {
8445
+ deletedBy = await getDeletedByUserId(req);
8446
+ } catch {
8447
+ deletedBy = null;
8448
+ }
8449
+ }
8450
+ await repo.update(numericId, buildSoftDeletePayload(repo.metadata, deletedBy));
8451
+ return json({ message: "Deleted successfully" }, { status: 200 });
8452
+ }
8453
+ const result = await repo.delete(numericId);
8375
8454
  if (result.affected === 0) return json({ message: "Not found" }, { status: 404 });
8376
8455
  return json({ message: "Deleted successfully" }, { status: 200 });
8377
8456
  }
@@ -8799,9 +8878,10 @@ function createCmsApiHandler(config) {
8799
8878
  userProfile,
8800
8879
  settings: settingsConfig,
8801
8880
  chat: chatConfig,
8802
- requireEntityPermission: reqEntityPerm,
8881
+ requireEntityPermission: userRequireEntityPermission,
8803
8882
  getSessionUser
8804
8883
  } = config;
8884
+ const requireEntityPermissionEffective = userRequireEntityPermission ?? (async (_req, entity, action) => config.json({ error: "Forbidden", reason: "entity_rbac_required", entity, action }, { status: 403 }));
8805
8885
  const analytics = analyticsConfig ?? (getCms ? {
8806
8886
  json: config.json,
8807
8887
  requireAuth: async () => null,
@@ -8839,12 +8919,20 @@ function createCmsApiHandler(config) {
8839
8919
  const crudOpts = {
8840
8920
  requireAuth: config.requireAuth,
8841
8921
  json: config.json,
8842
- requireEntityPermission: reqEntityPerm,
8843
- getCms
8922
+ requireEntityPermission: requireEntityPermissionEffective,
8923
+ getCms,
8924
+ ...getSessionUser ? {
8925
+ getDeletedByUserId: async () => {
8926
+ const u = await getSessionUser();
8927
+ if (!u?.id) return null;
8928
+ const n = Number(u.id);
8929
+ return Number.isFinite(n) ? n : null;
8930
+ }
8931
+ } : {}
8844
8932
  };
8845
8933
  const crud = createCrudHandler(dataSource, entityMap, crudOpts);
8846
8934
  const crudById = createCrudByIdHandler(dataSource, entityMap, crudOpts);
8847
- const mergePerm = (c) => !c ? void 0 : reqEntityPerm ? { ...c, requireEntityPermission: reqEntityPerm } : c;
8935
+ const mergePerm = (c) => !c ? void 0 : { ...c, requireEntityPermission: requireEntityPermissionEffective };
8848
8936
  const adminRoles = getSessionUser && createAdminRolesHandlers({
8849
8937
  dataSource,
8850
8938
  entityMap,
@@ -8860,12 +8948,7 @@ function createCmsApiHandler(config) {
8860
8948
  json: config.json,
8861
8949
  requireAuth: config.requireAuth
8862
8950
  }
8863
- ) ?? {
8864
- dataSource,
8865
- entityMap,
8866
- json: config.json,
8867
- requireAuth: config.requireAuth
8868
- };
8951
+ );
8869
8952
  const ecommerceAnalyticsGet = createEcommerceAnalyticsHandler(ecommerceAnalyticsResolved);
8870
8953
  const analyticsHandlers = analytics ? createAnalyticsHandlers(analytics) : null;
8871
8954
  const uploadMerged = upload ? {
@@ -8884,7 +8967,11 @@ function createCmsApiHandler(config) {
8884
8967
  const usersApiMerged = usersApi && getCms ? {
8885
8968
  ...usersApi,
8886
8969
  getCms: usersApi.getCms ?? getCms,
8887
- getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails
8970
+ getCompanyDetails: usersApi.getCompanyDetails ?? config.getCompanyDetails,
8971
+ ...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
8972
+ } : usersApi ? {
8973
+ ...usersApi,
8974
+ ...getSessionUser ? { getSessionUser: usersApi.getSessionUser ?? getSessionUser } : {}
8888
8975
  } : usersApi;
8889
8976
  const usersHandlers = usersApiMerged ? createUsersApiHandlers(mergePerm(usersApiMerged) ?? usersApiMerged) : null;
8890
8977
  const avatarPost = userAvatar ? createUserAvatarHandler(userAvatar) : null;
@@ -8895,7 +8982,7 @@ function createCmsApiHandler(config) {
8895
8982
  entityMap,
8896
8983
  json: config.json,
8897
8984
  requireAuth: config.requireAuth,
8898
- requireEntityPermission: reqEntityPerm
8985
+ requireEntityPermission: requireEntityPermissionEffective
8899
8986
  });
8900
8987
  const chatHandlers = chatConfig ? createChatHandlers(chatConfig) : null;
8901
8988
  function resolveResource(segment) {
@@ -8904,12 +8991,10 @@ function createCmsApiHandler(config) {
8904
8991
  }
8905
8992
  return {
8906
8993
  async handle(method, path, req) {
8907
- const perm = reqEntityPerm;
8908
8994
  async function analyticsGate() {
8909
8995
  const a = await config.requireAuth(req);
8910
8996
  if (a) return a;
8911
- if (perm) return perm(req, "analytics", "read");
8912
- return null;
8997
+ return requireEntityPermissionEffective(req, "analytics", "read");
8913
8998
  }
8914
8999
  if (path[0] === "admin" && path[1] === "roles") {
8915
9000
  if (!adminRoles) return config.json({ error: "Not found" }, { status: 404 });
@@ -8993,19 +9078,17 @@ function createCmsApiHandler(config) {
8993
9078
  const group = path[1];
8994
9079
  const isPublic = settingsConfig?.publicGetGroups?.includes(group);
8995
9080
  if (method === "GET") {
8996
- if (!isPublic && perm) {
9081
+ if (!isPublic) {
8997
9082
  const a = await config.requireAuth(req);
8998
9083
  if (a) return a;
8999
- const pe = await perm(req, "settings", "read");
9084
+ const pe = await requireEntityPermissionEffective(req, "settings", "read");
9000
9085
  if (pe) return pe;
9001
9086
  }
9002
9087
  return settingsHandlers.GET(req, group);
9003
9088
  }
9004
9089
  if (method === "PUT") {
9005
- if (perm) {
9006
- const pe = await perm(req, "settings", "update");
9007
- if (pe) return pe;
9008
- }
9090
+ const pe = await requireEntityPermissionEffective(req, "settings", "update");
9091
+ if (pe) return pe;
9009
9092
  return settingsHandlers.PUT(req, group);
9010
9093
  }
9011
9094
  }
@@ -9021,10 +9104,8 @@ function createCmsApiHandler(config) {
9021
9104
  if (path[0] === "orders" && path.length === 3 && path[2] === "invoice" && method === "GET" && getCms) {
9022
9105
  const a = await config.requireAuth(req);
9023
9106
  if (a) return a;
9024
- if (perm) {
9025
- const pe = await perm(req, "orders", "read");
9026
- if (pe) return pe;
9027
- }
9107
+ const pe = await requireEntityPermissionEffective(req, "orders", "read");
9108
+ if (pe) return pe;
9028
9109
  const cms = await getCms();
9029
9110
  const { streamOrderInvoicePdf: streamOrderInvoicePdf2 } = await Promise.resolve().then(() => (init_erp_order_invoice(), erp_order_invoice_exports));
9030
9111
  const oid = Number(path[1]);
@@ -9034,10 +9115,8 @@ function createCmsApiHandler(config) {
9034
9115
  if (path[0] === "orders" && path.length === 3 && path[2] === "repost-erp" && getCms) {
9035
9116
  const a = await config.requireAuth(req);
9036
9117
  if (a) return a;
9037
- if (perm) {
9038
- const pe = await perm(req, "orders", method === "GET" ? "read" : "update");
9039
- if (pe) return pe;
9040
- }
9118
+ const pe = await requireEntityPermissionEffective(req, "orders", method === "GET" ? "read" : "update");
9119
+ if (pe) return pe;
9041
9120
  const oid = Number(path[1]);
9042
9121
  if (!Number.isFinite(oid)) return config.json({ error: "Invalid id" }, { status: 400 });
9043
9122
  const cms = await getCms();
@@ -10494,6 +10573,9 @@ var DEFAULT_ADMIN_NAV = [
10494
10573
  { href: "/admin/submissions", label: "Submissions" },
10495
10574
  { href: "/admin/pages", label: "Pages" }
10496
10575
  ];
10576
+
10577
+ // src/index.ts
10578
+ console.log("\u{1F525} USING LOCAL CMS CORE (index.ts loaded) \u{1F525}");
10497
10579
  export {
10498
10580
  ADMIN_GROUP_NAME,
10499
10581
  Address,