@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.
Files changed (39) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +96 -0
  3. package/dist/src/cli.d.ts +2 -0
  4. package/dist/src/cli.js +23 -0
  5. package/dist/src/googlemaps-auth.d.ts +31 -0
  6. package/dist/src/googlemaps-auth.js +37 -0
  7. package/dist/src/googlemaps-budget.d.ts +61 -0
  8. package/dist/src/googlemaps-budget.js +142 -0
  9. package/dist/src/googlemaps-capabilities.d.ts +3 -0
  10. package/dist/src/googlemaps-capabilities.js +648 -0
  11. package/dist/src/googlemaps-conformance.d.ts +8 -0
  12. package/dist/src/googlemaps-conformance.js +18 -0
  13. package/dist/src/googlemaps-connector.d.ts +94 -0
  14. package/dist/src/googlemaps-connector.js +243 -0
  15. package/dist/src/googlemaps-data.d.ts +87 -0
  16. package/dist/src/googlemaps-data.js +370 -0
  17. package/dist/src/googlemaps-perform-harness.d.ts +5 -0
  18. package/dist/src/googlemaps-perform-harness.js +17 -0
  19. package/dist/src/googlemaps-server.d.ts +14 -0
  20. package/dist/src/googlemaps-server.js +25 -0
  21. package/dist/src/googlemaps-twin.d.ts +2 -0
  22. package/dist/src/googlemaps-twin.js +1116 -0
  23. package/dist/src/googlemaps-types.d.ts +45 -0
  24. package/dist/src/googlemaps-types.js +1 -0
  25. package/dist/src/index.d.ts +11 -0
  26. package/dist/src/index.js +65 -0
  27. package/package.json +52 -0
  28. package/src/cli.ts +22 -0
  29. package/src/googlemaps-auth.ts +52 -0
  30. package/src/googlemaps-budget.ts +168 -0
  31. package/src/googlemaps-capabilities.ts +766 -0
  32. package/src/googlemaps-conformance.ts +24 -0
  33. package/src/googlemaps-connector.ts +250 -0
  34. package/src/googlemaps-data.ts +399 -0
  35. package/src/googlemaps-perform-harness.ts +17 -0
  36. package/src/googlemaps-server.ts +33 -0
  37. package/src/googlemaps-twin.ts +1110 -0
  38. package/src/googlemaps-types.ts +47 -0
  39. 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);