@fonderie/customers 6.1.3 → 6.1.5

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.d.cts CHANGED
@@ -196,7 +196,8 @@ declare class CustomerAddressModel {
196
196
  }): Promise<ICustomerAddress>;
197
197
  updateLabel(addrId: string, customerId: string, labelId: string): Promise<ICustomerAddress>;
198
198
  setPrimary(addrId: string, customerId: string): Promise<void>;
199
- remove(addrId: string, customerId: string): Promise<void>;
199
+ /** Returns false when the address is not linked to THIS customer (no-op). */
200
+ remove(addrId: string, customerId: string): Promise<boolean>;
200
201
  }
201
202
 
202
203
  declare class CustomerEmailModel {
package/dist/index.d.ts CHANGED
@@ -196,7 +196,8 @@ declare class CustomerAddressModel {
196
196
  }): Promise<ICustomerAddress>;
197
197
  updateLabel(addrId: string, customerId: string, labelId: string): Promise<ICustomerAddress>;
198
198
  setPrimary(addrId: string, customerId: string): Promise<void>;
199
- remove(addrId: string, customerId: string): Promise<void>;
199
+ /** Returns false when the address is not linked to THIS customer (no-op). */
200
+ remove(addrId: string, customerId: string): Promise<boolean>;
200
201
  }
201
202
 
202
203
  declare class CustomerEmailModel {
package/dist/index.js CHANGED
@@ -908,16 +908,18 @@ var CustomerAddressModel = class {
908
908
  );
909
909
  });
910
910
  }
911
+ /** Returns false when the address is not linked to THIS customer (no-op). */
911
912
  async remove(addrId, customerId) {
912
- await this.store.transaction(async (tx) => {
913
+ return this.store.transaction(async (tx) => {
913
914
  const [deleted] = await tx.query(
914
915
  `DELETE FROM fonderie_customer_addresses
915
916
  WHERE addr_id = $1 AND customer_id = $2
916
917
  RETURNING is_primary AS "isPrimary"`,
917
918
  [addrId, customerId]
918
919
  );
920
+ if (!deleted) return false;
919
921
  await tx.query(`DELETE FROM fonderie_addresses WHERE id = $1`, [addrId]);
920
- if (deleted?.isPrimary) {
922
+ if (deleted.isPrimary) {
921
923
  await tx.query(
922
924
  `UPDATE fonderie_customer_addresses
923
925
  SET is_primary = true
@@ -930,6 +932,7 @@ var CustomerAddressModel = class {
930
932
  [customerId]
931
933
  );
932
934
  }
935
+ return true;
933
936
  });
934
937
  }
935
938
  };
@@ -1039,11 +1042,23 @@ var CustomerLabelModel = class {
1039
1042
  [type]
1040
1043
  );
1041
1044
  }
1042
- remove(id) {
1043
- return this.store.query(
1044
- `DELETE FROM fonderie_customer_labels WHERE id = $1`,
1045
+ /**
1046
+ * Returns false when the label is still referenced. Labels are a SHARED
1047
+ * table (no workspace column), so an unconditional delete would let one
1048
+ * tenant destroy a label other tenants' emails/phones/addresses point at.
1049
+ * Until labels are workspace-scoped, only an unreferenced label may go.
1050
+ */
1051
+ async remove(id) {
1052
+ const rows = await this.store.query(
1053
+ `DELETE FROM fonderie_customer_labels l
1054
+ WHERE l.id = $1
1055
+ AND NOT EXISTS (SELECT 1 FROM fonderie_customer_emails WHERE label_id = l.id)
1056
+ AND NOT EXISTS (SELECT 1 FROM fonderie_customer_phones WHERE label_id = l.id)
1057
+ AND NOT EXISTS (SELECT 1 FROM fonderie_customer_addresses WHERE label_id = l.id)
1058
+ RETURNING l.id`,
1045
1059
  [id]
1046
- ).then(() => void 0);
1060
+ );
1061
+ return rows.length > 0;
1047
1062
  }
1048
1063
  async findOrCreate(type, raw) {
1049
1064
  const value = raw.trim().toLowerCase();
@@ -1733,7 +1748,10 @@ function customerAddressController(store) {
1733
1748
  if (!isUuid(addrId)) {
1734
1749
  return setApiResponse2(HTTP2.UNPROCESSABLE, "INVALID_PARAMETER", "addrId must be a valid UUID");
1735
1750
  }
1736
- await addresses.remove(addrId, r.customer.id);
1751
+ const removed = await addresses.remove(addrId, r.customer.id);
1752
+ if (!removed) {
1753
+ return setApiResponse2(HTTP2.NOT_FOUND, "NOT_FOUND", "Address not found");
1754
+ }
1737
1755
  return setApiResponse2(HTTP2.OK, "ADDRESS_REMOVED", "Address removed successfully.");
1738
1756
  }
1739
1757
  };
@@ -2153,7 +2171,14 @@ function customerLabelController(store) {
2153
2171
  if (!isUuid(labelId)) {
2154
2172
  return setApiResponse7(HTTP7.UNPROCESSABLE, "INVALID_PARAMETER", "labelId must be a valid UUID");
2155
2173
  }
2156
- await labels.remove(labelId);
2174
+ const removed = await labels.remove(labelId);
2175
+ if (!removed) {
2176
+ return setApiResponse7(
2177
+ HTTP7.CONFLICT,
2178
+ "LABEL_IN_USE",
2179
+ "Label is still referenced by customer records and cannot be deleted."
2180
+ );
2181
+ }
2157
2182
  return setApiResponse7(HTTP7.OK, "LABEL_DELETED", "Label deleted successfully.");
2158
2183
  }
2159
2184
  };