@fonderie/customers 1.0.0 → 1.1.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.
package/dist/index.cjs CHANGED
@@ -28,6 +28,7 @@ __export(index_exports, {
28
28
  CustomerTagModel: () => CustomerTagModel,
29
29
  CustomersModule: () => CustomersModule,
30
30
  EVENT_KEYS: () => EVENT_KEYS,
31
+ schemas: () => schemas_exports,
31
32
  toAddressDTO: () => toAddressDTO,
32
33
  toCustomerAddressDTO: () => toCustomerAddressDTO,
33
34
  toCustomerDTO: () => toCustomerDTO,
@@ -89,13 +90,13 @@ function toCustomerShallowDTO(c) {
89
90
  };
90
91
  }
91
92
  function toCustomerRelationshipExpandedDTO(r) {
92
- const { id: customerId, ...customerFields } = toCustomerShallowDTO(r.customer);
93
+ const { id: customerId, ...customerFields2 } = toCustomerShallowDTO(r.customer);
93
94
  return {
94
95
  id: (0, import_core.stringOrEmpty)(r.id),
95
96
  customerId,
96
97
  relationship: (0, import_core.stringOrEmpty)(r.relationship),
97
98
  isPrimary: (0, import_core.booleanOrFalse)(r.isPrimary),
98
- ...customerFields
99
+ ...customerFields2
99
100
  };
100
101
  }
101
102
  function toCustomerDetailDTO(c) {
@@ -110,13 +111,13 @@ function toCustomerDetailDTO(c) {
110
111
  };
111
112
  }
112
113
  function toCustomerRelationshipExpandedD2DTO(r) {
113
- const { id: customerId, ...customerFields } = toCustomerShallowDTO(r.customer);
114
+ const { id: customerId, ...customerFields2 } = toCustomerShallowDTO(r.customer);
114
115
  return {
115
116
  id: (0, import_core.stringOrEmpty)(r.id),
116
117
  customerId,
117
118
  relationship: (0, import_core.stringOrEmpty)(r.relationship),
118
119
  isPrimary: (0, import_core.booleanOrFalse)(r.isPrimary),
119
- ...customerFields,
120
+ ...customerFields2,
120
121
  relationships: (0, import_core.arrayOrEmpty)(r.customer.relationships).map(toCustomerRelationshipExpandedDTO)
121
122
  };
122
123
  }
@@ -1196,6 +1197,67 @@ var CustomerTagModel = class {
1196
1197
 
1197
1198
  // src/routes.ts
1198
1199
  var import_middlewares = require("@fonderie/core/middlewares");
1200
+
1201
+ // src/schemas.ts
1202
+ var schemas_exports = {};
1203
+ __export(schemas_exports, {
1204
+ addAddressSchema: () => addAddressSchema,
1205
+ addEmailSchema: () => addEmailSchema,
1206
+ addPhoneSchema: () => addPhoneSchema,
1207
+ addRelationshipSchema: () => addRelationshipSchema,
1208
+ addTagSchema: () => addTagSchema,
1209
+ blacklistSchema: () => blacklistSchema,
1210
+ createCustomerSchema: () => createCustomerSchema,
1211
+ noteSchema: () => noteSchema,
1212
+ updateAddressSchema: () => updateAddressSchema,
1213
+ updateCustomerSchema: () => updateCustomerSchema,
1214
+ updateEmailSchema: () => updateEmailSchema,
1215
+ updatePhoneSchema: () => updatePhoneSchema
1216
+ });
1217
+ var import_zod = require("zod");
1218
+ var label = import_zod.z.string().max(100).optional();
1219
+ var isPrimary = import_zod.z.boolean().optional();
1220
+ var email = import_zod.z.string().trim().pipe(import_zod.z.email());
1221
+ var phone = import_zod.z.string().refine((v) => /^\+?[1-9]\d{6,14}$/.test(v.replace(/[\s\-()]/g, "")), "Invalid phone number");
1222
+ var customerFields = {
1223
+ type: import_zod.z.enum(["individual", "business"]).optional(),
1224
+ sex: import_zod.z.enum(["UNKNOWN", "MALE", "FEMALE"]).optional(),
1225
+ firstName: import_zod.z.string().max(100).nullable().optional(),
1226
+ lastName: import_zod.z.string().max(100).nullable().optional(),
1227
+ companyName: import_zod.z.string().max(200).nullable().optional(),
1228
+ avatarUrl: import_zod.z.string().trim().pipe(import_zod.z.url()).nullable().optional(),
1229
+ locale: import_zod.z.string().max(35).nullable().optional(),
1230
+ referenceCode: import_zod.z.string().max(100).nullable().optional()
1231
+ };
1232
+ var createCustomerSchema = import_zod.z.object(customerFields);
1233
+ var updateCustomerSchema = import_zod.z.object(customerFields).refine((o) => Object.values(o).some((v) => v !== void 0), "Provide at least one field");
1234
+ var blacklistSchema = import_zod.z.object({ reason: import_zod.z.string().max(1e3).optional() });
1235
+ var addEmailSchema = import_zod.z.object({ email, label, isPrimary });
1236
+ var updateEmailSchema = import_zod.z.object({ email: email.optional(), label, isPrimary }).refine((o) => Object.values(o).some((v) => v !== void 0), "Provide at least one field");
1237
+ var addPhoneSchema = import_zod.z.object({ phone, label, isPrimary });
1238
+ var updatePhoneSchema = import_zod.z.object({ phone: phone.optional(), label, isPrimary }).refine((o) => Object.values(o).some((v) => v !== void 0), "Provide at least one field");
1239
+ var addressFields = {
1240
+ label,
1241
+ isPrimary,
1242
+ line1: import_zod.z.string().max(200).nullable().optional(),
1243
+ line2: import_zod.z.string().max(200).nullable().optional(),
1244
+ unit: import_zod.z.string().max(50).nullable().optional(),
1245
+ zipPostalCode: import_zod.z.string().max(20).nullable().optional(),
1246
+ countryIso: import_zod.z.string().max(3).nullable().optional(),
1247
+ subdivision1Iso: import_zod.z.string().max(10).nullable().optional(),
1248
+ subdivision2Iso: import_zod.z.string().max(10).nullable().optional()
1249
+ };
1250
+ var addAddressSchema = import_zod.z.object(addressFields);
1251
+ var updateAddressSchema = import_zod.z.object(addressFields).refine((o) => Object.values(o).some((v) => v !== void 0), "Provide at least one field");
1252
+ var noteSchema = import_zod.z.object({ body: import_zod.z.string().trim().min(1, "body is required").max(1e4) });
1253
+ var addTagSchema = import_zod.z.object({ tag: import_zod.z.string().trim().min(1, "tag is required").max(100) });
1254
+ var addRelationshipSchema = import_zod.z.object({
1255
+ relatedId: import_zod.z.string().min(1, "relatedId is required"),
1256
+ relationship: import_zod.z.string().max(100).optional(),
1257
+ isPrimary
1258
+ });
1259
+
1260
+ // src/routes.ts
1199
1261
  var import_workspaces = require("@fonderie/workspaces");
1200
1262
 
1201
1263
  // src/controllers/customer.controller.ts
@@ -1312,7 +1374,8 @@ function customerController(store, config = {}, bus) {
1312
1374
  companyName: typeof companyName === "string" ? companyName : null,
1313
1375
  avatarUrl: typeof avatarUrl === "string" ? avatarUrl : null,
1314
1376
  locale: typeof locale === "string" ? locale : "en-US",
1315
- referenceCode: typeof referenceCode === "string" ? referenceCode.toUpperCase() : void 0,
1377
+ // exactOptionalPropertyTypes: omit the key entirely when absent
1378
+ ...typeof referenceCode === "string" ? { referenceCode: referenceCode.toUpperCase() } : {},
1316
1379
  referenceCodePrefix: prefix,
1317
1380
  createdBy: ctx.user?.id ?? null
1318
1381
  });
@@ -1661,20 +1724,20 @@ function customerEmailController(store) {
1661
1724
  return r.error;
1662
1725
  }
1663
1726
  const body = ctx.meta["body"];
1664
- const email = body?.["email"];
1665
- if (typeof email !== "string" || email.trim().length === 0) {
1727
+ const email2 = body?.["email"];
1728
+ if (typeof email2 !== "string" || email2.trim().length === 0) {
1666
1729
  return (0, import_core4.setApiResponse)(import_core4.HTTP.UNPROCESSABLE, "INVALID_PARAMETER", "email is required");
1667
1730
  }
1668
1731
  const rawLabel = typeof body?.["label"] === "string" ? body["label"] : "work";
1669
- const isPrimary = body?.["isPrimary"] === true;
1732
+ const isPrimary2 = body?.["isPrimary"] === true;
1670
1733
  const { id: labelId } = await labels.findOrCreate("email", rawLabel);
1671
1734
  let created;
1672
1735
  try {
1673
1736
  created = await emails.add({
1674
1737
  customerId: r.customer.id,
1675
- email: email.trim(),
1738
+ email: email2.trim(),
1676
1739
  labelId,
1677
- isPrimary
1740
+ isPrimary: isPrimary2
1678
1741
  });
1679
1742
  } catch (err) {
1680
1743
  if (err instanceof Error && err.message.includes("idx_fce_unique_email")) {
@@ -1870,20 +1933,20 @@ function customerPhoneController(store) {
1870
1933
  return r.error;
1871
1934
  }
1872
1935
  const body = ctx.meta["body"];
1873
- const phone = body?.["phone"];
1874
- if (typeof phone !== "string" || phone.trim().length === 0) {
1936
+ const phone2 = body?.["phone"];
1937
+ if (typeof phone2 !== "string" || phone2.trim().length === 0) {
1875
1938
  return (0, import_core6.setApiResponse)(import_core6.HTTP.UNPROCESSABLE, "INVALID_PARAMETER", "phone is required");
1876
1939
  }
1877
1940
  const rawLabel = typeof body?.["label"] === "string" ? body["label"] : "mobile";
1878
- const isPrimary = body?.["isPrimary"] === true;
1941
+ const isPrimary2 = body?.["isPrimary"] === true;
1879
1942
  const { id: labelId } = await labels.findOrCreate("phone", rawLabel);
1880
1943
  let created;
1881
1944
  try {
1882
1945
  created = await phones.add({
1883
1946
  customerId: r.customer.id,
1884
- phone: phone.trim(),
1947
+ phone: phone2.trim(),
1885
1948
  labelId,
1886
- isPrimary
1949
+ isPrimary: isPrimary2
1887
1950
  });
1888
1951
  } catch (err) {
1889
1952
  if (err instanceof Error && err.message.includes("idx_fcp_unique_phone")) {
@@ -2125,55 +2188,55 @@ function customerRelationshipController(store) {
2125
2188
  function buildCustomerRoutes(store, config, bus) {
2126
2189
  const wsCtx = (0, import_workspaces.withWorkspace)(store);
2127
2190
  const customer = customerController(store, config, bus);
2128
- const email = customerEmailController(store);
2129
- const phone = customerPhoneController(store);
2191
+ const email2 = customerEmailController(store);
2192
+ const phone2 = customerPhoneController(store);
2130
2193
  const address = customerAddressController(store);
2131
2194
  const note = customerNoteController(store);
2132
2195
  const tag = customerTagController(store);
2133
2196
  const relationship = customerRelationshipController(store);
2134
- const label = customerLabelController(store);
2197
+ const label2 = customerLabelController(store);
2135
2198
  return [
2136
2199
  // ── Labels ───────────────────────────────────────────────────────
2137
- ["GET", "/customers/labels", import_middlewares.requireAuth, wsCtx, label.list],
2138
- ["DELETE", "/customers/labels/:labelId", import_middlewares.requireAuth, wsCtx, label.remove],
2200
+ ["GET", "/customers/labels", import_middlewares.requireAuth, wsCtx, label2.list],
2201
+ ["DELETE", "/customers/labels/:labelId", import_middlewares.requireAuth, wsCtx, label2.remove],
2139
2202
  // ── Core customer CRUD ───────────────────────────────────────────
2140
2203
  ["GET", "/customers", import_middlewares.requireAuth, wsCtx, customer.list],
2141
- ["POST", "/customers", import_middlewares.requireAuth, wsCtx, customer.create],
2204
+ ["POST", "/customers", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(createCustomerSchema), customer.create],
2142
2205
  ["GET", "/customers/:customerId", import_middlewares.requireAuth, wsCtx, customer.get],
2143
- ["PUT", "/customers/:customerId", import_middlewares.requireAuth, wsCtx, customer.update],
2206
+ ["PUT", "/customers/:customerId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateCustomerSchema), customer.update],
2144
2207
  ["DELETE", "/customers/:customerId", import_middlewares.requireAuth, wsCtx, customer.delete],
2145
- ["POST", "/customers/:customerId/blacklist", import_middlewares.requireAuth, wsCtx, customer.blacklist],
2208
+ ["POST", "/customers/:customerId/blacklist", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(blacklistSchema), customer.blacklist],
2146
2209
  ["POST", "/customers/:customerId/unblacklist", import_middlewares.requireAuth, wsCtx, customer.unblacklist],
2147
2210
  // ── Emails ───────────────────────────────────────────────────────
2148
- ["GET", "/customers/:customerId/emails", import_middlewares.requireAuth, wsCtx, email.list],
2149
- ["POST", "/customers/:customerId/emails", import_middlewares.requireAuth, wsCtx, email.add],
2150
- ["PATCH", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx, email.update],
2151
- ["PUT", "/customers/:customerId/emails/:emailId/primary", import_middlewares.requireAuth, wsCtx, email.setPrimary],
2152
- ["DELETE", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx, email.remove],
2211
+ ["GET", "/customers/:customerId/emails", import_middlewares.requireAuth, wsCtx, email2.list],
2212
+ ["POST", "/customers/:customerId/emails", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addEmailSchema), email2.add],
2213
+ ["PATCH", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateEmailSchema), email2.update],
2214
+ ["PUT", "/customers/:customerId/emails/:emailId/primary", import_middlewares.requireAuth, wsCtx, email2.setPrimary],
2215
+ ["DELETE", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx, email2.remove],
2153
2216
  // ── Phones ───────────────────────────────────────────────────────
2154
- ["GET", "/customers/:customerId/phones", import_middlewares.requireAuth, wsCtx, phone.list],
2155
- ["POST", "/customers/:customerId/phones", import_middlewares.requireAuth, wsCtx, phone.add],
2156
- ["PATCH", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx, phone.update],
2157
- ["PUT", "/customers/:customerId/phones/:phoneId/primary", import_middlewares.requireAuth, wsCtx, phone.setPrimary],
2158
- ["DELETE", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx, phone.remove],
2217
+ ["GET", "/customers/:customerId/phones", import_middlewares.requireAuth, wsCtx, phone2.list],
2218
+ ["POST", "/customers/:customerId/phones", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addPhoneSchema), phone2.add],
2219
+ ["PATCH", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updatePhoneSchema), phone2.update],
2220
+ ["PUT", "/customers/:customerId/phones/:phoneId/primary", import_middlewares.requireAuth, wsCtx, phone2.setPrimary],
2221
+ ["DELETE", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx, phone2.remove],
2159
2222
  // ── Addresses ────────────────────────────────────────────────────
2160
2223
  ["GET", "/customers/:customerId/addresses", import_middlewares.requireAuth, wsCtx, address.list],
2161
- ["POST", "/customers/:customerId/addresses", import_middlewares.requireAuth, wsCtx, address.add],
2162
- ["PATCH", "/customers/:customerId/addresses/:addrId", import_middlewares.requireAuth, wsCtx, address.update],
2224
+ ["POST", "/customers/:customerId/addresses", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addAddressSchema), address.add],
2225
+ ["PATCH", "/customers/:customerId/addresses/:addrId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(updateAddressSchema), address.update],
2163
2226
  ["PUT", "/customers/:customerId/addresses/:addrId/primary", import_middlewares.requireAuth, wsCtx, address.setPrimary],
2164
2227
  ["DELETE", "/customers/:customerId/addresses/:addrId", import_middlewares.requireAuth, wsCtx, address.remove],
2165
2228
  // ── Notes ────────────────────────────────────────────────────────
2166
2229
  ["GET", "/customers/:customerId/notes", import_middlewares.requireAuth, wsCtx, note.list],
2167
- ["POST", "/customers/:customerId/notes", import_middlewares.requireAuth, wsCtx, note.create],
2168
- ["PUT", "/customers/:customerId/notes/:noteId", import_middlewares.requireAuth, wsCtx, note.update],
2230
+ ["POST", "/customers/:customerId/notes", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(noteSchema), note.create],
2231
+ ["PUT", "/customers/:customerId/notes/:noteId", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(noteSchema), note.update],
2169
2232
  ["DELETE", "/customers/:customerId/notes/:noteId", import_middlewares.requireAuth, wsCtx, note.delete],
2170
2233
  // ── Tags ─────────────────────────────────────────────────────────
2171
2234
  ["GET", "/customers/:customerId/tags", import_middlewares.requireAuth, wsCtx, tag.list],
2172
- ["POST", "/customers/:customerId/tags", import_middlewares.requireAuth, wsCtx, tag.add],
2235
+ ["POST", "/customers/:customerId/tags", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addTagSchema), tag.add],
2173
2236
  ["DELETE", "/customers/:customerId/tags/:tag", import_middlewares.requireAuth, wsCtx, tag.remove],
2174
2237
  // ── Relationships ────────────────────────────────────────────────────
2175
2238
  ["GET", "/customers/:customerId/relationships", import_middlewares.requireAuth, wsCtx, relationship.list],
2176
- ["POST", "/customers/:customerId/relationships", import_middlewares.requireAuth, wsCtx, relationship.add],
2239
+ ["POST", "/customers/:customerId/relationships", import_middlewares.requireAuth, wsCtx, (0, import_middlewares.validate)(addRelationshipSchema), relationship.add],
2177
2240
  ["PUT", "/customers/:customerId/relationships/:relatedId/primary", import_middlewares.requireAuth, wsCtx, relationship.setPrimary],
2178
2241
  ["DELETE", "/customers/:customerId/relationships/:relatedId", import_middlewares.requireAuth, wsCtx, relationship.remove]
2179
2242
  ];
@@ -2208,6 +2271,7 @@ var CustomersModule = class {
2208
2271
  CustomerTagModel,
2209
2272
  CustomersModule,
2210
2273
  EVENT_KEYS,
2274
+ schemas,
2211
2275
  toAddressDTO,
2212
2276
  toCustomerAddressDTO,
2213
2277
  toCustomerDTO,