@fonderie/customers 1.1.2 → 2.0.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fonderie/customers",
3
- "version": "1.1.2",
3
+ "version": "2.0.0",
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",
@@ -42,10 +42,10 @@
42
42
  "check": "biome check --write src"
43
43
  },
44
44
  "peerDependencies": {
45
- "@fonderie/core": "^0.1.1",
46
- "@fonderie/events": "^1.0.1",
47
- "@fonderie/store": "^0.1.1",
48
- "@fonderie/workspaces": "^1.0.1"
45
+ "@fonderie/core": "^1.0.0",
46
+ "@fonderie/events": "^2.0.0",
47
+ "@fonderie/store": "^1.0.0",
48
+ "@fonderie/workspaces": "^2.0.0"
49
49
  },
50
50
  "peerDependenciesMeta": {
51
51
  "@fonderie/events": {
@@ -76,12 +76,12 @@
76
76
  ],
77
77
  "repository": {
78
78
  "type": "git",
79
- "url": "git+https://github.com/fonderiejs/sdk.git",
79
+ "url": "git+https://github.com/fonderie-js/sdk.git",
80
80
  "directory": "packages/customers"
81
81
  },
82
- "homepage": "https://github.com/fonderiejs/sdk/tree/main/packages/customers#readme",
82
+ "homepage": "https://github.com/fonderie-js/sdk/tree/main/packages/customers#readme",
83
83
  "bugs": {
84
- "url": "https://github.com/fonderiejs/sdk/issues"
84
+ "url": "https://github.com/fonderie-js/sdk/issues"
85
85
  },
86
86
  "dependencies": {
87
87
  "zod": "^4.4.3"
@@ -1,111 +0,0 @@
1
- -- fonderie_customers
2
- CREATE TABLE IF NOT EXISTS fonderie_customers (
3
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
4
- workspace_id UUID NOT NULL,
5
- type TEXT NOT NULL DEFAULT 'individual',
6
- first_name TEXT,
7
- last_name TEXT,
8
- company_name TEXT,
9
- job_title TEXT,
10
- avatar_url TEXT,
11
- locale TEXT NOT NULL DEFAULT 'en-US',
12
- reference_code TEXT,
13
- is_blacklisted BOOLEAN NOT NULL DEFAULT false,
14
- created_by UUID,
15
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
16
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
17
- );
18
-
19
- CREATE INDEX IF NOT EXISTS idx_fc_workspace
20
- ON fonderie_customers (workspace_id);
21
-
22
- CREATE INDEX IF NOT EXISTS idx_fc_workspace_blacklisted
23
- ON fonderie_customers (workspace_id, is_blacklisted);
24
-
25
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fc_reference_code
26
- ON fonderie_customers (workspace_id, reference_code)
27
- WHERE reference_code IS NOT NULL;
28
-
29
- -- fonderie_addresses (shared; created IF NOT EXISTS so another package can also define it)
30
- CREATE TABLE IF NOT EXISTS fonderie_addresses (
31
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
32
- country_iso TEXT NOT NULL,
33
- subdivision1_iso TEXT,
34
- subdivision2_iso TEXT,
35
- zip_postal_code TEXT NOT NULL,
36
- line1 TEXT,
37
- line2 TEXT
38
- );
39
-
40
- -- fonderie_customer_emails
41
- CREATE TABLE IF NOT EXISTS fonderie_customer_emails (
42
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
43
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
44
- email TEXT NOT NULL,
45
- label TEXT NOT NULL DEFAULT 'work',
46
- is_primary BOOLEAN NOT NULL DEFAULT false,
47
- created_at TIMESTAMPTZ NOT NULL DEFAULT now()
48
- );
49
-
50
- CREATE INDEX IF NOT EXISTS idx_fce_customer
51
- ON fonderie_customer_emails (customer_id);
52
-
53
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fce_primary
54
- ON fonderie_customer_emails (customer_id)
55
- WHERE is_primary = true;
56
-
57
- -- fonderie_customer_phones
58
- CREATE TABLE IF NOT EXISTS fonderie_customer_phones (
59
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
60
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
61
- phone TEXT NOT NULL,
62
- label TEXT NOT NULL DEFAULT 'mobile',
63
- is_primary BOOLEAN NOT NULL DEFAULT false,
64
- created_at TIMESTAMPTZ NOT NULL DEFAULT now()
65
- );
66
-
67
- CREATE INDEX IF NOT EXISTS idx_fcp_customer
68
- ON fonderie_customer_phones (customer_id);
69
-
70
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fcp_primary
71
- ON fonderie_customer_phones (customer_id)
72
- WHERE is_primary = true;
73
-
74
- -- fonderie_customer_addresses (junction)
75
- CREATE TABLE IF NOT EXISTS fonderie_customer_addresses (
76
- addr_id UUID NOT NULL REFERENCES fonderie_addresses(id) ON DELETE CASCADE,
77
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
78
- label TEXT NOT NULL DEFAULT 'service',
79
- is_primary BOOLEAN NOT NULL DEFAULT false,
80
- PRIMARY KEY (addr_id, customer_id)
81
- );
82
-
83
- CREATE INDEX IF NOT EXISTS idx_fca_customer
84
- ON fonderie_customer_addresses (customer_id);
85
-
86
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fca_primary
87
- ON fonderie_customer_addresses (customer_id)
88
- WHERE is_primary = true;
89
-
90
- -- fonderie_customer_notes
91
- CREATE TABLE IF NOT EXISTS fonderie_customer_notes (
92
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
93
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
94
- author_id UUID,
95
- body TEXT NOT NULL,
96
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
97
- updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
98
- );
99
-
100
- CREATE INDEX IF NOT EXISTS idx_fcn_customer
101
- ON fonderie_customer_notes (customer_id);
102
-
103
- -- fonderie_customer_tags
104
- CREATE TABLE IF NOT EXISTS fonderie_customer_tags (
105
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
106
- tag TEXT NOT NULL,
107
- PRIMARY KEY (customer_id, tag)
108
- );
109
-
110
- CREATE INDEX IF NOT EXISTS idx_fct_tag
111
- ON fonderie_customer_tags (tag);
@@ -1,2 +0,0 @@
1
- ALTER TABLE fonderie_customers
2
- ADD COLUMN IF NOT EXISTS sex TEXT NOT NULL DEFAULT 'UNKNOWN';
@@ -1,6 +0,0 @@
1
- CREATE TABLE IF NOT EXISTS fonderie_customer_sequences (
2
- workspace_id UUID NOT NULL,
3
- prefix TEXT NOT NULL,
4
- next_val BIGINT NOT NULL DEFAULT 1,
5
- PRIMARY KEY (workspace_id, prefix)
6
- );
@@ -1 +0,0 @@
1
- -- No-op: sequence table stays (workspace_id, prefix) — per-prefix counters are intentional.
@@ -1 +0,0 @@
1
- ALTER TABLE fonderie_customers DROP COLUMN IF EXISTS job_title;
@@ -1,23 +0,0 @@
1
- -- Remove duplicate emails per customer, keeping the primary or the oldest row.
2
- DELETE FROM fonderie_customer_emails
3
- WHERE id NOT IN (
4
- SELECT DISTINCT ON (customer_id, email)
5
- id
6
- FROM fonderie_customer_emails
7
- ORDER BY customer_id, email, is_primary DESC, created_at ASC
8
- );
9
-
10
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fce_unique_email
11
- ON fonderie_customer_emails (customer_id, email);
12
-
13
- -- Remove duplicate phones per customer, keeping the primary or the oldest row.
14
- DELETE FROM fonderie_customer_phones
15
- WHERE id NOT IN (
16
- SELECT DISTINCT ON (customer_id, phone)
17
- id
18
- FROM fonderie_customer_phones
19
- ORDER BY customer_id, phone, is_primary DESC, created_at ASC
20
- );
21
-
22
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fcp_unique_phone
23
- ON fonderie_customer_phones (customer_id, phone);
@@ -1,13 +0,0 @@
1
- DO $$
2
- BEGIN
3
- IF EXISTS (
4
- SELECT 1 FROM information_schema.columns
5
- WHERE table_name = 'fonderie_customers' AND column_name = 'is_archived'
6
- ) THEN
7
- ALTER TABLE fonderie_customers RENAME COLUMN is_archived TO is_blacklisted;
8
- END IF;
9
- END $$;
10
-
11
- DROP INDEX IF EXISTS idx_fc_workspace_archived;
12
- CREATE INDEX IF NOT EXISTS idx_fc_workspace_blacklisted
13
- ON fonderie_customers (workspace_id, is_blacklisted);
@@ -1,2 +0,0 @@
1
- ALTER TABLE fonderie_customers
2
- ADD COLUMN IF NOT EXISTS blacklist_reason TEXT;
@@ -1,25 +0,0 @@
1
- -- Unit number on shared addresses table
2
- ALTER TABLE fonderie_addresses
3
- ADD COLUMN IF NOT EXISTS unit TEXT;
4
-
5
- -- Links two customers with a typed, directional relationship
6
- CREATE TABLE IF NOT EXISTS fonderie_customer_relationships (
7
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
8
- workspace_id UUID NOT NULL,
9
- customer_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
10
- related_id UUID NOT NULL REFERENCES fonderie_customers(id) ON DELETE CASCADE,
11
- relationship TEXT NOT NULL,
12
- is_primary BOOLEAN NOT NULL DEFAULT false,
13
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
14
- UNIQUE (customer_id, related_id)
15
- );
16
-
17
- CREATE INDEX IF NOT EXISTS idx_fcrel_customer
18
- ON fonderie_customer_relationships (customer_id);
19
-
20
- CREATE INDEX IF NOT EXISTS idx_fcrel_related
21
- ON fonderie_customer_relationships (related_id);
22
-
23
- CREATE UNIQUE INDEX IF NOT EXISTS idx_fcrel_primary
24
- ON fonderie_customer_relationships (customer_id)
25
- WHERE is_primary = true;
@@ -1,75 +0,0 @@
1
- -- fonderie_customer_label_type enum
2
- CREATE TYPE fonderie_customer_label_type AS ENUM ('email', 'phone', 'address');
3
-
4
- -- shared label catalog
5
- CREATE TABLE IF NOT EXISTS fonderie_customer_labels (
6
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
7
- type fonderie_customer_label_type NOT NULL,
8
- value TEXT NOT NULL,
9
- created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
10
- CONSTRAINT uq_fcl_type_value UNIQUE (type, value)
11
- );
12
-
13
- -- seed defaults
14
- INSERT INTO fonderie_customer_labels (type, value) VALUES
15
- ('email', 'work'),
16
- ('email', 'personal'),
17
- ('email', 'billing'),
18
- ('phone', 'mobile'),
19
- ('phone', 'office'),
20
- ('phone', 'home'),
21
- ('phone', 'fax'),
22
- ('address', 'service'),
23
- ('address', 'billing'),
24
- ('address', 'other')
25
- ON CONFLICT (type, value) DO NOTHING;
26
-
27
- -- promote any non-standard values already stored in existing rows
28
- INSERT INTO fonderie_customer_labels (type, value)
29
- SELECT DISTINCT 'email'::fonderie_customer_label_type, label
30
- FROM fonderie_customer_emails
31
- WHERE label IS NOT NULL
32
- ON CONFLICT (type, value) DO NOTHING;
33
-
34
- INSERT INTO fonderie_customer_labels (type, value)
35
- SELECT DISTINCT 'phone'::fonderie_customer_label_type, label
36
- FROM fonderie_customer_phones
37
- WHERE label IS NOT NULL
38
- ON CONFLICT (type, value) DO NOTHING;
39
-
40
- INSERT INTO fonderie_customer_labels (type, value)
41
- SELECT DISTINCT 'address'::fonderie_customer_label_type, label
42
- FROM fonderie_customer_addresses
43
- WHERE label IS NOT NULL
44
- ON CONFLICT (type, value) DO NOTHING;
45
-
46
- -- add label_id FK columns
47
- ALTER TABLE fonderie_customer_emails
48
- ADD COLUMN IF NOT EXISTS label_id UUID REFERENCES fonderie_customer_labels(id);
49
-
50
- ALTER TABLE fonderie_customer_phones
51
- ADD COLUMN IF NOT EXISTS label_id UUID REFERENCES fonderie_customer_labels(id);
52
-
53
- ALTER TABLE fonderie_customer_addresses
54
- ADD COLUMN IF NOT EXISTS label_id UUID REFERENCES fonderie_customer_labels(id);
55
-
56
- -- backfill label_id from existing label text
57
- UPDATE fonderie_customer_emails e
58
- SET label_id = l.id
59
- FROM fonderie_customer_labels l
60
- WHERE l.type = 'email' AND l.value = e.label;
61
-
62
- UPDATE fonderie_customer_phones p
63
- SET label_id = l.id
64
- FROM fonderie_customer_labels l
65
- WHERE l.type = 'phone' AND l.value = p.label;
66
-
67
- UPDATE fonderie_customer_addresses a
68
- SET label_id = l.id
69
- FROM fonderie_customer_labels l
70
- WHERE l.type = 'address' AND l.value = a.label;
71
-
72
- -- mark old text columns as deprecated
73
- COMMENT ON COLUMN fonderie_customer_emails.label IS 'deprecated: use label_id → fonderie_customer_labels';
74
- COMMENT ON COLUMN fonderie_customer_phones.label IS 'deprecated: use label_id → fonderie_customer_labels';
75
- COMMENT ON COLUMN fonderie_customer_addresses.label IS 'deprecated: use label_id → fonderie_customer_labels';
@@ -1,17 +0,0 @@
1
- -- Allow label catalog entries to be deleted even when in use.
2
- -- Affected phone/email/address rows keep their label text column; label_id becomes NULL.
3
-
4
- ALTER TABLE fonderie_customer_phones
5
- DROP CONSTRAINT IF EXISTS fonderie_customer_phones_label_id_fkey,
6
- ADD CONSTRAINT fonderie_customer_phones_label_id_fkey
7
- FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL;
8
-
9
- ALTER TABLE fonderie_customer_emails
10
- DROP CONSTRAINT IF EXISTS fonderie_customer_emails_label_id_fkey,
11
- ADD CONSTRAINT fonderie_customer_emails_label_id_fkey
12
- FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL;
13
-
14
- ALTER TABLE fonderie_customer_addresses
15
- DROP CONSTRAINT IF EXISTS fonderie_customer_addresses_label_id_fkey,
16
- ADD CONSTRAINT fonderie_customer_addresses_label_id_fkey
17
- FOREIGN KEY (label_id) REFERENCES fonderie_customer_labels(id) ON DELETE SET NULL;