@fonderie/customers 1.1.0 → 1.1.1
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/brain/outcomes.md +189 -0
- package/brain/signatures.md +244 -0
- package/package.json +5 -4
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
<!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->
|
|
2
|
+
|
|
3
|
+
# @fonderie/customers — outcomes
|
|
4
|
+
|
|
5
|
+
What this package does to a running app: tables its migrations create,
|
|
6
|
+
rows it seeds, routes it registers. Generated from the migration SQL and
|
|
7
|
+
route tables in source — trust this file instead of reading `dist/` or
|
|
8
|
+
downloading tarballs.
|
|
9
|
+
|
|
10
|
+
## Database tables (after all migrations)
|
|
11
|
+
|
|
12
|
+
### `fonderie_addresses`
|
|
13
|
+
|
|
14
|
+
```sql
|
|
15
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
16
|
+
country_iso TEXT NOT NULL
|
|
17
|
+
subdivision1_iso TEXT
|
|
18
|
+
subdivision2_iso TEXT
|
|
19
|
+
zip_postal_code TEXT NOT NULL
|
|
20
|
+
line1 TEXT
|
|
21
|
+
line2 TEXT
|
|
22
|
+
unit TEXT
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### `fonderie_customer_addresses`
|
|
26
|
+
|
|
27
|
+
```sql
|
|
28
|
+
addr_id UUID NOT NULL REFERENCES fonderie_addresses(id) ON DELETE CASCADE
|
|
29
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
30
|
+
label TEXT NOT NULL DEFAULT 'service'
|
|
31
|
+
is_primary BOOLEAN NOT NULL DEFAULT false
|
|
32
|
+
label_id UUID REFERENCES fonderie_customer_labels(id)
|
|
33
|
+
CONSTRAINT fonderie_customer_addresses_label_id_fkey FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL
|
|
34
|
+
-- PRIMARY KEY (addr_id, customer_id)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### `fonderie_customer_emails`
|
|
38
|
+
|
|
39
|
+
```sql
|
|
40
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
41
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
42
|
+
email TEXT NOT NULL
|
|
43
|
+
label TEXT NOT NULL DEFAULT 'work'
|
|
44
|
+
is_primary BOOLEAN NOT NULL DEFAULT false
|
|
45
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
46
|
+
label_id UUID REFERENCES fonderie_customer_labels(id)
|
|
47
|
+
CONSTRAINT fonderie_customer_emails_label_id_fkey FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `fonderie_customer_labels`
|
|
51
|
+
|
|
52
|
+
```sql
|
|
53
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
54
|
+
type fonderie_customer_label_type NOT NULL
|
|
55
|
+
value TEXT NOT NULL
|
|
56
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
57
|
+
-- CONSTRAINT uq_fcl_type_value UNIQUE (type, value)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### `fonderie_customer_notes`
|
|
61
|
+
|
|
62
|
+
```sql
|
|
63
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
64
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
65
|
+
author_id UUID
|
|
66
|
+
body TEXT NOT NULL
|
|
67
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
68
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `fonderie_customer_phones`
|
|
72
|
+
|
|
73
|
+
```sql
|
|
74
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
75
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
76
|
+
phone TEXT NOT NULL
|
|
77
|
+
label TEXT NOT NULL DEFAULT 'mobile'
|
|
78
|
+
is_primary BOOLEAN NOT NULL DEFAULT false
|
|
79
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
80
|
+
label_id UUID REFERENCES fonderie_customer_labels(id)
|
|
81
|
+
CONSTRAINT fonderie_customer_phones_label_id_fkey FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### `fonderie_customer_relationships`
|
|
85
|
+
|
|
86
|
+
```sql
|
|
87
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
88
|
+
workspace_id UUID NOT NULL
|
|
89
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
90
|
+
related_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
91
|
+
relationship TEXT NOT NULL
|
|
92
|
+
is_primary BOOLEAN NOT NULL DEFAULT false
|
|
93
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
94
|
+
-- UNIQUE (customer_id, related_id)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### `fonderie_customer_sequences`
|
|
98
|
+
|
|
99
|
+
```sql
|
|
100
|
+
workspace_id UUID NOT NULL
|
|
101
|
+
prefix TEXT NOT NULL
|
|
102
|
+
next_val BIGINT NOT NULL DEFAULT 1
|
|
103
|
+
-- PRIMARY KEY (workspace_id, prefix)
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### `fonderie_customer_tags`
|
|
107
|
+
|
|
108
|
+
```sql
|
|
109
|
+
customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE
|
|
110
|
+
tag TEXT NOT NULL
|
|
111
|
+
-- PRIMARY KEY (customer_id, tag)
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### `fonderie_customers`
|
|
115
|
+
|
|
116
|
+
```sql
|
|
117
|
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid()
|
|
118
|
+
workspace_id UUID NOT NULL
|
|
119
|
+
type TEXT NOT NULL DEFAULT 'individual'
|
|
120
|
+
first_name TEXT
|
|
121
|
+
last_name TEXT
|
|
122
|
+
company_name TEXT
|
|
123
|
+
avatar_url TEXT
|
|
124
|
+
locale TEXT NOT NULL DEFAULT 'en-US'
|
|
125
|
+
reference_code TEXT
|
|
126
|
+
is_blacklisted BOOLEAN NOT NULL DEFAULT false
|
|
127
|
+
created_by UUID
|
|
128
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
129
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
|
130
|
+
sex TEXT NOT NULL DEFAULT 'UNKNOWN'
|
|
131
|
+
blacklist_reason TEXT
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Raw SQL ships in `node_modules/@fonderie/customers/dist/migrations/sql/` — read it there if you must; never download tarballs.
|
|
135
|
+
|
|
136
|
+
## Seeded rows (behavioral contract)
|
|
137
|
+
|
|
138
|
+
```sql
|
|
139
|
+
INSERT INTO fonderie_customer_labels (type, value) VALUES ('email', 'work'), ('email', 'personal'), ('email', 'billing'), ('phone', 'mobile'), ('phone', 'office'), ('phone', 'home'), ('phone', 'fax'), ('address', 'service'), ('address', 'billing'), ('address', 'other') ON CONFLICT (type, value) DO NOTHING;
|
|
140
|
+
INSERT INTO fonderie_customer_labels (type, value) SELECT DISTINCT 'email'::fonderie_customer_label_type, label FROM fonderie_customer_emails WHERE label IS NOT NULL ON CONFLICT (type, value) DO NOTHING;
|
|
141
|
+
INSERT INTO fonderie_customer_labels (type, value) SELECT DISTINCT 'phone'::fonderie_customer_label_type, label FROM fonderie_customer_phones WHERE label IS NOT NULL ON CONFLICT (type, value) DO NOTHING;
|
|
142
|
+
INSERT INTO fonderie_customer_labels (type, value) SELECT DISTINCT 'address'::fonderie_customer_label_type, label FROM fonderie_customer_addresses WHERE label IS NOT NULL ON CONFLICT (type, value) DO NOTHING;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## HTTP routes registered
|
|
146
|
+
|
|
147
|
+
| Method | Path | Middleware chain (auth / validation / handler) |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| GET | `/customers` | `requireAuth → wsCtx → customer.list` |
|
|
150
|
+
| POST | `/customers` | `requireAuth → wsCtx → validate(createCustomerSchema) → customer.create` |
|
|
151
|
+
| DELETE | `/customers/:customerId` | `requireAuth → wsCtx → customer.delete` |
|
|
152
|
+
| GET | `/customers/:customerId` | `requireAuth → wsCtx → customer.get` |
|
|
153
|
+
| PUT | `/customers/:customerId` | `requireAuth → wsCtx → validate(updateCustomerSchema) → customer.update` |
|
|
154
|
+
| GET | `/customers/:customerId/addresses` | `requireAuth → wsCtx → address.list` |
|
|
155
|
+
| POST | `/customers/:customerId/addresses` | `requireAuth → wsCtx → validate(addAddressSchema) → address.add` |
|
|
156
|
+
| DELETE | `/customers/:customerId/addresses/:addrId` | `requireAuth → wsCtx → address.remove` |
|
|
157
|
+
| PATCH | `/customers/:customerId/addresses/:addrId` | `requireAuth → wsCtx → validate(updateAddressSchema) → address.update` |
|
|
158
|
+
| PUT | `/customers/:customerId/addresses/:addrId/primary` | `requireAuth → wsCtx → address.setPrimary` |
|
|
159
|
+
| POST | `/customers/:customerId/blacklist` | `requireAuth → wsCtx → validate(blacklistSchema) → customer.blacklist` |
|
|
160
|
+
| GET | `/customers/:customerId/emails` | `requireAuth → wsCtx → email.list` |
|
|
161
|
+
| POST | `/customers/:customerId/emails` | `requireAuth → wsCtx → validate(addEmailSchema) → email.add` |
|
|
162
|
+
| DELETE | `/customers/:customerId/emails/:emailId` | `requireAuth → wsCtx → email.remove` |
|
|
163
|
+
| PATCH | `/customers/:customerId/emails/:emailId` | `requireAuth → wsCtx → validate(updateEmailSchema) → email.update` |
|
|
164
|
+
| PUT | `/customers/:customerId/emails/:emailId/primary` | `requireAuth → wsCtx → email.setPrimary` |
|
|
165
|
+
| GET | `/customers/:customerId/notes` | `requireAuth → wsCtx → note.list` |
|
|
166
|
+
| POST | `/customers/:customerId/notes` | `requireAuth → wsCtx → validate(noteSchema) → note.create` |
|
|
167
|
+
| DELETE | `/customers/:customerId/notes/:noteId` | `requireAuth → wsCtx → note.delete` |
|
|
168
|
+
| PUT | `/customers/:customerId/notes/:noteId` | `requireAuth → wsCtx → validate(noteSchema) → note.update` |
|
|
169
|
+
| GET | `/customers/:customerId/phones` | `requireAuth → wsCtx → phone.list` |
|
|
170
|
+
| POST | `/customers/:customerId/phones` | `requireAuth → wsCtx → validate(addPhoneSchema) → phone.add` |
|
|
171
|
+
| DELETE | `/customers/:customerId/phones/:phoneId` | `requireAuth → wsCtx → phone.remove` |
|
|
172
|
+
| PATCH | `/customers/:customerId/phones/:phoneId` | `requireAuth → wsCtx → validate(updatePhoneSchema) → phone.update` |
|
|
173
|
+
| PUT | `/customers/:customerId/phones/:phoneId/primary` | `requireAuth → wsCtx → phone.setPrimary` |
|
|
174
|
+
| GET | `/customers/:customerId/relationships` | `requireAuth → wsCtx → relationship.list` |
|
|
175
|
+
| POST | `/customers/:customerId/relationships` | `requireAuth → wsCtx → validate(addRelationshipSchema) → relationship.add` |
|
|
176
|
+
| DELETE | `/customers/:customerId/relationships/:relatedId` | `requireAuth → wsCtx → relationship.remove` |
|
|
177
|
+
| PUT | `/customers/:customerId/relationships/:relatedId/primary` | `requireAuth → wsCtx → relationship.setPrimary` |
|
|
178
|
+
| GET | `/customers/:customerId/tags` | `requireAuth → wsCtx → tag.list` |
|
|
179
|
+
| POST | `/customers/:customerId/tags` | `requireAuth → wsCtx → validate(addTagSchema) → tag.add` |
|
|
180
|
+
| DELETE | `/customers/:customerId/tags/:tag` | `requireAuth → wsCtx → tag.remove` |
|
|
181
|
+
| POST | `/customers/:customerId/unblacklist` | `requireAuth → wsCtx → customer.unblacklist` |
|
|
182
|
+
| GET | `/customers/labels` | `requireAuth → wsCtx → label.list` |
|
|
183
|
+
| DELETE | `/customers/labels/:labelId` | `requireAuth → wsCtx → label.remove` |
|
|
184
|
+
|
|
185
|
+
## Migration statements not replayed (verify in raw SQL)
|
|
186
|
+
|
|
187
|
+
- `END IF`
|
|
188
|
+
- `END $$`
|
|
189
|
+
- `CREATE TYPE fonderie_customer_label_type AS ENUM ('email', 'phone', 'address')`
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
<!-- GENERATED — do not edit. Regenerate with: npm run docs:signatures -->
|
|
2
|
+
|
|
3
|
+
# @fonderie/customers — signatures
|
|
4
|
+
|
|
5
|
+
## @fonderie/customers
|
|
6
|
+
|
|
7
|
+
Subpath exports: `@fonderie/customers/types`, `@fonderie/customers/migrations`
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
type CustomersEventKey = (typeof EVENT_KEYS)[keyof typeof EVENT_KEYS];
|
|
11
|
+
|
|
12
|
+
type ICustomersConfig = {
|
|
13
|
+
referenceCodePrefix?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const EVENT_KEYS: { readonly customerCreated: "fonderie.customer.created"; readonly customerUpdated: "fonderie.customer.updated"; readonly customerDeleted: "fonderie.customer.deleted"; readonly customerBlacklisted: "fonderie.customer.blacklisted"; readonly customerUnblacklisted: "fonderie.customer.unblacklisted"; }
|
|
17
|
+
|
|
18
|
+
interface IAddressDTO {
|
|
19
|
+
countryIso: string;
|
|
20
|
+
subdivision1Iso: string;
|
|
21
|
+
subdivision2Iso: string;
|
|
22
|
+
zipPostalCode: string;
|
|
23
|
+
unit: string;
|
|
24
|
+
line1: string;
|
|
25
|
+
line2: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface ICustomerAddressDTO {
|
|
29
|
+
id: string;
|
|
30
|
+
label: string;
|
|
31
|
+
isPrimary: boolean;
|
|
32
|
+
address: IAddressDTO;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface ICustomerDetailDTO extends ICustomerDTO {
|
|
36
|
+
emails: ICustomerEmailDTO[];
|
|
37
|
+
phones: ICustomerPhoneDTO[];
|
|
38
|
+
addresses: ICustomerAddressDTO[];
|
|
39
|
+
notes: ICustomerNoteDTO[];
|
|
40
|
+
relationships: ICustomerRelationshipExpandedDTO[];
|
|
41
|
+
tags: string[];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ICustomerDTO {
|
|
45
|
+
id: string;
|
|
46
|
+
type: string;
|
|
47
|
+
sex: CustomerSex;
|
|
48
|
+
firstName: string;
|
|
49
|
+
lastName: string;
|
|
50
|
+
companyName: string;
|
|
51
|
+
avatarUrl: string;
|
|
52
|
+
locale: string;
|
|
53
|
+
referenceCode: string;
|
|
54
|
+
blacklisted: {
|
|
55
|
+
status: boolean;
|
|
56
|
+
reason: string | null;
|
|
57
|
+
};
|
|
58
|
+
createdBy: string;
|
|
59
|
+
createdAt: string;
|
|
60
|
+
updatedAt: string;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
interface ICustomerEmailDTO {
|
|
64
|
+
id: string;
|
|
65
|
+
email: string;
|
|
66
|
+
label: string;
|
|
67
|
+
isPrimary: boolean;
|
|
68
|
+
createdAt: string;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
interface ICustomerNoteDTO {
|
|
72
|
+
id: string;
|
|
73
|
+
authorId: string;
|
|
74
|
+
body: string;
|
|
75
|
+
createdAt: string;
|
|
76
|
+
updatedAt: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
interface ICustomerPhoneDTO {
|
|
80
|
+
id: string;
|
|
81
|
+
phone: string;
|
|
82
|
+
label: string;
|
|
83
|
+
isPrimary: boolean;
|
|
84
|
+
createdAt: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface ICustomerTagDTO {
|
|
88
|
+
tag: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function toAddressDTO(a: IAddress): IAddressDTO
|
|
92
|
+
|
|
93
|
+
function toCustomerAddressDTO(ca: ICustomerAddress): ICustomerAddressDTO
|
|
94
|
+
|
|
95
|
+
function toCustomerDetailDTO(c: ICustomerDetail): ICustomerDetailDTO
|
|
96
|
+
|
|
97
|
+
function toCustomerDTO(c: ICustomer): ICustomerDTO
|
|
98
|
+
|
|
99
|
+
function toCustomerEmailDTO(e: ICustomerEmail): ICustomerEmailDTO
|
|
100
|
+
|
|
101
|
+
function toCustomerNoteDTO(n: ICustomerNote): ICustomerNoteDTO
|
|
102
|
+
|
|
103
|
+
function toCustomerPhoneDTO(p: ICustomerPhone): ICustomerPhoneDTO
|
|
104
|
+
|
|
105
|
+
function toCustomerTagDTO(t: ICustomerTag): ICustomerTagDTO
|
|
106
|
+
|
|
107
|
+
new CustomerAddressModel(store: IStoreAdapter): CustomerAddressModel
|
|
108
|
+
.list(customerId: string): Promise<ICustomerAddress[]>
|
|
109
|
+
.add(opts: { customerId: string; countryIso: string; subdivision1Iso?: string | null; subdivision2Iso?: string | null; zipPostalCode: string; unit?: string | null; line1?: string | null; line2?: string | null; labelId: string; isPrimary?: boolean; }): Promise<...>
|
|
110
|
+
.updateLabel(addrId: string, customerId: string, labelId: string): Promise<ICustomerAddress>
|
|
111
|
+
.setPrimary(addrId: string, customerId: string): Promise<void>
|
|
112
|
+
.remove(addrId: string, customerId: string): Promise<void>
|
|
113
|
+
|
|
114
|
+
new CustomerEmailModel(store: IStoreAdapter): CustomerEmailModel
|
|
115
|
+
.list(customerId: string): Promise<ICustomerEmail[]>
|
|
116
|
+
.add(opts: { customerId: string; email: string; labelId: string; isPrimary?: boolean; }): Promise<ICustomerEmail>
|
|
117
|
+
.updateLabel(emailId: string, customerId: string, labelId: string): Promise<ICustomerEmail>
|
|
118
|
+
.setPrimary(emailId: string, customerId: string): Promise<void>
|
|
119
|
+
.remove(emailId: string, customerId: string): Promise<void>
|
|
120
|
+
|
|
121
|
+
new CustomerModel(store: IStoreAdapter): CustomerModel
|
|
122
|
+
.list(opts: ListCustomersOpts): Promise<ICustomer[]>
|
|
123
|
+
.findById(id: string, workspaceId: string): Promise<ICustomer | null>
|
|
124
|
+
.findDetail(id: string, workspaceId: string, depth: 2): Promise<ICustomerDetailD2 | null>
|
|
125
|
+
.create(opts: CreateCustomerOpts): Promise<ICustomer>
|
|
126
|
+
.update(id: string, workspaceId: string, opts: UpdateCustomerOpts, referenceCodePrefix?: string): Promise<ICustomer | null>
|
|
127
|
+
.delete(id: string, workspaceId: string): Promise<void>
|
|
128
|
+
.blacklist(id: string, workspaceId: string, reason?: string | null | undefined): Promise<void>
|
|
129
|
+
.unblacklist(id: string, workspaceId: string): Promise<void>
|
|
130
|
+
|
|
131
|
+
new CustomerNoteModel(store: IStoreAdapter): CustomerNoteModel
|
|
132
|
+
.list(customerId: string): Promise<ICustomerNote[]>
|
|
133
|
+
.create(opts: { customerId: string; authorId?: string | null; body: string; }): Promise<ICustomerNote>
|
|
134
|
+
.update(noteId: string, customerId: string, body: string): Promise<ICustomerNote | null>
|
|
135
|
+
.delete(noteId: string, customerId: string): Promise<void>
|
|
136
|
+
|
|
137
|
+
new CustomerPhoneModel(store: IStoreAdapter): CustomerPhoneModel
|
|
138
|
+
.list(customerId: string): Promise<ICustomerPhone[]>
|
|
139
|
+
.add(opts: { customerId: string; phone: string; labelId: string; isPrimary?: boolean; }): Promise<ICustomerPhone>
|
|
140
|
+
.updateLabel(phoneId: string, customerId: string, labelId: string): Promise<ICustomerPhone>
|
|
141
|
+
.setPrimary(phoneId: string, customerId: string): Promise<void>
|
|
142
|
+
.remove(phoneId: string, customerId: string): Promise<void>
|
|
143
|
+
|
|
144
|
+
new CustomerTagModel(store: IStoreAdapter): CustomerTagModel
|
|
145
|
+
.list(customerId: string): Promise<string[]>
|
|
146
|
+
.add(customerId: string, tag: string): Promise<void>
|
|
147
|
+
.remove(customerId: string, tag: string): Promise<void>
|
|
148
|
+
|
|
149
|
+
new CustomersModule(store: IStoreAdapter, config?: ICustomersConfig, bus?: EventBus | undefined): CustomersModule
|
|
150
|
+
.name: "@fonderie/customers"
|
|
151
|
+
.deps: string[]
|
|
152
|
+
.install(app: IFonderieApp): void
|
|
153
|
+
|
|
154
|
+
type AddressLabel = 'service' | 'billing' | 'other';
|
|
155
|
+
|
|
156
|
+
type CustomerType = 'individual' | 'business';
|
|
157
|
+
|
|
158
|
+
type EmailLabel = 'work' | 'personal' | 'billing';
|
|
159
|
+
|
|
160
|
+
interface IAddress {
|
|
161
|
+
id: string;
|
|
162
|
+
countryIso: string;
|
|
163
|
+
subdivision1Iso: string | null;
|
|
164
|
+
subdivision2Iso: string | null;
|
|
165
|
+
zipPostalCode: string;
|
|
166
|
+
unit: string | null;
|
|
167
|
+
line1: string | null;
|
|
168
|
+
line2: string | null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
interface ICustomer {
|
|
172
|
+
id: string;
|
|
173
|
+
workspaceId: string;
|
|
174
|
+
type: CustomerType;
|
|
175
|
+
sex: CustomerSex;
|
|
176
|
+
firstName: string | null;
|
|
177
|
+
lastName: string | null;
|
|
178
|
+
companyName: string | null;
|
|
179
|
+
avatarUrl: string | null;
|
|
180
|
+
locale: string;
|
|
181
|
+
referenceCode: string | null;
|
|
182
|
+
isBlacklisted: boolean;
|
|
183
|
+
blacklistReason: string | null;
|
|
184
|
+
createdBy: string | null;
|
|
185
|
+
createdAt: string;
|
|
186
|
+
updatedAt: string;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
interface ICustomerAddress {
|
|
190
|
+
addrId: string;
|
|
191
|
+
customerId: string;
|
|
192
|
+
labelId: string;
|
|
193
|
+
label: string;
|
|
194
|
+
isPrimary: boolean;
|
|
195
|
+
address: IAddress;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
interface ICustomerDetail extends ICustomer {
|
|
199
|
+
emails: ICustomerEmail[];
|
|
200
|
+
phones: ICustomerPhone[];
|
|
201
|
+
addresses: ICustomerAddress[];
|
|
202
|
+
notes: ICustomerNote[];
|
|
203
|
+
relationships: ICustomerRelationshipExpanded[];
|
|
204
|
+
tags: string[];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface ICustomerEmail {
|
|
208
|
+
id: string;
|
|
209
|
+
customerId: string;
|
|
210
|
+
email: string;
|
|
211
|
+
labelId: string;
|
|
212
|
+
label: string;
|
|
213
|
+
isPrimary: boolean;
|
|
214
|
+
createdAt: string;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
interface ICustomerNote {
|
|
218
|
+
id: string;
|
|
219
|
+
customerId: string;
|
|
220
|
+
authorId: string | null;
|
|
221
|
+
body: string;
|
|
222
|
+
createdAt: string;
|
|
223
|
+
updatedAt: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
interface ICustomerPhone {
|
|
227
|
+
id: string;
|
|
228
|
+
customerId: string;
|
|
229
|
+
phone: string;
|
|
230
|
+
labelId: string;
|
|
231
|
+
label: string;
|
|
232
|
+
isPrimary: boolean;
|
|
233
|
+
createdAt: string;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
interface ICustomerTag {
|
|
237
|
+
customerId: string;
|
|
238
|
+
tag: string;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
type PhoneLabel = 'mobile' | 'office' | 'home' | 'fax';
|
|
242
|
+
|
|
243
|
+
namespace schemas — exports: addAddressSchema, addEmailSchema, addPhoneSchema, addRelationshipSchema, addTagSchema, blacklistSchema, createCustomerSchema, noteSchema, updateAddressSchema, updateCustomerSchema, updateEmailSchema, updatePhoneSchema
|
|
244
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fonderie/customers",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Workspace-scoped customer records — individuals and businesses with multiple emails, phones, addresses, notes, and tags.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fonderie-js",
|
|
@@ -70,17 +70,18 @@
|
|
|
70
70
|
},
|
|
71
71
|
"files": [
|
|
72
72
|
"dist",
|
|
73
|
+
"brain",
|
|
73
74
|
"LICENSE",
|
|
74
75
|
"README.md"
|
|
75
76
|
],
|
|
76
77
|
"repository": {
|
|
77
78
|
"type": "git",
|
|
78
|
-
"url": "git+https://github.com/
|
|
79
|
+
"url": "git+https://github.com/fonderiejs/sdk.git",
|
|
79
80
|
"directory": "packages/customers"
|
|
80
81
|
},
|
|
81
|
-
"homepage": "https://github.com/
|
|
82
|
+
"homepage": "https://github.com/fonderiejs/sdk/tree/main/packages/customers#readme",
|
|
82
83
|
"bugs": {
|
|
83
|
-
"url": "https://github.com/
|
|
84
|
+
"url": "https://github.com/fonderiejs/sdk/issues"
|
|
84
85
|
},
|
|
85
86
|
"dependencies": {
|
|
86
87
|
"zod": "^4.4.3"
|