goblin-swiss 0.2.0 → 0.3.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.
Files changed (2) hide show
  1. package/lib/getAddress.js +67 -34
  2. package/package.json +1 -1
package/lib/getAddress.js CHANGED
@@ -1,69 +1,102 @@
1
- const BASE_URL = 'https://api3.geo.admin.ch/rest/services/ech/MapServer/find';
1
+ const BASE_URL = 'https://api3.geo.admin.ch/rest/services/ech/MapServer/';
2
2
 
3
3
  const LAYER = 'ch.swisstopo.amtliches-gebaeudeadressverzeichnis';
4
4
 
5
- /**
6
- * Resolve a structured address from a GeoAdmin SearchServer featureId.
7
- *
8
- * @param {string} featureId - SearchServer featureId, e.g. "1487827_0".
9
- * @param {AbortSignal} [signal] - Optional abort signal.
10
- * @returns {Promise<{
11
- * street: string|null,
12
- * houseNumber: string|null,
13
- * zip: string|null,
14
- * city: string|null,
15
- * municipality: string|null,
16
- * municipalityId: number|null,
17
- * egid: number|null,
18
- * edid: number|null,
19
- * egaid: number|null
20
- * }|null>}
21
- */
22
- async function getAddress(featureId, signal) {
23
- const [egid, edid = '0'] = String(featureId).split('_');
5
+ function parseZipLabel(zipLabel) {
6
+ const match = String(zipLabel ?? '')
7
+ .trim()
8
+ .match(/^(\d{4})\s+(.+)$/);
9
+ return match ? {zip: match[1], city: match[2]} : {zip: null, city: null};
10
+ }
24
11
 
12
+ async function findAddress(featureId, locale, signal) {
13
+ const [egid, edid = '0'] = String(featureId).split('_');
25
14
  const params = new URLSearchParams({
26
15
  layer: LAYER,
27
16
  searchText: egid,
28
17
  searchField: 'bdg_egid',
29
18
  contains: 'false',
30
19
  returnGeometry: 'false',
31
- lang: 'fr',
32
- });
33
-
34
- const response = await fetch(`${BASE_URL}?${params}`, {
35
- signal,
20
+ lang: locale,
36
21
  });
37
22
 
23
+ const response = await fetch(`${BASE_URL}find?${params}`, {signal});
38
24
  if (!response.ok) {
39
25
  throw new Error(
40
26
  `GeoAdmin lookup failed: ${response.status} ${response.statusText}`
41
27
  );
42
28
  }
43
29
 
44
- const data = await response.json();
30
+ const {results = []} = await response.json();
31
+ return (
32
+ results.find(({attributes}) => String(attributes?.adr_edid ?? '0') === edid)
33
+ ?.attributes ??
34
+ results[0]?.attributes ??
35
+ null
36
+ );
37
+ }
45
38
 
46
- const candidates = data.results ?? [];
39
+ async function getFeatureAddress(featureId, locale, signal) {
40
+ if (String(featureId).includes('_')) {
41
+ return findAddress(featureId, locale, signal);
42
+ }
47
43
 
48
- const result =
49
- candidates.find(
50
- ({attributes}) => String(attributes?.adr_edid ?? '0') === edid
51
- ) ?? candidates[0];
44
+ const params = new URLSearchParams({
45
+ returnGeometry: 'false',
46
+ lang: locale,
47
+ });
48
+ const response = await fetch(
49
+ `${BASE_URL}${LAYER}/${encodeURIComponent(featureId)}?${params}`,
50
+ {signal}
51
+ );
52
+ if (!response.ok) {
53
+ throw new Error(
54
+ `GeoAdmin lookup failed: ${response.status} ${response.statusText}`
55
+ );
56
+ }
52
57
 
53
- if (!result) {
58
+ const {feature} = await response.json();
59
+ return feature?.attributes ?? null;
60
+ }
61
+
62
+ /**
63
+ * Resolve a structured address from a GeoAdmin SearchServer featureId.
64
+ *
65
+ * @param {string|number} featureId - SearchServer featureId.
66
+ * @param {string} [locale='fr'] - Result language.
67
+ * @param {AbortSignal} [signal] - Optional abort signal.
68
+ * @returns {Promise<{
69
+ * street: string|null,
70
+ * houseNumber: string|null,
71
+ * zip: string|null,
72
+ * city: string|null,
73
+ * municipality: string|null,
74
+ * municipalityId: number|null,
75
+ * egid: number|null,
76
+ * edid: number|null,
77
+ * egaid: number|null,
78
+ * canton: string|null
79
+ * }|null>}
80
+ */
81
+ async function getAddress(featureId, locale = 'fr', signal) {
82
+ const attrs = await getFeatureAddress(featureId, locale, signal);
83
+ if (!attrs) {
54
84
  return null;
55
85
  }
56
86
 
57
- const attrs = result.attributes ?? {};
87
+ const {zip, city} = parseZipLabel(attrs.zip_label);
58
88
 
59
89
  return {
60
- street: attrs.stn_label ?? attrs.str_label ?? null,
90
+ street: attrs.stn_label ?? null,
61
91
  houseNumber: attrs.adr_number ?? null,
92
+ zip,
93
+ city,
62
94
  municipality: attrs.com_name ?? null,
63
95
  municipalityId: attrs.com_fosnr ?? null,
64
96
  egid: attrs.bdg_egid ?? null,
65
97
  edid: attrs.adr_edid ?? null,
66
98
  egaid: attrs.adr_egaid ?? null,
99
+ canton: attrs.com_canton ?? null,
67
100
  };
68
101
  }
69
102
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "goblin-swiss",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Swiss stuff",
5
5
  "author": "Epsitec SA",
6
6
  "contributors": [