@bicharts/shape-core 0.5.7 → 0.5.8

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.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  /*! @bicharts/shape-core — Apache-2.0. Bundled reference data: GeoNames (https://www.geonames.org/) CC BY 4.0; US Census/TIGER (public domain). Full text: NOTICE in this package. */
2
- import{a as dt,b as yt}from"./chunk-RIM62XDD.mjs";import{a as st,b as ct,c as at,d as ut,e as lt,f as ft}from"./chunk-WIPW5J2O.mjs";import{a as tt}from"./chunk-QEH7WTLB.mjs";import{a as nt,b as et}from"./chunk-2LR73DNS.mjs";import{a as ot,b as it,c as rt}from"./chunk-NWDPA7DG.mjs";import{a as j,b as J,c as Q,d as Y}from"./chunk-JY46MGFW.mjs";import{a as x,f as P,g as K,h as V,i as f,j as q,k as F,l as b,m as U,n as W,o as X,p as v,q as Z}from"./chunk-RPZZSD7D.mjs";import"./chunk-JH3W3DH7.mjs";import{a as H,b as E,c as B}from"./chunk-WBEROMBG.mjs";var A=85,T=2,pt=100,N=400,mt=97;function L(r){return!!P(r)}function p(r){let n=new Set;for(let e of r){if(e==null)continue;let i=x(String(e));if(i&&!n.has(i)&&(n.add(i),n.size>=N))break}return Array.from(n)}function g(r){let n=p(r);if(n.length===0||ht(r)<mt)return!1;let e=n.filter(c=>L(c)&&!f(c)).length,i=n.filter(c=>!L(c)&&!!f(c)).length;return e>=1&&e>=i}var gt=new Set(["USA","CAN","MEX"]);function z(r,n){if(!f(r))return!1;let e=P(r);return e?n==="world"?!0:gt.has(e):!1}function ht(r){let n=p(r);if(n.length===0)return 0;let e=0;for(let i of n)L(i)&&e++;return Math.round(e/n.length*1e3)/10}function M(r){let n=p(r);if(n.length===0)return 0;let e=0;for(let i of n)f(i)&&e++;return Math.round(e/n.length*1e3)/10}function _(r){let n=new Set;for(let e of r){if(e==null)continue;let i=String(e).trim();if(i&&!n.has(i)&&(n.add(i),n.size>=N))break}return Array.from(n)}function D(r){let n=_(r);if(n.length===0)return 0;let e=0;for(let i of n)b(i).length>0&&e++;return Math.round(e/n.length*1e3)/10}function Ct(r,n){let e=p(r);if(e.length===0)return 0;let i=0;for(let c of e)v(c,n)&&i++;return Math.round(i/e.length*1e3)/10}function k(r,n){let e=0;for(let i of p(r))n(i)&&e++;return e}function Pt(r,n){let e=0;for(let i of _(r))n(i)&&e++;return e}function bt(r,n,e,i){let c=[],m=[],o={},w=new Set(r),y=t=>n.map(s=>s[t]);for(let t of["city","zip","lat","lon","country"]){let s=e?.[t];s&&w.has(s)&&(o[t]=s)}let l=e?.state;if(l&&w.has(l)){let t=y(l),s=p(t);s.length>0&&s.every(a=>z(a,i))?m.push(`state=${l} (every value is "CA", which is both Canada and California)`):g(t)?(m.push(`state=${l} (every value is a country, not a state)`),o.country||(o.country=l)):M(t)<A?m.push(`state=${l} (only ${M(t)}% of values are states/provinces)`):o.state=l}let d=new Set(Object.values(o).filter(Boolean)),h=r.filter(t=>!d.has(t)&&!t.startsWith("__"));if(!o.state){let t=null;for(let s of h){let a=y(s);if(g(a))continue;let u=M(a);if(u<A)continue;let S=k(a,C=>!!f(C)),O=k(a,C=>!!f(C)&&!z(C,i));S<T&&O<1||(!t||u>t.pct)&&(t={name:s,pct:u})}t&&(o.state=t.name,d.add(t.name),c.push(`state=${t.name} (${t.pct}% states/provinces)`))}if(!o.zip)for(let t of h){if(d.has(t))continue;let s=y(t),a=D(s);if(!(a<pt)&&!(Pt(s,u=>b(u).length>0)<T)){o.zip=t,d.add(t),c.push(`zip=${t} (${a}% ZIP codes)`);break}}if(!o.country){for(let t of h)if(!d.has(t)&&g(y(t))){o.country=t,d.add(t),c.push(`country=${t}`);break}}if(!o.city){let t=null;for(let s of h){if(d.has(s))continue;let a=y(s),u=Ct(a,i);u<A||k(a,S=>v(S,i))<T||(!t||u>t.pct)&&(t={name:s,pct:u})}t&&(o.city=t.name,c.push(`city=${t.name} (${t.pct}% known cities)`))}let G=o.country?y(o.country):[],R=!!o.country&&g(G),$=R?new Set(G.map(t=>P(t==null?null:String(t))).filter(Boolean)).size:0,I=R&&$>=2;return o.country&&!I&&!(o.city||o.state||o.zip||o.lat&&o.lon)&&m.push(R?`country=${o.country} (every row resolves to the same country - nothing to place apart)`:`country=${o.country} (values are not country identifiers)`),{bind:!!(o.city||o.state||o.zip||I||o.lat&&o.lon)?o:null,backfilled:c,refused:m}}export{rt as GET_RANDOM,ft as IndexedText,it as SIMPLE_STRING_HASH,ot as STR,M as admin1MatchPct,Y as buildGeoIsoColumn,X as buildGeoPointColumns,Z as cityMatchPct,ut as classifyAdditivity,lt as classifyNumericValueNature,ct as classifyTemporal,tt as detectFormatSignature,j as detectGeo,B as detectOrdinalDomain,dt as engineTypeForSqlType,at as hostAggHint,yt as ingest,V as isCityTableLoaded,U as isGeoPointAmbiguity,st as isIdentifierName,Q as isJoinGeoKind,H as isOrdinalFriendlyName,g as looksLikeCountryColumn,et as monthLookupFor,q as normalizeCountry,nt as normalizeMonthKey,x as normalizePlaceName,K as registerCityTable,f as resolveAdmin1,W as resolveGeoPoint,bt as resolvePointRoles,E as safeDistinctValuesToShip,J as toGeoIso,D as zipMatchPct,b as zipPrefixCandidates,F as zipToPrefix3};
2
+ import{a as yt,b as mt}from"./chunk-RIM62XDD.mjs";import{a as ct,b as ut,c as lt,d as ft,e as pt,f as dt}from"./chunk-WIPW5J2O.mjs";import{a as et}from"./chunk-QEH7WTLB.mjs";import{a as ot,b as it}from"./chunk-2LR73DNS.mjs";import{a as rt,b as st,c as at}from"./chunk-NWDPA7DG.mjs";import{a as Q,b as Y,c as tt,d as nt}from"./chunk-JY46MGFW.mjs";import{a as P,f as b,g as q,h as F,i as f,j as Z,k as U,l as A,m as W,n as X,o as j,p as S,q as J}from"./chunk-RPZZSD7D.mjs";import"./chunk-JH3W3DH7.mjs";import{a as O,b as K,c as V}from"./chunk-WBEROMBG.mjs";var k=97,gt=new Set(["n a","none","null","nil","unknown","not applicable","not available","not specified","unspecified","missing","blank","empty","tbd","to be determined"]);function M(i){return i?gt.has(i):!0}var v=85,L=2,ht=100,N=400;function w(i){return!!b(i)}function y(i){let n=new Set;for(let e of i){if(e==null)continue;let r=P(String(e));if(!M(r)&&!n.has(r)&&(n.add(r),n.size>=N))break}return Array.from(n)}function g(i){let n=y(i);if(n.length===0||Pt(i)<97)return!1;let e=n.filter(a=>w(a)&&!f(a)).length,r=n.filter(a=>!w(a)&&!!f(a)).length;return e>=1&&e>=r}var Ct=new Set(["USA","CAN","MEX"]);function E(i,n){if(!f(i))return!1;let e=b(i);return e?n==="world"?!0:Ct.has(e):!1}function Pt(i){let n=y(i);if(n.length===0)return 0;let e=0;for(let r of n)w(r)&&e++;return Math.round(e/n.length*1e3)/10}function T(i){let n=y(i);if(n.length===0)return 0;let e=0;for(let r of n)f(r)&&e++;return Math.round(e/n.length*1e3)/10}function $(i){let n=new Set;for(let e of i){if(e==null)continue;let r=String(e).trim();if(!M(P(r))&&!n.has(r)&&(n.add(r),n.size>=N))break}return Array.from(n)}function B(i){let n=$(i);if(n.length===0)return 0;let e=0;for(let r of n)A(r).length>0&&e++;return Math.round(e/n.length*1e3)/10}function bt(i,n){let e=y(i);if(e.length===0)return 0;let r=0;for(let a of e)S(a,n)&&r++;return Math.round(r/e.length*1e3)/10}function G(i,n){let e=0;for(let r of y(i))n(r)&&e++;return e}function At(i,n){let e=0;for(let r of $(i))n(r)&&e++;return e}function Mt(i,n,e,r){let a=[],m=[],o={},I=new Set(i),d=t=>n.map(s=>s[t]);for(let t of["city","zip","lat","lon","country"]){let s=e?.[t];s&&I.has(s)&&(o[t]=s)}let l=e?.state;if(l&&I.has(l)){let t=d(l),s=y(t);s.length>0&&s.every(c=>E(c,r))?m.push(`state=${l} (every value is "CA", which is both Canada and California)`):g(t)?(m.push(`state=${l} (every value is a country, not a state)`),o.country||(o.country=l)):T(t)<v?m.push(`state=${l} (only ${T(t)}% of values are states/provinces)`):o.state=l}let p=new Set(Object.values(o).filter(Boolean)),h=i.filter(t=>!p.has(t)&&!t.startsWith("__"));if(!o.state){let t=null;for(let s of h){let c=d(s);if(g(c))continue;let u=T(c);if(u<v)continue;let R=G(c,C=>!!f(C)),H=G(c,C=>!!f(C)&&!E(C,r));R<L&&H<1||(!t||u>t.pct)&&(t={name:s,pct:u})}t&&(o.state=t.name,p.add(t.name),a.push(`state=${t.name} (${t.pct}% states/provinces)`))}if(!o.zip)for(let t of h){if(p.has(t))continue;let s=d(t),c=B(s);if(!(c<ht)&&!(At(s,u=>A(u).length>0)<L)){o.zip=t,p.add(t),a.push(`zip=${t} (${c}% ZIP codes)`);break}}if(!o.country){for(let t of h)if(!p.has(t)&&g(d(t))){o.country=t,p.add(t),a.push(`country=${t}`);break}}if(!o.city){let t=null;for(let s of h){if(p.has(s))continue;let c=d(s),u=bt(c,r);u<v||G(c,R=>S(R,r))<L||(!t||u>t.pct)&&(t={name:s,pct:u})}t&&(o.city=t.name,a.push(`city=${t.name} (${t.pct}% known cities)`))}let _=o.country?d(o.country):[],x=!!o.country&&g(_),D=x?new Set(_.map(t=>b(t==null?null:String(t))).filter(Boolean)).size:0,z=x&&D>=2;return o.country&&!z&&!(o.city||o.state||o.zip||o.lat&&o.lon)&&m.push(x?`country=${o.country} (every row resolves to the same country - nothing to place apart)`:`country=${o.country} (values are not country identifiers)`),{bind:!!(o.city||o.state||o.zip||z||o.lat&&o.lon)?o:null,backfilled:a,refused:m}}export{k as GAZETTEER_MATCH_PCT,at as GET_RANDOM,dt as IndexedText,st as SIMPLE_STRING_HASH,rt as STR,T as admin1MatchPct,nt as buildGeoIsoColumn,j as buildGeoPointColumns,J as cityMatchPct,ft as classifyAdditivity,pt as classifyNumericValueNature,ut as classifyTemporal,et as detectFormatSignature,Q as detectGeo,V as detectOrdinalDomain,yt as engineTypeForSqlType,lt as hostAggHint,mt as ingest,M as isBlankLike,F as isCityTableLoaded,W as isGeoPointAmbiguity,ct as isIdentifierName,tt as isJoinGeoKind,O as isOrdinalFriendlyName,g as looksLikeCountryColumn,it as monthLookupFor,Z as normalizeCountry,ot as normalizeMonthKey,P as normalizePlaceName,q as registerCityTable,f as resolveAdmin1,X as resolveGeoPoint,Mt as resolvePointRoles,K as safeDistinctValuesToShip,Y as toGeoIso,B as zipMatchPct,A as zipPrefixCandidates,U as zipToPrefix3};
@@ -3,6 +3,7 @@ export type { IValueCollection } from "./indexedText";
3
3
  export { classifyTemporal, classifyAdditivity, classifyNumericValueNature, hostAggHint, isIdentifierName, } from "./indexedText";
4
4
  export type { LLMColumnWithValue } from "./models";
5
5
  export type { LLMRequestModifier, SimpleColumn, VegaRendererPayload, LLMClientHints, LLMRequestCode, LLMQualifyResult, LLMRequestCodeResult, GetLicenseStatusResult, } from "./models";
6
+ export { GAZETTEER_MATCH_PCT, isBlankLike } from "./matchQuality";
6
7
  export { detectOrdinalDomain, safeDistinctValuesToShip, isOrdinalFriendlyName } from "./ordinalDetector";
7
8
  export { detectFormatSignature } from "./formatDetector";
8
9
  export { detectGeo, toGeoIso, buildGeoIsoColumn, isJoinGeoKind } from "./geoDetector";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * THE KNOB. Minimum share of a column's non-blank DISTINCT values that must resolve against
3
+ * the gazetteer before the column can claim a geographic role.
4
+ *
5
+ * Tune here and every classifier that opts in moves together. Higher is stricter about
6
+ * claiming a role at all; lower risks a column of something else claiming one. 97 leaves
7
+ * room for the odd typo in an otherwise clean column while staying far out of reach of a
8
+ * column that is not really places.
9
+ *
10
+ * Deliberately NOT applied to the looser name roles (city/state at 85%), which tolerate
11
+ * messier real-world text by design — raising those is a separate decision with its own
12
+ * consequences, and belongs to Joel, not to this constant quietly widening its reach.
13
+ */
14
+ export declare const GAZETTEER_MATCH_PCT = 97;
15
+ /**
16
+ * Is this ALREADY-NORMALIZED token a blank in disguise?
17
+ *
18
+ * Callers pass the output of normalizePlaceName, so genuine blanks are "" by then; this
19
+ * catches the ones a person typed. Excluded from the denominator, not counted as a failed
20
+ * match — a column of 40 countries and one "N/A" is a clean country column with a hole in
21
+ * it, not a 97.6%-quality one, and the difference decides whether the map draws.
22
+ */
23
+ export declare function isBlankLike(normalized: string): boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bicharts/shape-core",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "description": "Host-agnostic data-shape profiler: ingest a dataset's rows through IValueCollection.addRow and read back the measured shape as an LLMColumnWithValue[] payload \u2014 types, cardinality, temporal/ordinal detection, geographic region and point resolution, cross-column signals. MEASUREMENT only: the policy that decides what a measured shape means for chart selection lives server-side.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",