@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 +103 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -1
- package/dist/index.d.ts +109 -1
- package/dist/index.js +109 -40
- package/dist/index.js.map +1 -1
- package/dist/migrations/index.d.ts +3 -0
- package/package.json +9 -6
- package/dist/migrations/sql/001_customers.sql +0 -111
- package/dist/migrations/sql/002_customers_sex.sql +0 -2
- package/dist/migrations/sql/003_customer_sequences.sql +0 -6
- package/dist/migrations/sql/004_customer_sequences_per_workspace.sql +0 -1
- package/dist/migrations/sql/005_drop_job_title.sql +0 -1
- package/dist/migrations/sql/006_unique_email_phone.sql +0 -23
- package/dist/migrations/sql/007_rename_archived_to_blacklisted.sql +0 -13
- package/dist/migrations/sql/008_blacklist_reason.sql +0 -2
- package/dist/migrations/sql/009_customer_relationships.sql +0 -25
- package/dist/migrations/sql/010_customer_labels.sql +0 -75
- package/dist/migrations/sql/011_label_fk_set_null.sql +0 -17
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, ...
|
|
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
|
-
...
|
|
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, ...
|
|
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
|
-
...
|
|
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
|
-
|
|
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
|
|
1665
|
-
if (typeof
|
|
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
|
|
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:
|
|
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
|
|
1874
|
-
if (typeof
|
|
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
|
|
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:
|
|
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
|
|
2129
|
-
const
|
|
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
|
|
2197
|
+
const label2 = customerLabelController(store);
|
|
2135
2198
|
return [
|
|
2136
2199
|
// ── Labels ───────────────────────────────────────────────────────
|
|
2137
|
-
["GET", "/customers/labels", import_middlewares.requireAuth, wsCtx,
|
|
2138
|
-
["DELETE", "/customers/labels/:labelId", import_middlewares.requireAuth, wsCtx,
|
|
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,
|
|
2149
|
-
["POST", "/customers/:customerId/emails", import_middlewares.requireAuth, wsCtx,
|
|
2150
|
-
["PATCH", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx,
|
|
2151
|
-
["PUT", "/customers/:customerId/emails/:emailId/primary", import_middlewares.requireAuth, wsCtx,
|
|
2152
|
-
["DELETE", "/customers/:customerId/emails/:emailId", import_middlewares.requireAuth, wsCtx,
|
|
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,
|
|
2155
|
-
["POST", "/customers/:customerId/phones", import_middlewares.requireAuth, wsCtx,
|
|
2156
|
-
["PATCH", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx,
|
|
2157
|
-
["PUT", "/customers/:customerId/phones/:phoneId/primary", import_middlewares.requireAuth, wsCtx,
|
|
2158
|
-
["DELETE", "/customers/:customerId/phones/:phoneId", import_middlewares.requireAuth, wsCtx,
|
|
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,
|