@aiquants/contact-map 0.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/LICENSE +21 -0
- package/README.md +130 -0
- package/dist/client.d.mts +399 -0
- package/dist/client.d.ts +399 -0
- package/dist/client.js +2 -0
- package/dist/client.mjs +2 -0
- package/dist/index.d.mts +267 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.js +1 -0
- package/dist/index.mjs +1 -0
- package/dist/server.d.mts +89 -0
- package/dist/server.d.ts +89 -0
- package/dist/server.js +4 -0
- package/dist/server.mjs +4 -0
- package/dist/styles/contact-map.standalone.css +3 -0
- package/dist/tree-types-Dl6iBQze.d.mts +37 -0
- package/dist/tree-types-Dl6iBQze.d.ts +37 -0
- package/dist/wire-BxEK32O0.d.mts +148 -0
- package/dist/wire-BxEK32O0.d.ts +148 -0
- package/dist/worker/treeWorker.mjs +1 -0
- package/package.json +132 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
interface ContactRecord {
|
|
2
|
+
person_id: number;
|
|
3
|
+
person_id_redirect_to?: number | null;
|
|
4
|
+
full_name: string | null;
|
|
5
|
+
full_name_reading?: string | null;
|
|
6
|
+
company_name: string | null;
|
|
7
|
+
company_name_reading?: string | null;
|
|
8
|
+
department: string | null;
|
|
9
|
+
title: string | null;
|
|
10
|
+
address?: string | null;
|
|
11
|
+
postal_code?: string | null;
|
|
12
|
+
email?: string | null;
|
|
13
|
+
custom_email?: string | null;
|
|
14
|
+
company_phone_number?: string | null;
|
|
15
|
+
custom_company_phone_number?: string | null;
|
|
16
|
+
company_fax_number?: string | null;
|
|
17
|
+
mobile_phone_number?: string | null;
|
|
18
|
+
custom_mobile_phone_number?: string | null;
|
|
19
|
+
url?: string | null;
|
|
20
|
+
contacted_at: string | Date | null;
|
|
21
|
+
contacted_by?: string | null;
|
|
22
|
+
is_in_eight?: boolean | null;
|
|
23
|
+
is_contact_synced?: boolean | null;
|
|
24
|
+
is_active: boolean;
|
|
25
|
+
is_incomplete?: boolean | null;
|
|
26
|
+
created_at?: string | Date;
|
|
27
|
+
created_by?: string;
|
|
28
|
+
updated_at?: string | Date;
|
|
29
|
+
updated_by?: string;
|
|
30
|
+
}
|
|
31
|
+
type ContactMapStreamPhase = "idle" | "streaming" | "retrying" | "complete" | "auth-required" | "failed";
|
|
32
|
+
interface ContactMapStreamState {
|
|
33
|
+
records: ContactRecord[];
|
|
34
|
+
loadedCount: number;
|
|
35
|
+
companyCount: number;
|
|
36
|
+
totalCount: number | null;
|
|
37
|
+
isLoading: boolean;
|
|
38
|
+
isComplete: boolean;
|
|
39
|
+
phase: ContactMapStreamPhase;
|
|
40
|
+
error: Error | null;
|
|
41
|
+
}
|
|
42
|
+
interface ContactMapOutletContext {
|
|
43
|
+
contactMapRecords: ContactRecord[];
|
|
44
|
+
isStreamingComplete: boolean;
|
|
45
|
+
isStreamingFailed: boolean;
|
|
46
|
+
streamPhase: ContactMapStreamPhase;
|
|
47
|
+
loadedCount: number;
|
|
48
|
+
companyCount: number;
|
|
49
|
+
totalCount: number | null;
|
|
50
|
+
errorMessage: string | null;
|
|
51
|
+
}
|
|
52
|
+
interface SearchResultEntry {
|
|
53
|
+
item: ContactRecord;
|
|
54
|
+
score?: number;
|
|
55
|
+
baseScore?: number;
|
|
56
|
+
matches?: Array<{
|
|
57
|
+
key: string;
|
|
58
|
+
indices: Array<[
|
|
59
|
+
number,
|
|
60
|
+
number
|
|
61
|
+
]>;
|
|
62
|
+
value?: string;
|
|
63
|
+
}>;
|
|
64
|
+
}
|
|
65
|
+
interface ContactMapSearchOutletContext {
|
|
66
|
+
contactMapRecords: ContactRecord[];
|
|
67
|
+
filteredItems: readonly SearchResultEntry[];
|
|
68
|
+
searchTerm: string;
|
|
69
|
+
isSearching: boolean;
|
|
70
|
+
isIndexBuilding: boolean;
|
|
71
|
+
isPending: boolean;
|
|
72
|
+
hasSearchTerm: boolean;
|
|
73
|
+
enableHighlighting: boolean;
|
|
74
|
+
openEmailsWithGmail: boolean;
|
|
75
|
+
isSearchInProgress: boolean;
|
|
76
|
+
isSearchTabActive: boolean;
|
|
77
|
+
errorMessage: string | null;
|
|
78
|
+
isStreamingComplete: boolean;
|
|
79
|
+
isStreamingFailed: boolean;
|
|
80
|
+
}
|
|
81
|
+
interface IndexWorkerMetrics {
|
|
82
|
+
totalIndexBuilds?: number;
|
|
83
|
+
currentDataSize?: number;
|
|
84
|
+
lastIndexTime?: number;
|
|
85
|
+
cacheSize?: {
|
|
86
|
+
ngram?: number;
|
|
87
|
+
word?: number;
|
|
88
|
+
phonetic?: number;
|
|
89
|
+
};
|
|
90
|
+
indexMetadata?: Record<string, unknown>;
|
|
91
|
+
}
|
|
92
|
+
interface LevenshteinWorkerMetrics {
|
|
93
|
+
totalCalculations?: number;
|
|
94
|
+
totalDistanceCalculations?: number;
|
|
95
|
+
averageDistance?: number;
|
|
96
|
+
minDistance?: number | string;
|
|
97
|
+
maxDistance?: number;
|
|
98
|
+
partialMatches?: number;
|
|
99
|
+
perfectMatches?: number;
|
|
100
|
+
similarityThresholds?: {
|
|
101
|
+
above80?: number;
|
|
102
|
+
above60?: number;
|
|
103
|
+
above40?: number;
|
|
104
|
+
below40?: number;
|
|
105
|
+
};
|
|
106
|
+
distanceDistribution?: Record<string, number>;
|
|
107
|
+
queryLengthStats?: Record<string, {
|
|
108
|
+
count: number;
|
|
109
|
+
averageScore: number;
|
|
110
|
+
}>;
|
|
111
|
+
earlyTerminations?: number;
|
|
112
|
+
}
|
|
113
|
+
interface FieldPerformanceMetric {
|
|
114
|
+
matchCount: number;
|
|
115
|
+
averageScore: number;
|
|
116
|
+
totalScore: number;
|
|
117
|
+
bestScore: number;
|
|
118
|
+
worstScore: number;
|
|
119
|
+
}
|
|
120
|
+
interface ContactMapLogger {
|
|
121
|
+
info(message: string, ...args: unknown[]): void;
|
|
122
|
+
warn(message: string, ...args: unknown[]): void;
|
|
123
|
+
error(message: string, ...args: unknown[]): void;
|
|
124
|
+
}
|
|
125
|
+
declare const defaultLogger: ContactMapLogger;
|
|
126
|
+
type StreamCursor = {
|
|
127
|
+
contacted_at: string | null;
|
|
128
|
+
person_id: number;
|
|
129
|
+
};
|
|
130
|
+
type JsonSerialized<T> = {
|
|
131
|
+
[K in keyof T]: T[K] extends Date ? string : T[K] extends Date | null ? string | null : T[K];
|
|
132
|
+
};
|
|
133
|
+
type SerializedContactStreamRow = JsonSerialized<ContactRecord>;
|
|
134
|
+
type StreamChunkWire = {
|
|
135
|
+
records: SerializedContactStreamRow[];
|
|
136
|
+
nextCursor: StreamCursor | null;
|
|
137
|
+
isLast: boolean;
|
|
138
|
+
total?: number;
|
|
139
|
+
};
|
|
140
|
+
type StreamMetadataWire = {
|
|
141
|
+
type: "METADATA";
|
|
142
|
+
total: number;
|
|
143
|
+
};
|
|
144
|
+
type StreamErrorWire = {
|
|
145
|
+
error: string;
|
|
146
|
+
};
|
|
147
|
+
type StreamLineWire = StreamChunkWire | StreamMetadataWire | StreamErrorWire;
|
|
148
|
+
export { type ContactRecord as C, type FieldPerformanceMetric as F, type IndexWorkerMetrics as I, type JsonSerialized as J, type LevenshteinWorkerMetrics as L, type SerializedContactStreamRow as S, type ContactMapStreamPhase as a, type ContactMapSearchOutletContext as b, type ContactMapOutletContext as c, type ContactMapLogger as d, type SearchResultEntry as e, type ContactMapStreamState as f, type StreamChunkWire as g, type StreamCursor as h, type StreamErrorWire as i, type StreamLineWire as j, type StreamMetadataWire as k, defaultLogger as l };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var S=(t,n)=>t&&t.trim()||n;var H={\u672C\u90E8:{rank:10,type:"Organization"},\u30AB\u30F3\u30D1\u30CB\u30FC:{rank:10,type:"Organization"},\u672C\u793E:{rank:10,type:"Location"},\u30D6\u30ED\u30C3\u30AF:{rank:11,type:"Location"},\u652F\u5E97:{rank:12,type:"Location"},\u7814\u7A76\u6240:{rank:15,type:"Location"},\u5DE5\u5834:{rank:15,type:"Location"},\u4E8B\u696D\u90E8:{rank:18,type:"Organization"},\u90E8\u9580:{rank:18,type:"Organization"},\u7D71\u62EC\u90E8:{rank:19,type:"Organization"},\u90E8:{rank:20,type:"Organization"},\u958B\u767A:{rank:20,type:"Organization"},\u30B0\u30EB\u30FC\u30D7:{rank:22,type:"Organization"},\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8:{rank:25,type:"Organization"},\u63A8\u9032:{rank:20,type:"Organization"},\u4E8B\u696D\u6240:{rank:25,type:"Location"},\u55B6\u696D\u6240:{rank:28,type:"Location"},\u5BA4:{rank:30,type:"Organization"},\u8AB2:{rank:30,type:"Organization"},\u30BB\u30F3\u30BF\u30FC:{rank:30,type:"Location"},\u30D3\u30B8\u30CD\u30B9\u30D7\u30ED\u30C7\u30E5\u30FC\u30B9\u30BB\u30F3\u30BF\u30FC:{rank:30,type:"Location"},\u30C1\u30FC\u30E0:{rank:40,type:"Organization"},\u4FC2:{rank:50,type:"Organization"},Department:{rank:20,type:"Organization"},Dept:{rank:20,type:"Organization"},"Dept.":{rank:20,type:"Organization"},Division:{rank:20,type:"Organization"},Div:{rank:20,type:"Organization"},"Div.":{rank:20,type:"Organization"},Section:{rank:30,type:"Organization"},Sect:{rank:30,type:"Organization"},"Sect.":{rank:30,type:"Organization"},Unit:{rank:30,type:"Organization"},Group:{rank:22,type:"Organization"},Team:{rank:40,type:"Organization"},Branch:{rank:12,type:"Location"},Office:{rank:28,type:"Location"},Center:{rank:30,type:"Location"},Centre:{rank:30,type:"Location"},HQ:{rank:10,type:"Organization"},Headquarters:{rank:10,type:"Organization"}},k=t=>{for(let[n,i]of Object.entries(H))if(t.endsWith(n))return i;return{rank:99,type:"Other"}},z=t=>k(t).rank,Q=["\u30B0\u30EB\u30FC\u30D7","\u30C1\u30FC\u30E0","Group","Team","\u5BA4","\u8AB2","Unit","Area","\u90E8","Department","Dept","Division","Div","\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8","\u63A8\u9032"],v=t=>Q.find(n=>t.endsWith(n)),X=new Set(["&","Quality","Innovation","R&D","Solutions","Development","Laboratory","and","Food","Beverage"]),J=(t,n)=>n>1&&(t.endsWith("\u652F\u5E97")||t.endsWith("\u672C\u90E8")||t.endsWith("\u4E8B\u696D\u6240")||t.endsWith("\u5DE5\u5834")),Z=(t,n)=>{if(!n)return!0;let i=k(t),r=k(n);if(i.rank<r.rank||t.endsWith("\u672C\u90E8")&&n.endsWith("\u672C\u90E8"))return!1;let p=v(t),f=v(n);return!(p&&f&&p!==f)},x=(t,n)=>{if(!t)return[];if(t==="\u517C")return["\u517C"];if(t==="\u517C\u52D9")return["\u517C"];if(t.startsWith("\u517C ")||t.startsWith("\u517C\u3000")){let r=t.slice(1).trim();return["\u517C",...x(r,n)]}if(t.startsWith("\u517C\u52D9 ")||t.startsWith("\u517C\u52D9\u3000")){let r=t.slice(2).trim();return["\u517C",...x(r,n)]}let i="";for(let r=t.length-1;r>0;r--){if(t[r]!==" ")continue;let p=t.slice(0,r);if(!X.has(p)&&n.has(p)){i=p;break}}if(i){let r=i,p=t.slice(i.length),f=/^\s+(and|&)\s+([A-Za-z0-9]+)/i,b=p.match(f);b&&(r=t.slice(0,i.length+b[0].length));let l=t.slice(r.length),e=["Department","Dept","Division","Div","Section","Sect","Unit","Group","Team","Branch","Office","Center","Centre","HQ","Headquarters"];for(let s of e){let g=new RegExp(`^\\s+${s}\\.?(?=$|[\\s,])`,"i"),c=l.match(g);if(c){r=t.slice(0,r.length+c[0].length);break}}let u=t.slice(r.length).trim();return[r,...x(u,n)]}return[t]},V=(t,n)=>{let r=t.replace(/[\s\u3000]+(?:兼務|兼)[\s\u3000]+/g,"\u3000\u517C\u3000").replace(/^(?:兼務|兼)[\s\u3000]+/,"\u517C\u3000").replace(/[\s\u3000]+(?:兼務|兼)$/,"\u3000\u517C").split(/\u3000/),p=[];for(let f of r){let b=f.trim();b&&p.push(...x(b,n))}return p},A=(t,n)=>{let i=[],r=["\u90E8","\u8AB2","\u5BA4","\u672C\u90E8","\u652F\u5E97","\u55B6\u696D\u6240","\u30B0\u30EB\u30FC\u30D7","\u30C1\u30FC\u30E0","\u30BB\u30F3\u30BF\u30FC","\u30AB\u30F3\u30D1\u30CB\u30FC","\u4E8B\u696D\u6240","\u5DE5\u5834","\u7814\u7A76\u6240","\u4FC2","\u90E8\u9580","\u4E8B\u696D\u90E8","\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8","\u63A8\u9032","\u958B\u767A","Department","Dept","Division","Div","Section","Sect","Unit","Group","Team","Branch","Office","Center","Centre","HQ","Headquarters"],p=t.split(/[\s\u3000,()()[\]]+/).filter(Boolean),f=p.length,b=new Set;for(let l=f;l>=1;l--)for(let e=0;e<=f-l;e++){let u=!1;for(let g=e;g<e+l;g++)if(b.has(g)){u=!0;break}if(u)continue;let s=p.slice(e,e+l).join(" ");if(!(s==="\u517C"||s==="\u517C\u52D9"||s==="\u4FC2"||s==="of"||s==="&"||s==="Quality"||s==="Innovation"||s==="R&D"||s==="Solutions"||s==="Development"||s==="Laboratory"||s==="and"||s==="Food"||s==="Beverage")&&n.allKnownDepartments.has(s)){i.push({name:s,index:e});for(let g=e;g<e+l;g++)b.add(g)}}for(let l=0;l<f;l++){if(b.has(l))continue;let e=p[l];for(e.endsWith("\u9577")&&e.length>1?e=e.slice(0,-1):e.endsWith("\u7D71\u62EC")&&e.length>2&&(e=e.slice(0,-2));;){let c=!1;if(e.startsWith("\u62C5\u5F53")&&e.length>2||e.startsWith("\u5C02\u4EFB")&&e.length>2||e.startsWith("\u517C\u52D9")&&e.length>2?(e=e.slice(2),c=!0):(e.startsWith("\u526F")||e.startsWith("\u517C"))&&e.length>1&&(e=e.slice(1),c=!0),!c)break}if(e.includes("\u30FB")&&!n.allKnownDepartments.has(e)){let c=e.split("\u30FB"),y=c[c.length-1],T=r.find(E=>y.endsWith(E));if(T){for(let E of c){let C=E;r.some(o=>C.endsWith(o))||(C=C+T);let P=e!=="\u517C"&&e!=="\u4FC2"&&e!=="of"&&e!=="&"&&e!=="Quality"&&e!=="Innovation"&&e!=="R&D"&&e!=="Solutions"&&e!=="Development"&&e!=="Laboratory"&&e!=="and"&&e!=="Food"&&e!=="Beverage"&&n.allKnownDepartments.has(C),h=r.some(o=>C.endsWith(o)),a=r.includes(C);(P||h&&!a)&&i.push({name:C,index:l})}continue}}let u=e!=="\u517C"&&e!=="\u4FC2"&&e!=="of"&&e!=="&"&&e!=="Quality"&&e!=="Innovation"&&e!=="R&D"&&e!=="Solutions"&&e!=="Development"&&e!=="Laboratory"&&e!=="and"&&e!=="Food"&&e!=="Beverage"&&n.allKnownDepartments.has(e),s=r.some(c=>e.endsWith(c)),g=r.includes(e);(u||s&&!g)&&i.push({name:e,index:l})}return i.sort((l,e)=>l.index-e.index),i.map(l=>l.name)},L=(t,n)=>{let i=0;for(let r of n)i<t.length&&r===t[i]&&i++;return i===t.length},_={name:"Standard",parse:(t,n,i="full")=>{let r=S(t.department,"");if(!r)return null;let p=V(r,n.allKnownDepartments),f=new Map;for(let e of p)f.set(e,(f.get(e)||0)+1);let b=e=>{let u=[],s=[];for(let g=0;g<e.length;g++){let c=e[g];if(c==="\u517C"){s.length>0&&(u.push(s),s=[]);continue}let y=k(c),T=y.rank,E=f.get(c)||0,C=J(c,E);if(s.length===0)s.push(c);else{let P=s[s.length-1],h=k(P),a=h.rank;if(s.includes(c))u.push(s),s=[c];else{let o=!1;if(C)o=!0;else if(h.type===y.type){let m=v(P),d=v(c);m&&d&&m!==d||P.endsWith("\u672C\u90E8")&&c.endsWith("\u672C\u90E8")||P.endsWith("\u90E8\u9580")&&c.endsWith("\u4E8B\u696D\u90E8")||P.endsWith("\u4E8B\u696D\u90E8")&&c.endsWith("\u90E8\u9580")||P.endsWith("\u90E8\u9580")&&c.endsWith("\u672C\u90E8")||h.type==="Other"&&y.type==="Other"?o=!0:o=a<T}else o=T>=10,o&&h.type==="Location"&&y.type==="Organization"&&a>=T&&e.slice(g+1).includes(P)&&(o=!1);o?s.push(c):(u.push(s),s=[c])}}if(C){let P=g+1<e.length?e[g+1]:void 0;Z(c,P)&&s.length>0&&(u.push(s),s=[])}}return s.length>0&&u.push(s),u},l=[];if(i==="full"&&l.push(...b(p)),i==="pure_org"){let e=p.filter(u=>k(u).type!=="Location");e.length>0&&l.push(...b(e))}if(t.title){let u=/[^\x20-\x7E]/.test(t.title)?/[\s\u3000]*(?:兼務|兼)[\s\u3000]*/:/[,;]|(?:兼務|兼)/,s=t.title.split(u).filter(Boolean),g=[],c=(h,a)=>{let o=z(h),m=z(a),d=o<m;if(!d){let D=v(h),R=v(a);if(D&&R&&D!==R)d=!0;else if(h.endsWith("\u672C\u90E8")&&a.endsWith("\u672C\u90E8"))d=!0;else if(h.endsWith("\u90E8\u9580")&&a.endsWith("\u4E8B\u696D\u90E8")||h.endsWith("\u4E8B\u696D\u90E8")&&a.endsWith("\u90E8\u9580"))d=!0;else if(h.endsWith("\u90E8\u9580")&&a.endsWith("\u672C\u90E8"))d=!0;else{let w=k(h),G=k(a);w.type==="Other"&&G.type==="Other"&&(d=!0)}}return d};for(let h of s){let a=A(h,n);if(a.length===0)continue;let o=[];for(let m of a)if(o.length===0)o.push(m);else{let d=o[o.length-1];if(c(d,m))o.push(m);else{g.push([...o]);let D=!1;for(let R=o.length-2;R>=0;R--){let w=o[R];if(c(w,m)){o=[...o.slice(0,R+1),m],D=!0;break}}D||(o=[m])}}o.length>0&&g.push(o)}let y=[...l],T=h=>s.some(a=>a.includes(h)&&a.length>h.length);for(let h of g){let a=!1;for(let o of l){let m=o.findIndex(d=>h.includes(d));if(m!==-1){let d=o[m],D=h.indexOf(d);if(m>0&&D===0){let R=o.slice(0,m);y.push([...R,...h]),a=!0}else if(D>0&&m===0){let R=h.slice(0,D);y.push([...R,...o]),y.push(h),a=!0}else h.length>o.length-m,a=!0}if(!a){let d=o[o.length-1],D=h[0];c(d,D)&&(y.push([...o,...h]),a=!0)}}a||y.push(h)}let E=[],C=[],P=new Set;for(let h of y){let a=h.join("|");P.has(a)||(P.add(a),C.push(h))}for(let h=0;h<C.length;h++){let a=C[h],o=!1;for(let m=0;m<C.length;m++){if(h===m)continue;let d=C[m];if(d.length>a.length&&d.slice(0,a.length).join("|")===a.join("|")){let D=a[a.length-1];if(!T(D)){o=!0;break}}if(d.length>a.length&&L(a,d)){let D=a[a.length-1];if(!T(D)){o=!0;break}}if(a.length===1&&d.length>0){let D=a[0],R=d[d.length-1];if(D!==R&&R.endsWith(D)){o=!0;break}}}o||E.push(a)}return E.length>0?E:null}if(l.length>0){let e=[];for(let u=0;u<l.length;u++){let s=l[u],g=!1;for(let c=0;c<l.length;c++){if(u===c)continue;let y=l[c];if(y.length>s.length&&L(s,y)){g=!0;break}}g||e.push(s)}return e.length>0?e:null}return null}},F={name:"TitleBased",parse:(t,n,i="full")=>{let r=t.title;if(!r)return null;let p=A(r,n);return p.length>0?[p]:null}};var Y="\u672A\u5206\u985E",$="\u540D\u524D\u672A\u8A2D\u5B9A",ee=[_,F],te=t=>{let n=S(t.full_name,$),i=S(t.title,"");return i.length>0?`${n} (${i})`:n},B=(t,n)=>`${t} (${n.toLocaleString()})`,W=t=>t.sort((n,i)=>n.label.localeCompare(i.label,"ja")),O=(t,n,i)=>{let r=t.get(n);if(r)return r;let p=i();return t.set(n,p),p},N=t=>encodeURIComponent(t.replace(/\//g,"\uFF0F")),q=t=>t.sort((n,i)=>{let r=!!(n.contact.title&&n.contact.title.trim().length>0),p=!!(i.contact.title&&i.contact.title.trim().length>0);return r&&!p?-1:!r&&p?1:n.label.localeCompare(i.label,"ja")}),U=t=>{let n=S(t.contact.full_name,$),i=S(t.contact.title,"");return{name:i?`${n} (${i})`:n,type:"file",absolutePath:t.path,relativePath:t.segment,personId:t.contact.person_id,title:t.contact.title||void 0,isPrimary:t.isPrimary}},K=t=>{let n=W(Array.from(t.children.values())).map(K),i=q([...t.persons]).map(U);return{name:B(t.label,t.personCount),type:"directory",absolutePath:t.path,relativePath:t.segment,children:[...i,...n]}},M=class{constructor(){this.companyMap=new Map;this.processedPersonIds=new Set;this.allDepts=new Set;this.cachedResult=null}appendRecords(n){if(!n||n.length===0)return;let i="full",r=!1;for(let p of n)if(!this.processedPersonIds.has(p.person_id)&&p.department){let f=p.department.split(/\u3000/);for(let b of f){let l=b.trim();if(!l||l==="\u517C"||l==="\u4FC2")continue;if(/[^\x20-\x7E]/.test(l)){let u=l.split(" ").filter(s=>s.length>0&&s!=="\u517C"&&s!=="\u4FC2");for(let s of u)this.allDepts.add(s)}else this.allDepts.add(l)}}for(let p of n){let f=p.person_id;if(!Number.isFinite(f)||this.processedPersonIds.has(f))continue;this.processedPersonIds.add(f),r=!0;let b=S(p.company_name,Y),l=te(p),e=`company:${N(b)}`,u=O(this.companyMap,e,()=>({label:b,segment:e,path:`/${e}`,departments:new Map,persons:[],personCount:0})),s=[],g={allKnownDepartments:this.allDepts};for(let c of ee){let y=c.parse(p,g,i);if(y&&y.length>0){s=y;break}}s.length===0&&s.push([]);for(let c=0;c<s.length;c++){let y=s[c];if(y.length===0){let a=`person:${f}`,o=`${u.path}/${a}`;u.persons.some(d=>d.contact.person_id===f)||u.persons.push({contact:p,label:l,path:o,segment:a,isPrimary:!0});continue}let T=null,E=u.path;if(y.length>0){let a=y[0],o=`department:${N(a)}`;T=O(u.departments,o,()=>({label:a,segment:o,path:`${E}/${o}`,children:new Map,persons:[],personCount:0})),E=T.path,T.personCount+=1;for(let m=1;m<y.length;m++){let d=y[m],D=`department:${N(d)}`;if(!T)throw new Error("Unexpected null currentDepartmentNode");T=O(T.children,D,()=>({label:d,segment:D,path:`${E}/${D}`,children:new Map,persons:[],personCount:0})),E=T.path,T.personCount+=1}}else continue;let C=`person:${f}`,P=`${T.path}/${C}`;T.persons.some(a=>a.contact.person_id===f)||T.persons.push({contact:p,label:l,path:P,segment:C,isPrimary:c===0})}u.personCount+=1}r&&(this.cachedResult=null)}getSnapshot(){if(this.cachedResult)return this.cachedResult;let n={},i=W(Array.from(this.companyMap.values())).map(r=>{let p=W(Array.from(r.departments.values())).map(K),f=q([...r.persons]).map(U),b={name:B(r.label,r.personCount),type:"directory",absolutePath:r.path,relativePath:r.segment,children:[...f,...p]};return n[r.label]=b,b});return this.cachedResult={tree:i,companyMap:n},this.cachedResult}append(n){this.appendRecords(n)}build(){return this.getSnapshot().tree}reset(){this.companyMap.clear(),this.processedPersonIds.clear(),this.allDepts.clear(),this.cachedResult=null}getUniquePersonCount(){return this.processedPersonIds.size}get size(){return this.processedPersonIds.size}};var ne=3e3,j=60,re=700,se=25,ie=t=>{let n=j+t/se;return Math.min(re,Math.max(j,n))};var oe={setTimeout:(t,n)=>setTimeout(t,n),clearTimeout:t=>clearTimeout(t),now:()=>Date.now()},I=class{constructor(n,i=oe){this.postMessage=n;this.timer=i;this.builder=new M;this.pendingRecords=[];this.rawRecords=[];this.activeGeneration=0;this.rebuildEpoch=0;this.lastEmitTime=0;this.emitTimerId=null;this.processTimerId=null;this.isProcessing=!1;this.finalizeRequested=!1}handleMessage(n){switch(n.type){case"RESET_TREE":{this.cancelTimers(),this.activeGeneration=n.generation,this.rebuildEpoch=Math.max(this.rebuildEpoch,n.epochBase)+1,this.builder=new M,this.pendingRecords.length=0,this.rawRecords.length=0,this.lastEmitTime=0,this.finalizeRequested=!1,this.isProcessing=!1;break}case"APPEND_RECORDS":{if(n.generation!==this.activeGeneration)return;for(let i=0;i<n.records.length;i++){let r=n.records[i];this.pendingRecords.push(r),this.rawRecords.push(r)}this.scheduleProcess();break}case"FINALIZE_TREE":{if(n.generation!==this.activeGeneration)return;this.finalizeRequested=!0,this.scheduleProcess();break}}}scheduleProcess(){this.isProcessing||this.processTimerId!==null||(this.processTimerId=this.timer.setTimeout(()=>{this.processTimerId=null,this.processStep()},0))}processStep(){this.isProcessing=!0;let n=Math.min(ne,this.pendingRecords.length);if(n>0){let r=this.pendingRecords.splice(0,n);this.builder.append(r)}if(this.pendingRecords.length>0){this.isProcessing=!1,this.scheduleProcess(),this.scheduleEmit(!1);return}if(this.finalizeRequested){this.finalizeRequested=!1,this.builder=new M,this.builder.append(this.rawRecords),this.rebuildEpoch+=1,this.isProcessing=!1,this.emitNow(!0);return}this.isProcessing=!1,this.scheduleEmit(!0)}scheduleEmit(n){if(this.emitTimerId!==null){n&&(this.timer.clearTimeout(this.emitTimerId),this.emitTimerId=null,this.emitNow(!0));return}let i=this.timer.now(),r=ie(this.builder.getUniquePersonCount()),p=i-this.lastEmitTime;if(p>=r||n)this.emitNow(n);else{let f=r-p;this.emitTimerId=this.timer.setTimeout(()=>{this.emitTimerId=null,this.emitNow(this.pendingRecords.length===0&&!this.finalizeRequested)},f)}}emitNow(n){this.lastEmitTime=this.timer.now();let i=this.builder.build();this.postMessage({type:"TREE_CHUNK",generation:this.activeGeneration,tree:i,consumedRecords:this.rawRecords.length,uniquePersonCount:this.builder.getUniquePersonCount(),isIdle:n,rebuildEpoch:this.rebuildEpoch})}cancelTimers(){this.processTimerId!==null&&(this.timer.clearTimeout(this.processTimerId),this.processTimerId=null),this.emitTimerId!==null&&(this.timer.clearTimeout(this.emitTimerId),this.emitTimerId=null)}dispose(){this.cancelTimers(),this.pendingRecords.length=0,this.rawRecords.length=0}};var ae=new I(t=>{self.postMessage(t)});self.onmessage=t=>{ae.handleMessage(t.data)};
|
package/package.json
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aiquants/contact-map",
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Reusable contact-map feature package: shared types/schemas, React (Router v7 / v8) UI with virtual scrolling + tree view + incremental Web Worker + fuzzy search + resize panels, and a drizzle (mssql) server layer with DI ports.",
|
|
5
|
+
"sideEffects": [
|
|
6
|
+
"**/*.css"
|
|
7
|
+
],
|
|
8
|
+
"main": "dist/index.js",
|
|
9
|
+
"module": "dist/index.mjs",
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"import": "./dist/index.mjs",
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./client": {
|
|
18
|
+
"types": "./dist/client.d.ts",
|
|
19
|
+
"import": "./dist/client.mjs",
|
|
20
|
+
"require": "./dist/client.js"
|
|
21
|
+
},
|
|
22
|
+
"./server": {
|
|
23
|
+
"types": "./dist/server.d.ts",
|
|
24
|
+
"import": "./dist/server.mjs",
|
|
25
|
+
"require": "./dist/server.js"
|
|
26
|
+
},
|
|
27
|
+
"./styles/contact-map.standalone.css": "./dist/styles/contact-map.standalone.css",
|
|
28
|
+
"./worker/treeWorker": {
|
|
29
|
+
"import": "./dist/worker/treeWorker.mjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"keywords": [
|
|
38
|
+
"contact-map",
|
|
39
|
+
"react-router",
|
|
40
|
+
"drizzle",
|
|
41
|
+
"mssql",
|
|
42
|
+
"ndjson",
|
|
43
|
+
"web-worker",
|
|
44
|
+
"virtual-scroll",
|
|
45
|
+
"directory-tree",
|
|
46
|
+
"fuzzy-search",
|
|
47
|
+
"typescript"
|
|
48
|
+
],
|
|
49
|
+
"author": "AI Quants",
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@heroicons/react": "^2.2.0",
|
|
53
|
+
"@radix-ui/react-label": "^2.1.8",
|
|
54
|
+
"@radix-ui/react-slot": "^1.2.4",
|
|
55
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
56
|
+
"class-variance-authority": "^0.7.1",
|
|
57
|
+
"clsx": "^2.1.1",
|
|
58
|
+
"lucide-react": "^0.561.0",
|
|
59
|
+
"tailwind-merge": "^3.5.0"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@aiquants/directory-tree": "^3.11.1",
|
|
63
|
+
"@aiquants/fuzzy-search": "^2.2.1",
|
|
64
|
+
"@aiquants/resize-panels": "^2.0.1",
|
|
65
|
+
"@aiquants/select-box": "^0.9.2",
|
|
66
|
+
"@aiquants/swipe-overlay": "^1.2.5",
|
|
67
|
+
"@aiquants/virtualscroll": "^3.5.0",
|
|
68
|
+
"@tailwindcss/cli": "^4.1.18",
|
|
69
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
70
|
+
"@testing-library/react": "^16.3.2",
|
|
71
|
+
"@types/node": "^25.9.1",
|
|
72
|
+
"@types/react": "^19.2.7",
|
|
73
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
74
|
+
"drizzle-orm": "1.0.0-rc.4",
|
|
75
|
+
"jsdom": "^27.4.0",
|
|
76
|
+
"react": "^19.2.7",
|
|
77
|
+
"react-dom": "^19.2.7",
|
|
78
|
+
"react-router": "^8.3.0",
|
|
79
|
+
"rimraf": "^6.1.2",
|
|
80
|
+
"tailwindcss": "^4.1.18",
|
|
81
|
+
"tailwindcss-animate": "^1.0.7",
|
|
82
|
+
"tsup": "^8.5.1",
|
|
83
|
+
"typescript": "^5.9.3",
|
|
84
|
+
"vitest": "^4.1.10",
|
|
85
|
+
"zod": "^3.25.76"
|
|
86
|
+
},
|
|
87
|
+
"peerDependencies": {
|
|
88
|
+
"@aiquants/directory-tree": "^3.11.1",
|
|
89
|
+
"@aiquants/fuzzy-search": "^2.2.1",
|
|
90
|
+
"@aiquants/resize-panels": "^2.0.1",
|
|
91
|
+
"@aiquants/select-box": "^0.9.2",
|
|
92
|
+
"@aiquants/swipe-overlay": "^1.2.5",
|
|
93
|
+
"@aiquants/virtualscroll": "^3.5.0",
|
|
94
|
+
"drizzle-orm": ">=1.0.0-beta.4 <2.0.0",
|
|
95
|
+
"react": ">=18",
|
|
96
|
+
"react-dom": ">=18",
|
|
97
|
+
"react-router": "^7.0.0 || ^8.0.0",
|
|
98
|
+
"zod": ">=3.25.0 <5.0.0"
|
|
99
|
+
},
|
|
100
|
+
"peerDependenciesMeta": {
|
|
101
|
+
"drizzle-orm": {
|
|
102
|
+
"optional": true
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"engines": {
|
|
106
|
+
"node": ">=18.0.0",
|
|
107
|
+
"pnpm": ">=8.0.0"
|
|
108
|
+
},
|
|
109
|
+
"publishConfig": {
|
|
110
|
+
"access": "public"
|
|
111
|
+
},
|
|
112
|
+
"scripts": {
|
|
113
|
+
"build": "tsup && node ../../.config/scripts/strip-dts-comments.mjs dist && pnpm build:css",
|
|
114
|
+
"build:css": "tailwindcss -i src/styles/standalone.entry.css -o dist/styles/contact-map.standalone.css --minify",
|
|
115
|
+
"watch:css": "tailwindcss -i src/styles/standalone.entry.css -o dist/styles/contact-map.standalone.css --minify --watch",
|
|
116
|
+
"build:watch": "tsup --watch --onSuccess \"pnpm build:css\"",
|
|
117
|
+
"dev": "tsup --watch --onSuccess \"pnpm build:css\"",
|
|
118
|
+
"typecheck": "tsc --noEmit",
|
|
119
|
+
"clean": "rimraf dist",
|
|
120
|
+
"publish:patch": "pnpm run verify && pnpm version patch --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
121
|
+
"publish:minor": "pnpm run verify && pnpm version minor --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
122
|
+
"publish:major": "pnpm run verify && pnpm version major --no-git-tag-version --no-git-checks && pnpm publish --no-git-checks",
|
|
123
|
+
"lint": "biome lint src/",
|
|
124
|
+
"check": "biome check src/",
|
|
125
|
+
"check:fix": "biome check --write src/",
|
|
126
|
+
"test": "vitest run",
|
|
127
|
+
"test:coverage": "vitest run --coverage",
|
|
128
|
+
"typecheck:spec": "tsc --noEmit -p tsconfig.spec.json",
|
|
129
|
+
"check:md": "cd ../.. && node_modules/.bin/markdownlint-cli2 \"packages/contact-map/**/*.md\"",
|
|
130
|
+
"verify": "node_modules/.bin/tsc --noEmit && node_modules/.bin/tsc --noEmit -p tsconfig.spec.json && ../../node_modules/.bin/biome check src/ && pnpm run check:md && node_modules/.bin/vitest run"
|
|
131
|
+
}
|
|
132
|
+
}
|