@volter/twin-googlemaps 0.1.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.
- package/LICENSE +202 -0
- package/README.md +96 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +23 -0
- package/dist/src/googlemaps-auth.d.ts +31 -0
- package/dist/src/googlemaps-auth.js +37 -0
- package/dist/src/googlemaps-budget.d.ts +61 -0
- package/dist/src/googlemaps-budget.js +142 -0
- package/dist/src/googlemaps-capabilities.d.ts +3 -0
- package/dist/src/googlemaps-capabilities.js +648 -0
- package/dist/src/googlemaps-conformance.d.ts +8 -0
- package/dist/src/googlemaps-conformance.js +18 -0
- package/dist/src/googlemaps-connector.d.ts +94 -0
- package/dist/src/googlemaps-connector.js +243 -0
- package/dist/src/googlemaps-data.d.ts +87 -0
- package/dist/src/googlemaps-data.js +370 -0
- package/dist/src/googlemaps-perform-harness.d.ts +5 -0
- package/dist/src/googlemaps-perform-harness.js +17 -0
- package/dist/src/googlemaps-server.d.ts +14 -0
- package/dist/src/googlemaps-server.js +25 -0
- package/dist/src/googlemaps-twin.d.ts +2 -0
- package/dist/src/googlemaps-twin.js +1116 -0
- package/dist/src/googlemaps-types.d.ts +45 -0
- package/dist/src/googlemaps-types.js +1 -0
- package/dist/src/index.d.ts +11 -0
- package/dist/src/index.js +65 -0
- package/package.json +52 -0
- package/src/cli.ts +22 -0
- package/src/googlemaps-auth.ts +52 -0
- package/src/googlemaps-budget.ts +168 -0
- package/src/googlemaps-capabilities.ts +766 -0
- package/src/googlemaps-conformance.ts +24 -0
- package/src/googlemaps-connector.ts +250 -0
- package/src/googlemaps-data.ts +399 -0
- package/src/googlemaps-perform-harness.ts +17 -0
- package/src/googlemaps-server.ts +33 -0
- package/src/googlemaps-twin.ts +1110 -0
- package/src/googlemaps-types.ts +47 -0
- package/src/index.ts +124 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export type GoogleMapsRequest = {
|
|
2
|
+
method: string;
|
|
3
|
+
path: string;
|
|
4
|
+
body?: string;
|
|
5
|
+
root?: string;
|
|
6
|
+
readOnly?: boolean;
|
|
7
|
+
occurredAt?: string;
|
|
8
|
+
headers?: Record<string, string>;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type GoogleMapsResponse = { status: number; body: unknown };
|
|
12
|
+
|
|
13
|
+
/** Web-service ("Maps") status enum shared across geocode/directions/etc. */
|
|
14
|
+
export type MapsStatus =
|
|
15
|
+
| 'OK'
|
|
16
|
+
| 'ZERO_RESULTS'
|
|
17
|
+
| 'OVER_DAILY_LIMIT'
|
|
18
|
+
| 'OVER_QUERY_LIMIT'
|
|
19
|
+
| 'REQUEST_DENIED'
|
|
20
|
+
| 'INVALID_REQUEST'
|
|
21
|
+
| 'MAX_ELEMENTS_EXCEEDED'
|
|
22
|
+
| 'MAX_WAYPOINTS_EXCEEDED'
|
|
23
|
+
| 'MAX_ROUTE_LENGTH_EXCEEDED'
|
|
24
|
+
| 'NOT_FOUND'
|
|
25
|
+
| 'UNKNOWN_ERROR';
|
|
26
|
+
|
|
27
|
+
export type LatLng = { lat: number; lng: number };
|
|
28
|
+
|
|
29
|
+
export type Viewport = { northeast: LatLng; southwest: LatLng };
|
|
30
|
+
|
|
31
|
+
export type AddressComponent = { long_name: string; short_name: string; types: string[] };
|
|
32
|
+
|
|
33
|
+
export type Geometry = {
|
|
34
|
+
location: LatLng;
|
|
35
|
+
location_type: 'ROOFTOP' | 'RANGE_INTERPOLATED' | 'GEOMETRIC_CENTER' | 'APPROXIMATE';
|
|
36
|
+
viewport: Viewport;
|
|
37
|
+
bounds?: Viewport;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type GeocodeResult = {
|
|
41
|
+
address_components: AddressComponent[];
|
|
42
|
+
formatted_address: string;
|
|
43
|
+
geometry: Geometry;
|
|
44
|
+
place_id: string;
|
|
45
|
+
types: string[];
|
|
46
|
+
plus_code?: { global_code: string; compound_code: string };
|
|
47
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
export { handleGoogleMapsTwinRequest } from './googlemaps-twin.ts';
|
|
2
|
+
export { createGoogleMapsTwinFetch, createGoogleMapsTwinServer, type GoogleMapsTwinFetchOptions } from './googlemaps-server.ts';
|
|
3
|
+
export {
|
|
4
|
+
GOOGLEMAPS_API_BASE,
|
|
5
|
+
googleMapsRequestForAction,
|
|
6
|
+
liveGoogleMapsExecute,
|
|
7
|
+
pullGoogleMapsGeocodes,
|
|
8
|
+
pullGoogleMapsPlaces,
|
|
9
|
+
pushGoogleMapsAction,
|
|
10
|
+
syncGoogleMapsFromReal,
|
|
11
|
+
} from './googlemaps-connector.ts';
|
|
12
|
+
export type { GoogleMapsExecute } from './googlemaps-connector.ts';
|
|
13
|
+
// The client-side rate budget — the fail-closed backstop `liveGoogleMapsExecute` routes every live
|
|
14
|
+
// request through. The mechanism is the kernel's (`@volter/world-core` → rateBudget.ts); these are this
|
|
15
|
+
// vendor's numbers and the typed bindings around them.
|
|
16
|
+
export {
|
|
17
|
+
GOOGLEMAPS_BUDGET_CEILING,
|
|
18
|
+
GOOGLEMAPS_BUDGET_MAX_RETRY_AFTER_S,
|
|
19
|
+
GOOGLEMAPS_BUDGET_WINDOW_MS,
|
|
20
|
+
GOOGLEMAPS_CALL_WEIGHTS,
|
|
21
|
+
GOOGLEMAPS_RATE_BUDGET,
|
|
22
|
+
GoogleMapsBudget,
|
|
23
|
+
GoogleMapsBudgetError,
|
|
24
|
+
googleMapsBudgetPath,
|
|
25
|
+
googleMapsCallWeight,
|
|
26
|
+
splitGoogleMapsPath,
|
|
27
|
+
} from './googlemaps-budget.ts';
|
|
28
|
+
export type {
|
|
29
|
+
GoogleMapsBudgetErrorKind,
|
|
30
|
+
GoogleMapsBudgetOptions,
|
|
31
|
+
GoogleMapsBudgetReservation,
|
|
32
|
+
GoogleMapsBudgetSnapshot,
|
|
33
|
+
} from './googlemaps-budget.ts';
|
|
34
|
+
export {
|
|
35
|
+
allPlaces,
|
|
36
|
+
deterministicDuration,
|
|
37
|
+
deterministicElevation,
|
|
38
|
+
deterministicLatLng,
|
|
39
|
+
deterministicTimeZone,
|
|
40
|
+
distanceText,
|
|
41
|
+
durationText,
|
|
42
|
+
encodePolyline,
|
|
43
|
+
findPlaceById,
|
|
44
|
+
findPlaceByLatLng,
|
|
45
|
+
findPlaceByText,
|
|
46
|
+
geocodeResultFromPlace,
|
|
47
|
+
haversineMeters,
|
|
48
|
+
isZeroResultsQuery,
|
|
49
|
+
normalizeAddress,
|
|
50
|
+
stableHash,
|
|
51
|
+
synthGeocodeResult,
|
|
52
|
+
viewportAround,
|
|
53
|
+
} from './googlemaps-data.ts';
|
|
54
|
+
export type { CannedPlace } from './googlemaps-data.ts';
|
|
55
|
+
export type {
|
|
56
|
+
AddressComponent,
|
|
57
|
+
GeocodeResult,
|
|
58
|
+
Geometry,
|
|
59
|
+
GoogleMapsRequest,
|
|
60
|
+
GoogleMapsResponse,
|
|
61
|
+
LatLng,
|
|
62
|
+
MapsStatus,
|
|
63
|
+
Viewport,
|
|
64
|
+
} from './googlemaps-types.ts';
|
|
65
|
+
|
|
66
|
+
import { registerPack, type TwinPack } from '@volter/world-core';
|
|
67
|
+
import { GOOGLEMAPS_RATE_BUDGET as RATE_BUDGET } from './googlemaps-budget.ts';
|
|
68
|
+
|
|
69
|
+
import { performGoogleMapsAction, syncGoogleMapsFromRemote } from './googlemaps-connector.ts';
|
|
70
|
+
|
|
71
|
+
export const pack: TwinPack = {
|
|
72
|
+
// PROTOCOL 2 (docs/contributing/architecture.md#protocol-2-the-pack-is-a-plugin): the pack is a plugin — its wire, its tree, and its half of the real
|
|
73
|
+
// state system. Moved 2026-09-08. The Google Maps APIs answer questions and accept no writes, so `perform`
|
|
74
|
+
// settles every entry with that reason and only `refresh` ever crosses.
|
|
75
|
+
protocol: '2',
|
|
76
|
+
refresh: { every: '1h', onDemand: { atMost: '60s' } }, // an address's geocode moves rarely; there are no webhooks
|
|
77
|
+
stateSystem: { perform: performGoogleMapsAction, refresh: syncGoogleMapsFromRemote },
|
|
78
|
+
// the round trip seeds one address's geocode — the twin's own door, because the vendor has no writable
|
|
79
|
+
// surface at all
|
|
80
|
+
roundTrip: { method: 'POST', path: '/twin/geocode?key=round-trip', body: { address: '1600 Amphitheatre Parkway, Mountain View, CA', result: { formatted_address: '1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA', geometry: { location: { lat: 37.4224, lng: -122.0842 } }, place_id: 'ChIJ_round_trip', types: ['street_address'] } } },
|
|
81
|
+
// a geocode stands alone — no subject here names another, so there is nothing for rule 5 to follow
|
|
82
|
+
references: [],
|
|
83
|
+
// The LEGACY endpoints this connector calls (Geocoding, Place Details) authenticate with `key=`
|
|
84
|
+
// in the QUERY STRING. Google's newer surfaces (Places API New, Address Validation) accept
|
|
85
|
+
// `X-Goog-Api-Key` instead — if this pack ever pulls through those, the strategy becomes a header
|
|
86
|
+
// and this line is where that is said (googlemaps-auth.ts documents both).
|
|
87
|
+
auth: { in: 'query', name: 'key' },
|
|
88
|
+
parityOrigin: 'http://twin',
|
|
89
|
+
// shapeParity is NOT held, for a structural reason rather than a divergence: the Geocoding API has no
|
|
90
|
+
// inventory to enumerate — you ask it about an address, and nothing lists what you have asked. A refresh
|
|
91
|
+
// into a fresh root therefore has nothing to ask about, so the gate's comparison has no ground here.
|
|
92
|
+
vendor: 'googlemaps',
|
|
93
|
+
// The SAME object googlemaps-budget.ts declares at module load — one source of truth, so
|
|
94
|
+
// registering the pack and importing the connector arm identical numbers.
|
|
95
|
+
rateBudget: RATE_BUDGET,
|
|
96
|
+
transport: 'rest',
|
|
97
|
+
archetype: 'crud',
|
|
98
|
+
bin: 'world-googlemaps',
|
|
99
|
+
// The subject types the twin SERVES over its own API — the R2 resource-level claim.
|
|
100
|
+
// `place` is deliberately NOT here: it is a connector-side projection that only
|
|
101
|
+
// `pullGoogleMapsPlaces` / `syncGoogleMapsFromReal` fold in from a real account through an
|
|
102
|
+
// injected client, and no route reads it back — Place Details answers from the canned
|
|
103
|
+
// corpus (`findPlaceById` over googlemaps-data.ts's PLACES), never from stored state.
|
|
104
|
+
// `geocode` stays because the twin both writes it (POST /twin/geocode) and serves it
|
|
105
|
+
// (the Geocoding route's stateful override); `audit` because GET /twin/audit reads it.
|
|
106
|
+
resources: ['geocode', 'audit'],
|
|
107
|
+
specSource: 'Google Maps Platform web-service APIs (Geocoding, Distance Matrix, Directions, Places + Places API New, Roads, Time Zone, Elevation, Geolocation, Address Validation, Static Maps, Street View Static) — deterministic canned data in faithful response shapes',
|
|
108
|
+
description: 'Google Maps Platform twin — deterministic, offline replicas of the Maps web-service APIs in vendor-faithful response shapes with the real status semantics + API-key gate.',
|
|
109
|
+
// Adoption + interception, moved off the central maps unchanged (descriptor-first back-migration, adding-a-twin.md §3,
|
|
110
|
+
// 2026-08-31): the official Node client, the `@googlemaps/` scope, the
|
|
111
|
+
// GOOGLEMAPS_* credential stem, and maps.googleapis.com — one of several *.googleapis.com
|
|
112
|
+
// hosts kept as separate vendors rather than one 'google' (see webrisk, gemini).
|
|
113
|
+
adoption: {
|
|
114
|
+
// Google's official Maps Platform Python client (googlemaps/google-maps-services-python).
|
|
115
|
+
pypi: ['googlemaps'],
|
|
116
|
+
sdks: ['@googlemaps/google-maps-services-js'],
|
|
117
|
+
scopes: ['@googlemaps/'],
|
|
118
|
+
envStems: ['GOOGLEMAPS'],
|
|
119
|
+
},
|
|
120
|
+
hosts: [{ host: 'maps.googleapis.com' }],
|
|
121
|
+
browserRouting: { apiPathPrefix: '/maps/api/', loaderHost: 'https://maps.googleapis.com' },
|
|
122
|
+
};
|
|
123
|
+
// registered at import: the kernel learns the pack's state system (protocol 2)
|
|
124
|
+
registerPack(pack);
|