@aws-amplify/geo 1.2.4 → 1.2.5-geo.11

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 (39) hide show
  1. package/dist/aws-amplify-geo.js +2020 -137
  2. package/dist/aws-amplify-geo.js.map +1 -1
  3. package/dist/aws-amplify-geo.min.js +6 -6
  4. package/dist/aws-amplify-geo.min.js.map +1 -1
  5. package/lib/Geo.d.ts +36 -10
  6. package/lib/Geo.js +140 -20
  7. package/lib/Geo.js.map +1 -1
  8. package/lib/Providers/AmazonLocationServiceProvider.d.ts +37 -8
  9. package/lib/Providers/AmazonLocationServiceProvider.js +405 -53
  10. package/lib/Providers/AmazonLocationServiceProvider.js.map +1 -1
  11. package/lib/types/AmazonLocationServiceProvider.d.ts +21 -1
  12. package/lib/types/Geo.d.ts +48 -2
  13. package/lib/types/Provider.d.ts +5 -2
  14. package/lib/types/Provider.js +0 -12
  15. package/lib/types/Provider.js.map +1 -1
  16. package/lib/util.d.ts +6 -0
  17. package/lib/util.js +144 -0
  18. package/lib/util.js.map +1 -0
  19. package/lib-esm/Geo.d.ts +36 -10
  20. package/lib-esm/Geo.js +140 -20
  21. package/lib-esm/Geo.js.map +1 -1
  22. package/lib-esm/Providers/AmazonLocationServiceProvider.d.ts +37 -8
  23. package/lib-esm/Providers/AmazonLocationServiceProvider.js +406 -54
  24. package/lib-esm/Providers/AmazonLocationServiceProvider.js.map +1 -1
  25. package/lib-esm/types/AmazonLocationServiceProvider.d.ts +21 -1
  26. package/lib-esm/types/Geo.d.ts +48 -2
  27. package/lib-esm/types/Provider.d.ts +5 -2
  28. package/lib-esm/types/Provider.js +0 -12
  29. package/lib-esm/types/Provider.js.map +1 -1
  30. package/lib-esm/util.d.ts +6 -0
  31. package/lib-esm/util.js +134 -0
  32. package/lib-esm/util.js.map +1 -0
  33. package/package.json +6 -4
  34. package/src/Geo.ts +118 -20
  35. package/src/Providers/AmazonLocationServiceProvider.ts +422 -75
  36. package/src/types/AmazonLocationServiceProvider.ts +56 -1
  37. package/src/types/Geo.ts +71 -4
  38. package/src/types/Provider.ts +29 -6
  39. package/src/util.ts +173 -0
package/src/types/Geo.ts CHANGED
@@ -22,6 +22,10 @@ export interface GeoConfig {
22
22
  items: string[];
23
23
  default: string;
24
24
  };
25
+ geofenceCollections?: {
26
+ items: string[];
27
+ default: string;
28
+ };
25
29
  };
26
30
  }
27
31
 
@@ -31,10 +35,10 @@ export interface MapStyle {
31
35
  style: string;
32
36
  }
33
37
 
34
- export type Latitude = number;
35
38
  export type Longitude = number;
39
+ export type Latitude = number;
36
40
 
37
- // Coordinate point
41
+ // Coordinates are a tuple of longitude and latitude
38
42
  export type Coordinates = [Longitude, Latitude];
39
43
 
40
44
  // SW Longitude point for bounding box
@@ -73,6 +77,7 @@ export type SearchByTextOptions =
73
77
  | SearchByTextOptionsWithBiasPosition
74
78
  | SearchByTextOptionsWithSearchAreaConstraints;
75
79
 
80
+ // Options object for searchByCoodinates
76
81
  export type SearchByCoordinatesOptions = {
77
82
  maxResults?: number;
78
83
  searchIndexName?: string;
@@ -97,6 +102,68 @@ export interface Place {
97
102
  street?: string;
98
103
  subRegion?: string;
99
104
  }
105
+ // Array of 4 or more coordinates, where the first and last coordinate are the same to form a closed boundary
106
+ export type LinearRing = Coordinates[];
107
+
108
+ // An array of one linear ring
109
+ export type GeofencePolygon = LinearRing[];
110
+
111
+ // Geometry object for Polygon
112
+ export type PolygonGeometry = {
113
+ polygon: GeofencePolygon;
114
+ };
115
+
116
+ // Geofence object used as input for saveGeofences
117
+ export type GeofenceInput = {
118
+ geofenceId: string;
119
+ geometry: PolygonGeometry;
120
+ };
100
121
 
101
- // Return type for searchForSuggestions
102
- export type SearchForSuggestionsResults = string[];
122
+ // Options object for saveGeofences
123
+ export type GeofenceOptions = {
124
+ providerName?: string;
125
+ };
126
+
127
+ // Error type for errors related to Geofence API calls
128
+ export type GeofenceError = {
129
+ error: {
130
+ code: string;
131
+ message: string;
132
+ };
133
+ geofenceId: string;
134
+ };
135
+
136
+ // Base geofence object
137
+ type GeofenceBase = {
138
+ geofenceId: string;
139
+ createTime?: Date;
140
+ updateTime?: Date;
141
+ };
142
+
143
+ // Results object for getGeofence
144
+ export type Geofence = GeofenceBase & {
145
+ geometry: PolygonGeometry;
146
+ };
147
+
148
+ // Results object for saveGeofences
149
+ export type SaveGeofencesResults = {
150
+ successes: GeofenceBase[];
151
+ errors: GeofenceError[];
152
+ };
153
+
154
+ // Options object for listGeofence
155
+ export type ListGeofenceOptions = GeofenceOptions & {
156
+ nextToken?: string;
157
+ };
158
+
159
+ // Results options for listGeofence
160
+ export type ListGeofenceResults = {
161
+ entries: Geofence[];
162
+ nextToken: string;
163
+ };
164
+
165
+ // Results object for deleteGeofence
166
+ export type DeleteGeofencesResults = {
167
+ successes: string[];
168
+ errors: GeofenceError[];
169
+ };
@@ -10,14 +10,19 @@
10
10
  * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
11
  * and limitations under the License.
12
12
  */
13
-
14
13
  import {
15
14
  SearchByTextOptions,
16
15
  SearchByCoordinatesOptions,
17
- SearchForSuggestionsResults,
18
16
  Coordinates,
19
17
  Place,
20
18
  MapStyle,
19
+ Geofence,
20
+ GeofenceInput,
21
+ GeofenceOptions,
22
+ ListGeofenceOptions,
23
+ ListGeofenceResults,
24
+ SaveGeofencesResults,
25
+ DeleteGeofencesResults,
21
26
  } from './Geo';
22
27
 
23
28
  export interface GeoProvider {
@@ -36,15 +41,33 @@ export interface GeoProvider {
36
41
  // get the map resource listed as default
37
42
  getDefaultMap(): MapStyle;
38
43
 
44
+ // search by a text string and return a list of places
39
45
  searchByText(text: string, options?: SearchByTextOptions): Promise<Place[]>;
40
46
 
47
+ // search by coordinates and return a matching place
41
48
  searchByCoordinates(
42
49
  coordinates: Coordinates,
43
50
  options?: SearchByCoordinatesOptions
44
51
  ): Promise<Place>;
45
52
 
46
- searchForSuggestions(
47
- text: string,
48
- options?: SearchByTextOptions
49
- ): Promise<SearchForSuggestionsResults>;
53
+ // create geofences
54
+ saveGeofences(
55
+ geofences: GeofenceInput[],
56
+ options?: GeofenceOptions
57
+ ): Promise<SaveGeofencesResults>;
58
+
59
+ // get a single geofence
60
+ getGeofence(
61
+ geofenceId: string,
62
+ options?: ListGeofenceOptions
63
+ ): Promise<Geofence>;
64
+
65
+ // list all geofences
66
+ listGeofences(options?: ListGeofenceOptions): Promise<ListGeofenceResults>;
67
+
68
+ // Delete geofences
69
+ deleteGeofences(
70
+ geofenceIds: string[],
71
+ options?: GeofenceOptions
72
+ ): Promise<DeleteGeofencesResults>;
50
73
  }
package/src/util.ts ADDED
@@ -0,0 +1,173 @@
1
+ /*
2
+ * Copyright 2017-2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance with
5
+ * the License. A copy of the License is located at
6
+ *
7
+ * http://aws.amazon.com/apache2.0/
8
+ *
9
+ * or in the "license" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
10
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
11
+ * and limitations under the License.
12
+ */
13
+ import booleanClockwise from '@turf/boolean-clockwise';
14
+
15
+ import {
16
+ Longitude,
17
+ Latitude,
18
+ GeofenceInput,
19
+ GeofencePolygon,
20
+ LinearRing,
21
+ } from './types';
22
+
23
+ export function validateCoordinates(lng: Longitude, lat: Latitude): void {
24
+ if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
25
+ throw new Error(`Invalid coordinates: [${lng},${lat}]`);
26
+ }
27
+ if (lat < -90 || lat > 90) {
28
+ throw new Error('Latitude must be between -90 and 90 degrees inclusive.');
29
+ } else if (lng < -180 || lng > 180) {
30
+ throw new Error(
31
+ 'Longitude must be between -180 and 180 degrees inclusive.'
32
+ );
33
+ }
34
+ }
35
+
36
+ export function validateGeofenceId(geofenceId: string): void {
37
+ const geofenceIdRegex = /^[-._\p{L}\p{N}]+$/iu;
38
+
39
+ // Check if geofenceId is valid
40
+ if (!geofenceIdRegex.test(geofenceId)) {
41
+ throw new Error(
42
+ `Invalid geofenceId: '${geofenceId}' - IDs can only contain alphanumeric characters, hyphens, underscores and periods.`
43
+ );
44
+ }
45
+ }
46
+
47
+ export function validateLinearRing(
48
+ linearRing: LinearRing,
49
+ geofenceId?: string
50
+ ): void {
51
+ const errorPrefix = geofenceId ? `${geofenceId}: ` : '';
52
+ // Validate LinearRing size, must be at least 4 points
53
+ if (linearRing.length < 4) {
54
+ throw new Error(
55
+ `${errorPrefix}LinearRing must contain 4 or more coordinates.`
56
+ );
57
+ }
58
+
59
+ // Validate all coordinates are valid, error with which ones are bad
60
+ const badCoordinates = [];
61
+ linearRing.forEach(coordinates => {
62
+ try {
63
+ validateCoordinates(coordinates[0], coordinates[1]);
64
+ } catch (error) {
65
+ badCoordinates.push({ coordinates, error: error.message });
66
+ }
67
+ });
68
+ if (badCoordinates.length > 0) {
69
+ throw new Error(
70
+ `${errorPrefix}One or more of the coordinates in the Polygon LinearRing are not valid: ${JSON.stringify(
71
+ badCoordinates
72
+ )}`
73
+ );
74
+ }
75
+
76
+ // Validate first and last coordinates are the same
77
+ const [lngA, latA] = linearRing[0];
78
+ const [lngB, latB] = linearRing[linearRing.length - 1];
79
+
80
+ if (lngA !== lngB || latA !== latB) {
81
+ throw new Error(
82
+ `${errorPrefix}LinearRing's first and last coordinates are not the same`
83
+ );
84
+ }
85
+
86
+ if (booleanClockwise(linearRing)) {
87
+ throw new Error(
88
+ `${errorPrefix}LinearRing coordinates must be wound counterclockwise`
89
+ );
90
+ }
91
+ }
92
+
93
+ export function validatePolygon(
94
+ polygon: GeofencePolygon,
95
+ geofenceId?: string
96
+ ): void {
97
+ const errorPrefix = geofenceId ? `${geofenceId}: ` : '';
98
+ if (!Array.isArray(polygon)) {
99
+ throw new Error(
100
+ `${errorPrefix}Polygon is of incorrect structure. It should be an array of LinearRings`
101
+ );
102
+ }
103
+ if (polygon.length < 1) {
104
+ throw new Error(
105
+ `${errorPrefix}Polygon must have a single LinearRing array.`
106
+ );
107
+ }
108
+ if (polygon.length > 1) {
109
+ throw new Error(
110
+ `${errorPrefix}Polygon must have a single LinearRing array. Note: We do not currently support polygons with holes, multipolygons, polygons that are wound clockwise, or that cross the antimeridian.`
111
+ );
112
+ }
113
+ const verticesCount = polygon.reduce(
114
+ (prev, linearRing) => prev + linearRing.length,
115
+ 0
116
+ );
117
+ if (verticesCount > 1000) {
118
+ throw new Error(
119
+ `${errorPrefix}Polygon has more than the maximum 1000 vertices.`
120
+ );
121
+ }
122
+ }
123
+
124
+ export function validateGeofencesInput(geofences: GeofenceInput[]) {
125
+ const geofenceIds = {};
126
+
127
+ geofences.forEach((geofence: GeofenceInput) => {
128
+ // verify all required properties are present
129
+
130
+ // Validate geofenceId exists
131
+ if (!geofence.geofenceId) {
132
+ throw new Error(`Geofence '${geofence}' is missing geofenceId`);
133
+ }
134
+ const { geofenceId } = geofence;
135
+ validateGeofenceId(geofenceId);
136
+
137
+ // Validate geofenceId is unique
138
+ if (geofenceIds[geofenceId]) {
139
+ throw new Error(`Duplicate geofenceId: ${geofenceId}`);
140
+ } else {
141
+ geofenceIds[geofenceId] = true;
142
+ }
143
+
144
+ // Validate geometry exists
145
+ if (!geofence.geometry) {
146
+ throw new Error(`Geofence '${geofenceId}' is missing geometry`);
147
+ }
148
+ const { geometry } = geofence;
149
+
150
+ // Validate polygon exists
151
+ if (!geometry.polygon) {
152
+ throw new Error(`Geofence '${geofenceId}' is missing geometry.polygon`);
153
+ }
154
+ const { polygon } = geometry;
155
+
156
+ // Validate polygon length and structure
157
+ try {
158
+ validatePolygon(polygon, geofenceId);
159
+ } catch (error) {
160
+ if (
161
+ error.message === `Polygon has more than the maximum 1000 vertices.`
162
+ ) {
163
+ throw new Error(
164
+ `Geofence '${geofenceId}' has more than the maximum of 1000 vertices`
165
+ );
166
+ }
167
+ }
168
+
169
+ // Validate LinearRing length, structure, and coordinates
170
+ const [linearRing] = polygon;
171
+ validateLinearRing(linearRing, geofenceId);
172
+ });
173
+ }