Skip to content

Commit 1ad96c4

Browse files
committed
fix: remove features not supported upstream
1 parent a5e4e16 commit 1ad96c4

File tree

4 files changed

+5
-156
lines changed

4 files changed

+5
-156
lines changed

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
"@types/google.maps": "^3.53.1",
4545
"@types/jest": "^29.5.5",
4646
"@types/selenium-webdriver": "^4.0.9",
47-
"@types/trusted-types": "^2.0.7",
4847
"@typescript-eslint/eslint-plugin": "^8.8.1",
4948
"@typescript-eslint/parser": "^8.8.1",
5049
"core-js": "^3.6.4",

src/2.0/2.0.md

Lines changed: 1 addition & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -22,105 +22,6 @@ import { setOptions, importLibrary } from "@googlemaps/js-api-loader";
2222
const { Map } = await importLibrary("maps");
2323
```
2424

25-
## Synchronous API (TBD)
26-
27-
### Motivation
28-
29-
There are a lot of situations where the `importLibrary` function doesn't
30-
work well, since using an async function or promises isn't always a viable
31-
option.
32-
33-
Currently, the only alternative to `importLibrary` is to use the global
34-
`google.maps` namespaces. An additional synchronous API is intended to
35-
provide an alternative way to using the global namespaces while solving some
36-
of the problems that come with using them.
37-
38-
Any synchronous access to the libraries requires developers to make sure the
39-
libraries have already been loaded when the corresponding code is executed.
40-
In practice, this is rarely a big issue.
41-
42-
The exact shape of the synchronous API is to be determined, it could be a
43-
simple Map instance `libraries` or a pair of has/get functions to check for and
44-
retrieve loaded libraries.
45-
46-
### Example 1: helper classes
47-
48-
Imagine some service class that uses the `places` library and the
49-
`PlacesService` to do it's thing.
50-
51-
#### global namespace
52-
53-
This is how it would be written with the global `google.maps` namespace:
54-
55-
```tsx
56-
class PlacesHelper {
57-
private service: google.maps.places.PlacesService;
58-
59-
constructor() {
60-
if (!google.maps.places.PlacesService)
61-
throw new Error("maps api or places library missing");
62-
63-
this.service = new google.maps.places.PlacesService();
64-
}
65-
66-
// ...
67-
}
68-
```
69-
70-
This has two drawbacks:
71-
72-
- having to write out `google.maps.places` for all classes (and
73-
types, but that's a seperate issue) adds a lot of "noise" to the code
74-
- references to the global namespace can't really be minified, and
75-
due to the late loading of the API, a global assignment to a shorthand
76-
name isn't really possible.
77-
78-
#### importLibrary
79-
80-
Since in a constructor, we can't `await` the result of `importLibrary`, the
81-
only way to do this is using the `.then()` function, which drastically
82-
changes the semantics of the code:
83-
84-
```tsx
85-
class PlacesHelper {
86-
private service: google.maps.places.PlacesService | null = null;
87-
88-
constructor() {
89-
importLibrary("places").then(
90-
({ PlacesService }) => (this.service = new PlacesService())
91-
);
92-
}
93-
}
94-
```
95-
96-
Here, the service has to be declared as optional (`| null`) in typescript,
97-
and every other method of the class has to somehow deal with the fact that
98-
the service might not yet have been initialized. Even if the library is
99-
already loaded, it won't be returned until the queued mircotasks and the
100-
handlers for the awaited Promise are executed.
101-
This can even have cascading effects on all classes calling methods of this
102-
class.
103-
104-
#### proposed sync API
105-
106-
A synchronous API would allow us to write the same code we used for
107-
global namespaces, but without the readability problems and without global
108-
namespaces:
109-
110-
```tsx
111-
class PlacesHelper {
112-
private service: google.maps.places.PlacesService = null;
113-
114-
constructor() {
115-
if (!isLibraryImported("places"))
116-
throw new Error("maps api or places library missing");
117-
118-
const { PlacesService } = getImportedLibrary("places");
119-
this.service = new PlacesService();
120-
}
121-
}
122-
```
123-
12425
## Internal Behavior
12526

12627
- the ApiLoader doesn't do anything (except for storing the options) until
@@ -129,7 +30,7 @@ class PlacesHelper {
12930
even if the maps API isn't used on most pages.
13031

13132
- Once the importLibrary function is called, the options are frozen and
132-
attempts to modify them will throw an Error
33+
attempts to modify them will get ignored
13334

13435
- the first call to importLibrary initiates the bootstrapping, once the
13536
maps API is loaded, importLibrary will directly forward to the

src/2.0/index.ts

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,7 @@ const libraries_: Partial<APILibraryMap> = {};
3333
*/
3434
export function setOptions(options: APIOptions) {
3535
if (isBootrapped_) {
36-
throw new Error(
37-
"options cannot be modified after the API has been loaded."
38-
);
36+
return;
3937
}
4038

4139
options_ = options;
@@ -49,7 +47,7 @@ export async function importLibrary(
4947
): ReturnType<typeof google.maps.importLibrary>;
5048

5149
export async function importLibrary<
52-
TLibraryName extends keyof APILibraryMap,
50+
TLibraryName extends APILibraryName,
5351
TLibrary extends APILibraryMap[TLibraryName],
5452
>(libraryName: TLibraryName): Promise<TLibrary> {
5553
if (!isBootrapped_) {
@@ -76,33 +74,9 @@ export async function importLibrary<
7674
return libraries_[libraryName] as TLibrary;
7775
}
7876

79-
/**
80-
* Synchronously loads a library. Will directly return the library, or null
81-
* if it hasn't been loaded.
82-
*/
83-
export function getImportedLibrary<
84-
TLibraryName extends APILibraryName,
85-
TLibrary extends APILibraryMap[TLibraryName],
86-
>(libraryName: TLibraryName): TLibrary | null {
87-
if (!isLibraryImported(libraryName)) {
88-
throw new Error(`library ${libraryName} hasn't been imported.`);
89-
}
90-
91-
return libraries_[libraryName] as TLibrary;
92-
}
93-
94-
/**
95-
* Check if the given library has already been loaded.
96-
*/
97-
export function isLibraryImported(libraryName: APILibraryName): boolean {
98-
return libraryName in libraries_;
99-
}
100-
10177
const api = {
10278
setOptions,
10379
importLibrary,
104-
getImportedLibrary,
105-
isLibraryImported,
10680
};
10781

10882
export default api;

src/2.0/loader.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,7 @@ export function bootstrapLoader(options: APIOptions) {
5959
urlParameters.set("callback", `google.maps.__ib__`);
6060

6161
const scriptEl = document.createElement("script");
62-
scriptEl.src = getTrustedScriptURL(
63-
`https://maps.googleapis.com/maps/api/js?${urlParameters.toString()}`
64-
) as string;
62+
scriptEl.src = `https://maps.googleapis.com/maps/api/js?${urlParameters.toString()}`;
6563

6664
scriptEl.onerror = () => {
6765
reject(new APILoadingError());
@@ -81,7 +79,7 @@ export function bootstrapLoader(options: APIOptions) {
8179
return apiLoadedPromise;
8280
};
8381

84-
// create intermediate importLibrary function that loads the API and calls
82+
// create the intermediate importLibrary function that loads the API and calls
8583
// the real importLibrary function.
8684
google.maps.importLibrary = async (library: string) => {
8785
libraries.add(library);
@@ -91,26 +89,3 @@ export function bootstrapLoader(options: APIOptions) {
9189
return google.maps.importLibrary(library);
9290
};
9391
}
94-
95-
const getTrustedScriptURL: (url: string) => string | TrustedScriptURL = (() => {
96-
// check if trustedTypes are supported
97-
if (typeof window === "undefined" || !("trustedTypes" in window)) {
98-
return (url) => url;
99-
}
100-
101-
// this policy will only certify the `maps.googleapis.com` script url,
102-
// everything else will throw an error.
103-
const policy = window.trustedTypes.createPolicy(
104-
"google-maps-api#js-api-loader",
105-
{
106-
createScriptURL: (input) => {
107-
const url = new URL(input);
108-
if (url.host !== "maps.googleapis.com") throw new Error("invalid url");
109-
110-
return input;
111-
},
112-
}
113-
);
114-
115-
return (url) => policy.createScriptURL(url);
116-
})();

0 commit comments

Comments
 (0)