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

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 +2024 -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 +49 -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 +147 -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 +49 -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 +137 -0
  32. package/lib-esm/util.js.map +1 -0
  33. package/package.json +6 -4
  34. package/src/Geo.ts +119 -20
  35. package/src/Providers/AmazonLocationServiceProvider.ts +422 -75
  36. package/src/types/AmazonLocationServiceProvider.ts +56 -1
  37. package/src/types/Geo.ts +73 -4
  38. package/src/types/Provider.ts +30 -6
  39. package/src/util.ts +180 -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 searchByCoordinates
76
81
  export type SearchByCoordinatesOptions = {
77
82
  maxResults?: number;
78
83
  searchIndexName?: string;
@@ -97,6 +102,70 @@ 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
+ export type GeofenceId = string;
117
+
118
+ // Geofence object used as input for saveGeofences
119
+ export type GeofenceInput = {
120
+ geofenceId: GeofenceId;
121
+ geometry: PolygonGeometry;
122
+ };
123
+
124
+ // Options object for saveGeofences
125
+ export type GeofenceOptions = {
126
+ providerName?: string;
127
+ };
100
128
 
101
- // Return type for searchForSuggestions
102
- export type SearchForSuggestionsResults = string[];
129
+ // Error type for errors related to Geofence API calls
130
+ export type GeofenceError = {
131
+ error: {
132
+ code: string;
133
+ message: string;
134
+ };
135
+ geofenceId: GeofenceId;
136
+ };
137
+
138
+ // Base geofence object
139
+ type GeofenceBase = {
140
+ geofenceId: GeofenceId;
141
+ createTime?: Date;
142
+ updateTime?: Date;
143
+ };
144
+
145
+ // Results object for getGeofence
146
+ export type Geofence = GeofenceBase & {
147
+ geometry: PolygonGeometry;
148
+ };
149
+
150
+ // Results object for saveGeofences
151
+ export type SaveGeofencesResults = {
152
+ successes: GeofenceBase[];
153
+ errors: GeofenceError[];
154
+ };
155
+
156
+ // Options object for listGeofence
157
+ export type ListGeofenceOptions = GeofenceOptions & {
158
+ nextToken?: string;
159
+ };
160
+
161
+ // Results options for listGeofence
162
+ export type ListGeofenceResults = {
163
+ entries: Geofence[];
164
+ nextToken: string | undefined;
165
+ };
166
+
167
+ // Results object for deleteGeofence
168
+ export type DeleteGeofencesResults = {
169
+ successes: GeofenceId[];
170
+ errors: GeofenceError[];
171
+ };
@@ -10,14 +10,20 @@
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
+ GeofenceId,
21
+ GeofenceInput,
22
+ GeofenceOptions,
23
+ ListGeofenceOptions,
24
+ ListGeofenceResults,
25
+ SaveGeofencesResults,
26
+ DeleteGeofencesResults,
21
27
  } from './Geo';
22
28
 
23
29
  export interface GeoProvider {
@@ -36,15 +42,33 @@ export interface GeoProvider {
36
42
  // get the map resource listed as default
37
43
  getDefaultMap(): MapStyle;
38
44
 
45
+ // search by a text string and return a list of places
39
46
  searchByText(text: string, options?: SearchByTextOptions): Promise<Place[]>;
40
47
 
48
+ // search by coordinates and return a matching place
41
49
  searchByCoordinates(
42
50
  coordinates: Coordinates,
43
51
  options?: SearchByCoordinatesOptions
44
52
  ): Promise<Place>;
45
53
 
46
- searchForSuggestions(
47
- text: string,
48
- options?: SearchByTextOptions
49
- ): Promise<SearchForSuggestionsResults>;
54
+ // create geofences
55
+ saveGeofences(
56
+ geofences: GeofenceInput[],
57
+ options?: GeofenceOptions
58
+ ): Promise<SaveGeofencesResults>;
59
+
60
+ // get a single geofence
61
+ getGeofence(
62
+ geofenceId: GeofenceId,
63
+ options?: ListGeofenceOptions
64
+ ): Promise<Geofence>;
65
+
66
+ // list all geofences
67
+ listGeofences(options?: ListGeofenceOptions): Promise<ListGeofenceResults>;
68
+
69
+ // Delete geofences
70
+ deleteGeofences(
71
+ geofenceIds: string[],
72
+ options?: GeofenceOptions
73
+ ): Promise<DeleteGeofencesResults>;
50
74
  }
package/src/util.ts ADDED
@@ -0,0 +1,180 @@
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
+ GeofenceId,
19
+ GeofenceInput,
20
+ GeofencePolygon,
21
+ LinearRing,
22
+ } from './types';
23
+
24
+ export function validateCoordinates(lng: Longitude, lat: Latitude): void {
25
+ if (!Number.isFinite(lng) || !Number.isFinite(lat)) {
26
+ throw new Error(`Invalid coordinates: [${lng},${lat}]`);
27
+ }
28
+ if (lat < -90 || 90 < lat) {
29
+ throw new Error('Latitude must be between -90 and 90 degrees inclusive.');
30
+ } else if (lng < -180 || 180 < lng) {
31
+ throw new Error(
32
+ 'Longitude must be between -180 and 180 degrees inclusive.'
33
+ );
34
+ }
35
+ }
36
+
37
+ export function validateGeofenceId(geofenceId: GeofenceId): void {
38
+ const geofenceIdRegex = /^[-._\p{L}\p{N}]+$/iu;
39
+
40
+ // Check if geofenceId is valid
41
+ if (!geofenceIdRegex.test(geofenceId)) {
42
+ throw new Error(
43
+ `Invalid geofenceId: '${geofenceId}' - IDs can only contain alphanumeric characters, hyphens, underscores and periods.`
44
+ );
45
+ }
46
+ }
47
+
48
+ export function validateLinearRing(
49
+ linearRing: LinearRing,
50
+ geofenceId?: GeofenceId
51
+ ): void {
52
+ const errorPrefix = geofenceId ? `${geofenceId}: ` : '';
53
+ // Validate LinearRing size, must be at least 4 points
54
+ if (linearRing.length < 4) {
55
+ throw new Error(
56
+ `${errorPrefix}LinearRing must contain 4 or more coordinates.`
57
+ );
58
+ }
59
+
60
+ // Validate all coordinates are valid, error with which ones are bad
61
+ const badCoordinates = [];
62
+ linearRing.forEach(coordinates => {
63
+ try {
64
+ validateCoordinates(coordinates[0], coordinates[1]);
65
+ } catch (error) {
66
+ badCoordinates.push({ coordinates, error: error.message });
67
+ }
68
+ });
69
+ if (badCoordinates.length > 0) {
70
+ throw new Error(
71
+ `${errorPrefix}One or more of the coordinates in the Polygon LinearRing are not valid: ${JSON.stringify(
72
+ badCoordinates
73
+ )}`
74
+ );
75
+ }
76
+
77
+ // Validate first and last coordinates are the same
78
+ const [lngA, latA] = linearRing[0];
79
+ const [lngB, latB] = linearRing[linearRing.length - 1];
80
+
81
+ if (lngA !== lngB || latA !== latB) {
82
+ throw new Error(
83
+ `${errorPrefix}LinearRing's first and last coordinates are not the same`
84
+ );
85
+ }
86
+
87
+ if (booleanClockwise(linearRing)) {
88
+ throw new Error(
89
+ `${errorPrefix}LinearRing coordinates must be wound counterclockwise`
90
+ );
91
+ }
92
+ }
93
+
94
+ export function validatePolygon(
95
+ polygon: GeofencePolygon,
96
+ geofenceId?: GeofenceId
97
+ ): void {
98
+ const errorPrefix = geofenceId ? `${geofenceId}: ` : '';
99
+ if (!Array.isArray(polygon)) {
100
+ throw new Error(
101
+ `${errorPrefix}Polygon is of incorrect structure. It should be an array of LinearRings`
102
+ );
103
+ }
104
+ if (polygon.length < 1) {
105
+ throw new Error(
106
+ `${errorPrefix}Polygon must have a single LinearRing array.`
107
+ );
108
+ }
109
+
110
+ if (polygon.length > 1) {
111
+ throw new Error(
112
+ `${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.`
113
+ );
114
+ }
115
+ const verticesCount = polygon.reduce(
116
+ (prev, linearRing) => prev + linearRing.length,
117
+ 0
118
+ );
119
+ if (verticesCount > 1000) {
120
+ throw new Error(
121
+ `${errorPrefix}Polygon has more than the maximum 1000 vertices.`
122
+ );
123
+ }
124
+ polygon.forEach(linearRing => {
125
+ validateLinearRing(linearRing, geofenceId);
126
+ });
127
+ }
128
+
129
+ export function validateGeofencesInput(geofences: GeofenceInput[]) {
130
+ const geofenceIds = {};
131
+
132
+ geofences.forEach((geofence: GeofenceInput) => {
133
+ // verify all required properties are present
134
+
135
+ // Validate geofenceId exists
136
+ if (!geofence.geofenceId) {
137
+ throw new Error(`Geofence '${geofence}' is missing geofenceId`);
138
+ }
139
+ const { geofenceId } = geofence;
140
+ validateGeofenceId(geofenceId);
141
+
142
+ // Validate geofenceId is unique
143
+ if (geofenceIds[geofenceId]) {
144
+ throw new Error(`Duplicate geofenceId: ${geofenceId}`);
145
+ } else {
146
+ geofenceIds[geofenceId] = true;
147
+ }
148
+
149
+ // Validate geometry exists
150
+ if (!geofence.geometry) {
151
+ throw new Error(`Geofence '${geofenceId}' is missing geometry`);
152
+ }
153
+ const { geometry } = geofence;
154
+
155
+ // Validate polygon exists
156
+ if (!geometry.polygon) {
157
+ throw new Error(`Geofence '${geofenceId}' is missing geometry.polygon`);
158
+ }
159
+ const { polygon } = geometry;
160
+
161
+ // Validate polygon length and structure
162
+ try {
163
+ validatePolygon(polygon, geofenceId);
164
+ } catch (error) {
165
+ if (
166
+ error.message.includes(
167
+ 'Polygon has more than the maximum 1000 vertices.'
168
+ )
169
+ ) {
170
+ throw new Error(
171
+ `Geofence '${geofenceId}' has more than the maximum of 1000 vertices`
172
+ );
173
+ }
174
+ }
175
+
176
+ // Validate LinearRing length, structure, and coordinates
177
+ const [linearRing] = polygon;
178
+ validateLinearRing(linearRing, geofenceId);
179
+ });
180
+ }