googlemaps-kit 0.5.0 → 0.7.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 (343) hide show
  1. package/README.md +56 -3
  2. package/dist/advanced/parsers.d.ts +1 -1
  3. package/dist/advanced/parsers.d.ts.map +1 -1
  4. package/dist/advanced/parsers.js +1 -1
  5. package/dist/advanced/parsers.js.map +1 -1
  6. package/dist/advanced.d.ts +2 -2
  7. package/dist/advanced.d.ts.map +1 -1
  8. package/dist/advanced.js.map +1 -1
  9. package/dist/books.d.ts +30 -0
  10. package/dist/books.d.ts.map +1 -0
  11. package/dist/books.js +77 -0
  12. package/dist/books.js.map +1 -0
  13. package/dist/cli/run.d.ts.map +1 -1
  14. package/dist/cli/run.js +9 -11
  15. package/dist/cli/run.js.map +1 -1
  16. package/dist/cli/tui/app.d.ts.map +1 -1
  17. package/dist/cli/tui/app.js +7 -7
  18. package/dist/cli/tui/app.js.map +1 -1
  19. package/dist/cli.js +14 -11
  20. package/dist/cli.js.map +1 -1
  21. package/dist/client/gmaps-client.d.ts +7 -29
  22. package/dist/client/gmaps-client.d.ts.map +1 -1
  23. package/dist/client/gmaps-client.js +15 -131
  24. package/dist/client/gmaps-client.js.map +1 -1
  25. package/dist/client/http-client.d.ts +3 -1
  26. package/dist/client/http-client.d.ts.map +1 -1
  27. package/dist/client/http-client.js +14 -3
  28. package/dist/client/http-client.js.map +1 -1
  29. package/dist/client/intent.d.ts +1 -11
  30. package/dist/client/intent.d.ts.map +1 -1
  31. package/dist/client/intent.js +17 -13
  32. package/dist/client/intent.js.map +1 -1
  33. package/dist/client/maps-tools.d.ts +8 -4
  34. package/dist/client/maps-tools.d.ts.map +1 -1
  35. package/dist/client/maps-tools.js +20 -11
  36. package/dist/client/maps-tools.js.map +1 -1
  37. package/dist/client/namespaces.d.ts +51 -19
  38. package/dist/client/namespaces.d.ts.map +1 -1
  39. package/dist/client/namespaces.js +82 -28
  40. package/dist/client/namespaces.js.map +1 -1
  41. package/dist/client/place-workflows.d.ts +7 -0
  42. package/dist/client/place-workflows.d.ts.map +1 -0
  43. package/dist/client/place-workflows.js +113 -0
  44. package/dist/client/place-workflows.js.map +1 -0
  45. package/dist/finance/client.d.ts +19 -0
  46. package/dist/finance/client.d.ts.map +1 -0
  47. package/dist/finance/client.js +75 -0
  48. package/dist/finance/client.js.map +1 -0
  49. package/dist/finance/parsers.d.ts +13 -0
  50. package/dist/finance/parsers.d.ts.map +1 -0
  51. package/dist/finance/parsers.js +146 -0
  52. package/dist/finance/parsers.js.map +1 -0
  53. package/dist/finance/types.d.ts +76 -0
  54. package/dist/finance/types.d.ts.map +1 -0
  55. package/dist/finance/types.js +2 -0
  56. package/dist/finance/types.js.map +1 -0
  57. package/dist/finance.d.ts +5 -0
  58. package/dist/finance.d.ts.map +1 -0
  59. package/dist/finance.js +4 -0
  60. package/dist/finance.js.map +1 -0
  61. package/dist/flights/client.d.ts +9 -0
  62. package/dist/flights/client.d.ts.map +1 -0
  63. package/dist/flights/client.js +14 -0
  64. package/dist/flights/client.js.map +1 -0
  65. package/dist/flights/parsers.d.ts +11 -0
  66. package/dist/flights/parsers.d.ts.map +1 -0
  67. package/dist/flights/parsers.js +64 -0
  68. package/dist/flights/parsers.js.map +1 -0
  69. package/dist/flights/types.d.ts +52 -0
  70. package/dist/flights/types.d.ts.map +1 -0
  71. package/dist/flights/types.js +2 -0
  72. package/dist/flights/types.js.map +1 -0
  73. package/dist/flights.d.ts +5 -0
  74. package/dist/flights.d.ts.map +1 -0
  75. package/dist/flights.js +4 -0
  76. package/dist/flights.js.map +1 -0
  77. package/dist/gemini-web/client.d.ts +16 -0
  78. package/dist/gemini-web/client.d.ts.map +1 -0
  79. package/dist/gemini-web/client.js +110 -0
  80. package/dist/gemini-web/client.js.map +1 -0
  81. package/dist/gemini-web/parsers.d.ts +5 -0
  82. package/dist/gemini-web/parsers.d.ts.map +1 -0
  83. package/dist/gemini-web/parsers.js +62 -0
  84. package/dist/gemini-web/parsers.js.map +1 -0
  85. package/dist/gemini-web/types.d.ts +47 -0
  86. package/dist/gemini-web/types.d.ts.map +1 -0
  87. package/dist/gemini-web/types.js +2 -0
  88. package/dist/gemini-web/types.js.map +1 -0
  89. package/dist/gemini-web.d.ts +5 -0
  90. package/dist/gemini-web.d.ts.map +1 -0
  91. package/dist/gemini-web.js +4 -0
  92. package/dist/gemini-web.js.map +1 -0
  93. package/dist/google-search/client.d.ts +16 -0
  94. package/dist/google-search/client.d.ts.map +1 -0
  95. package/dist/google-search/client.js +117 -0
  96. package/dist/google-search/client.js.map +1 -0
  97. package/dist/google-search/errors.d.ts +8 -0
  98. package/dist/google-search/errors.d.ts.map +1 -0
  99. package/dist/google-search/errors.js +13 -0
  100. package/dist/google-search/errors.js.map +1 -0
  101. package/dist/google-search/html.d.ts +12 -0
  102. package/dist/google-search/html.d.ts.map +1 -0
  103. package/dist/google-search/html.js +135 -0
  104. package/dist/google-search/html.js.map +1 -0
  105. package/dist/google-search/parsers.d.ts +6 -0
  106. package/dist/google-search/parsers.d.ts.map +1 -0
  107. package/dist/google-search/parsers.js +177 -0
  108. package/dist/google-search/parsers.js.map +1 -0
  109. package/dist/google-search/types.d.ts +66 -0
  110. package/dist/google-search/types.d.ts.map +1 -0
  111. package/dist/google-search/types.js +2 -0
  112. package/dist/google-search/types.js.map +1 -0
  113. package/dist/google-search.d.ts +6 -0
  114. package/dist/google-search.d.ts.map +1 -0
  115. package/dist/google-search.js +4 -0
  116. package/dist/google-search.js.map +1 -0
  117. package/dist/hotels/client.d.ts +9 -0
  118. package/dist/hotels/client.d.ts.map +1 -0
  119. package/dist/hotels/client.js +14 -0
  120. package/dist/hotels/client.js.map +1 -0
  121. package/dist/hotels/parsers.d.ts +7 -0
  122. package/dist/hotels/parsers.d.ts.map +1 -0
  123. package/dist/hotels/parsers.js +74 -0
  124. package/dist/hotels/parsers.js.map +1 -0
  125. package/dist/hotels/types.d.ts +55 -0
  126. package/dist/hotels/types.d.ts.map +1 -0
  127. package/dist/hotels/types.js +2 -0
  128. package/dist/hotels/types.js.map +1 -0
  129. package/dist/hotels.d.ts +4 -0
  130. package/dist/hotels.d.ts.map +1 -0
  131. package/dist/hotels.js +3 -0
  132. package/dist/hotels.js.map +1 -0
  133. package/dist/index.d.ts +9 -5
  134. package/dist/index.d.ts.map +1 -1
  135. package/dist/index.js +3 -1
  136. package/dist/index.js.map +1 -1
  137. package/dist/known-surfaces.d.ts +35 -5
  138. package/dist/known-surfaces.d.ts.map +1 -1
  139. package/dist/known-surfaces.js +35 -5
  140. package/dist/known-surfaces.js.map +1 -1
  141. package/dist/lens/client.d.ts +14 -0
  142. package/dist/lens/client.d.ts.map +1 -0
  143. package/dist/lens/client.js +116 -0
  144. package/dist/lens/client.js.map +1 -0
  145. package/dist/lens/errors.d.ts +8 -0
  146. package/dist/lens/errors.d.ts.map +1 -0
  147. package/dist/lens/errors.js +13 -0
  148. package/dist/lens/errors.js.map +1 -0
  149. package/dist/lens/types.d.ts +27 -0
  150. package/dist/lens/types.d.ts.map +1 -0
  151. package/dist/lens/types.js +2 -0
  152. package/dist/lens/types.js.map +1 -0
  153. package/dist/lens.d.ts +8 -0
  154. package/dist/lens.d.ts.map +1 -0
  155. package/dist/lens.js +5 -0
  156. package/dist/lens.js.map +1 -0
  157. package/dist/news.d.ts +46 -0
  158. package/dist/news.d.ts.map +1 -0
  159. package/dist/news.js +202 -0
  160. package/dist/news.js.map +1 -0
  161. package/dist/pagespeed/client.d.ts +28 -0
  162. package/dist/pagespeed/client.d.ts.map +1 -0
  163. package/dist/pagespeed/client.js +222 -0
  164. package/dist/pagespeed/client.js.map +1 -0
  165. package/dist/pagespeed/errors.d.ts +9 -0
  166. package/dist/pagespeed/errors.d.ts.map +1 -0
  167. package/dist/pagespeed/errors.js +15 -0
  168. package/dist/pagespeed/errors.js.map +1 -0
  169. package/dist/pagespeed/parsers.d.ts +7 -0
  170. package/dist/pagespeed/parsers.d.ts.map +1 -0
  171. package/dist/pagespeed/parsers.js +236 -0
  172. package/dist/pagespeed/parsers.js.map +1 -0
  173. package/dist/pagespeed/types.d.ts +156 -0
  174. package/dist/pagespeed/types.d.ts.map +1 -0
  175. package/dist/pagespeed/types.js +2 -0
  176. package/dist/pagespeed/types.js.map +1 -0
  177. package/dist/pagespeed/wire.d.ts +10 -0
  178. package/dist/pagespeed/wire.d.ts.map +1 -0
  179. package/dist/pagespeed/wire.js +96 -0
  180. package/dist/pagespeed/wire.js.map +1 -0
  181. package/dist/pagespeed.d.ts +6 -0
  182. package/dist/pagespeed.d.ts.map +1 -0
  183. package/dist/pagespeed.js +4 -0
  184. package/dist/pagespeed.js.map +1 -0
  185. package/dist/parsers/geocode.d.ts.map +1 -1
  186. package/dist/parsers/geocode.js +30 -1
  187. package/dist/parsers/geocode.js.map +1 -1
  188. package/dist/parsers/reviews.d.ts +8 -1
  189. package/dist/parsers/reviews.d.ts.map +1 -1
  190. package/dist/parsers/reviews.js +46 -9
  191. package/dist/parsers/reviews.js.map +1 -1
  192. package/dist/platform/catalog.d.ts +18 -0
  193. package/dist/platform/catalog.d.ts.map +1 -0
  194. package/dist/platform/catalog.js +320 -0
  195. package/dist/platform/catalog.js.map +1 -0
  196. package/dist/platform/parity.d.ts +12 -0
  197. package/dist/platform/parity.d.ts.map +1 -0
  198. package/dist/platform/parity.js +25 -0
  199. package/dist/platform/parity.js.map +1 -0
  200. package/dist/services/elevation.d.ts +6 -4
  201. package/dist/services/elevation.d.ts.map +1 -1
  202. package/dist/services/elevation.js +39 -4
  203. package/dist/services/elevation.js.map +1 -1
  204. package/dist/services/environment/air-quality.d.ts +39 -0
  205. package/dist/services/environment/air-quality.d.ts.map +1 -0
  206. package/dist/services/environment/air-quality.js +82 -0
  207. package/dist/services/environment/air-quality.js.map +1 -0
  208. package/dist/services/environment/weather.d.ts +42 -0
  209. package/dist/services/environment/weather.d.ts.map +1 -0
  210. package/dist/services/environment/weather.js +63 -0
  211. package/dist/services/environment/weather.js.map +1 -0
  212. package/dist/services/geocode.d.ts +5 -1
  213. package/dist/services/geocode.d.ts.map +1 -1
  214. package/dist/services/geocode.js +13 -0
  215. package/dist/services/geocode.js.map +1 -1
  216. package/dist/services/keyed.d.ts +80 -0
  217. package/dist/services/keyed.d.ts.map +1 -0
  218. package/dist/services/keyed.js +152 -0
  219. package/dist/services/keyed.js.map +1 -0
  220. package/dist/services/knowledge.d.ts +6 -2
  221. package/dist/services/knowledge.d.ts.map +1 -1
  222. package/dist/services/knowledge.js +30 -5
  223. package/dist/services/knowledge.js.map +1 -1
  224. package/dist/services/mobility.d.ts.map +1 -1
  225. package/dist/services/mobility.js +13 -2
  226. package/dist/services/mobility.js.map +1 -1
  227. package/dist/services/nearby-search.d.ts +32 -0
  228. package/dist/services/nearby-search.d.ts.map +1 -0
  229. package/dist/services/nearby-search.js +85 -0
  230. package/dist/services/nearby-search.js.map +1 -0
  231. package/dist/services/panorama.d.ts +8 -1
  232. package/dist/services/panorama.d.ts.map +1 -1
  233. package/dist/services/panorama.js +48 -0
  234. package/dist/services/panorama.js.map +1 -1
  235. package/dist/services/photos.d.ts.map +1 -1
  236. package/dist/services/photos.js +9 -2
  237. package/dist/services/photos.js.map +1 -1
  238. package/dist/services/places.d.ts.map +1 -1
  239. package/dist/services/places.js +1 -0
  240. package/dist/services/places.js.map +1 -1
  241. package/dist/services/reviews.d.ts.map +1 -1
  242. package/dist/services/reviews.js +4 -1
  243. package/dist/services/reviews.js.map +1 -1
  244. package/dist/services/search.d.ts +8 -3
  245. package/dist/services/search.d.ts.map +1 -1
  246. package/dist/services/search.js +28 -9
  247. package/dist/services/search.js.map +1 -1
  248. package/dist/translate.d.ts +75 -0
  249. package/dist/translate.d.ts.map +1 -0
  250. package/dist/translate.js +126 -0
  251. package/dist/translate.js.map +1 -0
  252. package/dist/travel-google/common.d.ts +24 -0
  253. package/dist/travel-google/common.d.ts.map +1 -0
  254. package/dist/travel-google/common.js +72 -0
  255. package/dist/travel-google/common.js.map +1 -0
  256. package/dist/trends/client.d.ts +17 -0
  257. package/dist/trends/client.d.ts.map +1 -0
  258. package/dist/trends/client.js +86 -0
  259. package/dist/trends/client.js.map +1 -0
  260. package/dist/trends/errors.d.ts +8 -0
  261. package/dist/trends/errors.d.ts.map +1 -0
  262. package/dist/trends/errors.js +13 -0
  263. package/dist/trends/errors.js.map +1 -0
  264. package/dist/trends/links.d.ts +8 -0
  265. package/dist/trends/links.d.ts.map +1 -0
  266. package/dist/trends/links.js +71 -0
  267. package/dist/trends/links.js.map +1 -0
  268. package/dist/trends/parsers.d.ts +5 -0
  269. package/dist/trends/parsers.d.ts.map +1 -0
  270. package/dist/trends/parsers.js +126 -0
  271. package/dist/trends/parsers.js.map +1 -0
  272. package/dist/trends/types.d.ts +71 -0
  273. package/dist/trends/types.d.ts.map +1 -0
  274. package/dist/trends/types.js +2 -0
  275. package/dist/trends/types.js.map +1 -0
  276. package/dist/trends.d.ts +9 -0
  277. package/dist/trends.d.ts.map +1 -0
  278. package/dist/trends.js +8 -0
  279. package/dist/trends.js.map +1 -0
  280. package/dist/types/common.d.ts +28 -2
  281. package/dist/types/common.d.ts.map +1 -1
  282. package/dist/types/common.js.map +1 -1
  283. package/dist/types/directions.d.ts +1 -1
  284. package/dist/types/directions.d.ts.map +1 -1
  285. package/dist/types/dx.d.ts +23 -10
  286. package/dist/types/dx.d.ts.map +1 -1
  287. package/dist/types/panorama.d.ts +19 -0
  288. package/dist/types/panorama.d.ts.map +1 -1
  289. package/dist/types/reviews.d.ts +3 -4
  290. package/dist/types/reviews.d.ts.map +1 -1
  291. package/dist/types/suggest.d.ts +4 -6
  292. package/dist/types/suggest.d.ts.map +1 -1
  293. package/dist/utils/google-web.d.ts +24 -0
  294. package/dist/utils/google-web.d.ts.map +1 -0
  295. package/dist/utils/google-web.js +150 -0
  296. package/dist/utils/google-web.js.map +1 -0
  297. package/dist/utils/place-ref.d.ts +14 -4
  298. package/dist/utils/place-ref.d.ts.map +1 -1
  299. package/dist/utils/place-ref.js +49 -1
  300. package/dist/utils/place-ref.js.map +1 -1
  301. package/dist/youtube/client.d.ts +19 -0
  302. package/dist/youtube/client.d.ts.map +1 -0
  303. package/dist/youtube/client.js +115 -0
  304. package/dist/youtube/client.js.map +1 -0
  305. package/dist/youtube/errors.d.ts +8 -0
  306. package/dist/youtube/errors.d.ts.map +1 -0
  307. package/dist/youtube/errors.js +13 -0
  308. package/dist/youtube/errors.js.map +1 -0
  309. package/dist/youtube/parsers.d.ts +9 -0
  310. package/dist/youtube/parsers.d.ts.map +1 -0
  311. package/dist/youtube/parsers.js +213 -0
  312. package/dist/youtube/parsers.js.map +1 -0
  313. package/dist/youtube/types.d.ts +90 -0
  314. package/dist/youtube/types.d.ts.map +1 -0
  315. package/dist/youtube/types.js +2 -0
  316. package/dist/youtube/types.js.map +1 -0
  317. package/dist/youtube.d.ts +9 -0
  318. package/dist/youtube.d.ts.map +1 -0
  319. package/dist/youtube.js +6 -0
  320. package/dist/youtube.js.map +1 -0
  321. package/docs/books.md +18 -0
  322. package/docs/environment-research.md +65 -0
  323. package/docs/finance-research.md +153 -0
  324. package/docs/finance.md +43 -0
  325. package/docs/gemini-web.md +36 -0
  326. package/docs/google-ai-books-research.md +53 -0
  327. package/docs/google-media-research.md +105 -0
  328. package/docs/google-search-research.md +36 -0
  329. package/docs/google-search.md +53 -0
  330. package/docs/google-services-research.md +135 -0
  331. package/docs/google-travel-research.md +86 -0
  332. package/docs/internal/reverse-engineering.md +85 -0
  333. package/docs/lens.md +54 -0
  334. package/docs/maps-revalidation.md +31 -0
  335. package/docs/news.md +35 -0
  336. package/docs/pagespeed-research.md +153 -0
  337. package/docs/pagespeed.md +135 -0
  338. package/docs/reviews-research.md +33 -0
  339. package/docs/translate.md +78 -0
  340. package/docs/trends-research.md +82 -0
  341. package/docs/trends.md +75 -0
  342. package/docs/youtube.md +72 -0
  343. package/package.json +77 -2
@@ -0,0 +1,213 @@
1
+ import { YouTubeError } from './errors.js';
2
+ export function youtubeObject(value) {
3
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
4
+ }
5
+ function fail(label) { throw new YouTubeError(`Malformed YouTube ${label}`, 'parse'); }
6
+ function optionalString(value) { return typeof value === 'string' ? value : undefined; }
7
+ function requiredString(value, name) { return typeof value === 'string' && value.length > 0 ? value : fail(name); }
8
+ function numeric(value) {
9
+ const result = typeof value === 'string' && /^\d+$/.test(value) ? Number(value) : value;
10
+ return typeof result === 'number' && Number.isFinite(result) && result >= 0 ? result : undefined;
11
+ }
12
+ export function youtubeText(value) {
13
+ if (!youtubeObject(value))
14
+ return undefined;
15
+ if (typeof value.simpleText === 'string')
16
+ return value.simpleText;
17
+ if (Array.isArray(value.runs))
18
+ return value.runs.map(run => youtubeObject(run) && typeof run.text === 'string' ? run.text : '').join('');
19
+ if (typeof value.content === 'string')
20
+ return value.content;
21
+ return undefined;
22
+ }
23
+ function thumbnails(value) {
24
+ if (!youtubeObject(value) || !Array.isArray(value.thumbnails))
25
+ return [];
26
+ return value.thumbnails.flatMap(item => youtubeObject(item) && typeof item.url === 'string' ? [{ url: item.url.startsWith('//') ? `https:${item.url}` : item.url, width: numeric(item.width), height: numeric(item.height) }] : []);
27
+ }
28
+ export function extractYouTubeJson(html, variable) {
29
+ const escaped = variable.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
30
+ const pattern = new RegExp(`(?:var\\s+)?${escaped}\\s*=\\s*|window\\[["']${escaped}["']\\]\\s*=\\s*`, 'g');
31
+ let match;
32
+ while ((match = pattern.exec(html))) {
33
+ const start = pattern.lastIndex;
34
+ if (html[start] !== '{')
35
+ continue;
36
+ let depth = 0, quoted = false, escapedCharacter = false;
37
+ for (let index = start; index < html.length; index++) {
38
+ const character = html[index];
39
+ if (quoted) {
40
+ if (escapedCharacter)
41
+ escapedCharacter = false;
42
+ else if (character === '\\')
43
+ escapedCharacter = true;
44
+ else if (character === '"')
45
+ quoted = false;
46
+ }
47
+ else if (character === '"')
48
+ quoted = true;
49
+ else if (character === '{')
50
+ depth++;
51
+ else if (character === '}' && --depth === 0) {
52
+ try {
53
+ const value = JSON.parse(html.slice(start, index + 1));
54
+ return youtubeObject(value) ? value : fail(variable);
55
+ }
56
+ catch (cause) {
57
+ throw new YouTubeError(`Malformed YouTube ${variable} JSON`, 'parse', undefined, undefined, { cause });
58
+ }
59
+ }
60
+ }
61
+ return fail(variable);
62
+ }
63
+ return undefined;
64
+ }
65
+ export function parseVideo(raw, id, initialData) {
66
+ if (!youtubeObject(raw) || !youtubeObject(raw.playabilityStatus))
67
+ return fail('player response');
68
+ const playability = raw.playabilityStatus;
69
+ const details = youtubeObject(raw.videoDetails) ? raw.videoDetails : {};
70
+ if (details.videoId !== undefined && details.videoId !== id)
71
+ return fail('player video ID');
72
+ const captionContainer = youtubeObject(raw.captions) && youtubeObject(raw.captions.playerCaptionsTracklistRenderer) ? raw.captions.playerCaptionsTracklistRenderer : undefined;
73
+ const captions = !Array.isArray(captionContainer?.captionTracks) ? [] : captionContainer.captionTracks.map(value => {
74
+ if (!youtubeObject(value))
75
+ return fail('caption track');
76
+ return { languageCode: requiredString(value.languageCode, 'caption language'), name: youtubeText(value.name) ?? '', baseUrl: requiredString(value.baseUrl, 'caption URL'), kind: optionalString(value.kind), isTranslatable: typeof value.isTranslatable === 'boolean' ? value.isTranslatable : undefined, raw: value };
77
+ });
78
+ return {
79
+ id: optionalString(details.videoId) ?? id,
80
+ url: `https://www.youtube.com/watch?v=${id}`,
81
+ title: optionalString(details.title), author: optionalString(details.author), channelId: optionalString(details.channelId),
82
+ description: optionalString(details.shortDescription), lengthSeconds: numeric(details.lengthSeconds), viewCount: optionalString(details.viewCount),
83
+ keywords: Array.isArray(details.keywords) ? details.keywords.filter((value) => typeof value === 'string') : undefined,
84
+ isLiveContent: typeof details.isLiveContent === 'boolean' ? details.isLiveContent : undefined,
85
+ thumbnails: thumbnails(details.thumbnail),
86
+ playability: { status: requiredString(playability.status, 'playability status'), reason: optionalString(playability.reason), raw: playability },
87
+ captions, raw, initialData,
88
+ };
89
+ }
90
+ function ownerId(value) {
91
+ if (!youtubeObject(value) || !Array.isArray(value.runs))
92
+ return undefined;
93
+ for (const run of value.runs) {
94
+ if (youtubeObject(run) && youtubeObject(run.navigationEndpoint) && youtubeObject(run.navigationEndpoint.browseEndpoint))
95
+ return optionalString(run.navigationEndpoint.browseEndpoint.browseId);
96
+ }
97
+ return undefined;
98
+ }
99
+ function searchItem(type, raw) {
100
+ const id = requiredString(raw[type === 'video' ? 'videoId' : 'channelId'], 'search result ID');
101
+ const title = youtubeText(raw.title) ?? fail('search result title');
102
+ const owner = raw.ownerText ?? raw.longBylineText ?? raw.shortBylineText;
103
+ return {
104
+ type, id, title,
105
+ url: type === 'video' ? `https://www.youtube.com/watch?v=${id}` : `https://www.youtube.com/channel/${id}`,
106
+ description: youtubeText(raw.descriptionSnippet), author: youtubeText(owner), channelId: type === 'channel' ? id : ownerId(owner),
107
+ duration: youtubeText(raw.lengthText), viewCount: youtubeText(raw.viewCountText), publishedTime: youtubeText(raw.publishedTimeText),
108
+ thumbnails: thumbnails(raw.thumbnail ?? (Array.isArray(raw.thumbnails) ? raw.thumbnails[0] : undefined)), raw,
109
+ };
110
+ }
111
+ function path(value, ...keys) {
112
+ for (const key of keys)
113
+ value = typeof key === 'number' && Array.isArray(value) ? value[key] : typeof key === 'string' && youtubeObject(value) ? value[key] : undefined;
114
+ return value;
115
+ }
116
+ function playlistLockup(raw) {
117
+ const id = requiredString(raw.contentId, 'playlist ID');
118
+ const metadata = path(raw, 'metadata', 'lockupMetadataViewModel');
119
+ const rows = path(metadata, 'metadata', 'contentMetadataViewModel', 'metadataRows');
120
+ const byline = Array.isArray(rows) ? rows.find(row => path(row, 'lockupContentMetadataRowExtension', 'contentType') === 'METADATA_ROW_CONTENT_TYPE_BYLINE') : undefined;
121
+ const author = path(byline, 'metadataParts', 0, 'text');
122
+ return {
123
+ type: 'playlist', id,
124
+ title: requiredString(youtubeText(path(metadata, 'title')), 'playlist title'),
125
+ url: `https://www.youtube.com/playlist?list=${id}`,
126
+ author: youtubeText(author),
127
+ channelId: optionalString(path(author, 'commandRuns', 0, 'onTap', 'innertubeCommand', 'browseEndpoint', 'browseId')),
128
+ thumbnails: thumbnails({ thumbnails: path(raw, 'contentImage', 'collectionThumbnailViewModel', 'primaryThumbnail', 'thumbnailViewModel', 'image', 'sources') }),
129
+ raw,
130
+ };
131
+ }
132
+ export function parseSearch(raw, client) {
133
+ if (!youtubeObject(raw))
134
+ return fail('search response');
135
+ const primary = youtubeObject(raw.contents) && youtubeObject(raw.contents.twoColumnSearchResultsRenderer) ? raw.contents.twoColumnSearchResultsRenderer.primaryContents : undefined;
136
+ const actions = raw.onResponseReceivedCommands ?? raw.onResponseReceivedActions;
137
+ if (!youtubeObject(primary) && !Array.isArray(actions))
138
+ return fail('search results');
139
+ const items = [];
140
+ const seen = new Set();
141
+ let token;
142
+ const stack = [primary ?? actions];
143
+ while (stack.length) {
144
+ const value = stack.pop();
145
+ if (Array.isArray(value)) {
146
+ for (let i = value.length - 1; i >= 0; i--)
147
+ stack.push(value[i]);
148
+ continue;
149
+ }
150
+ if (!youtubeObject(value))
151
+ continue;
152
+ if (youtubeObject(value.continuationCommand) && typeof value.continuationCommand.token === 'string')
153
+ token ??= value.continuationCommand.token;
154
+ if (youtubeObject(value.lockupViewModel) && value.lockupViewModel.contentType === 'LOCKUP_CONTENT_TYPE_PLAYLIST') {
155
+ const item = playlistLockup(value.lockupViewModel);
156
+ if (!seen.has(`playlist:${item.id}`)) {
157
+ items.push(item);
158
+ seen.add(`playlist:${item.id}`);
159
+ }
160
+ continue;
161
+ }
162
+ const entry = ['video', 'channel'].find(type => youtubeObject(value[`${type}Renderer`]));
163
+ if (entry) {
164
+ const item = searchItem(entry, value[`${entry}Renderer`]);
165
+ const key = `${entry}:${item.id}`;
166
+ if (!seen.has(key)) {
167
+ items.push(item);
168
+ seen.add(key);
169
+ }
170
+ continue;
171
+ }
172
+ for (const [key, child] of Object.entries(value).reverse()) {
173
+ if (!/adSlotRenderer|promotedSparklesWebRenderer|searchPyvRenderer|adMetadata|loggingDirectives|trackingParams/.test(key))
174
+ stack.push(child);
175
+ }
176
+ }
177
+ return { items, estimatedResults: optionalString(raw.estimatedResults), continuation: token ? { token, client } : undefined, raw };
178
+ }
179
+ export function extractYouTubeClient(html) {
180
+ const pattern = /ytcfg\.set\s*\(/g;
181
+ let match;
182
+ while ((match = pattern.exec(html))) {
183
+ const config = extractYouTubeJson(`config=${html.slice(pattern.lastIndex).trimStart()}`, 'config');
184
+ if (!config || !youtubeObject(config.INNERTUBE_CONTEXT) || !youtubeObject(config.INNERTUBE_CONTEXT.client))
185
+ continue;
186
+ const client = config.INNERTUBE_CONTEXT.client;
187
+ if (client.clientName !== 'WEB')
188
+ return fail('unsupported anonymous client');
189
+ return { clientName: 'WEB', clientVersion: requiredString(client.clientVersion, 'client version'), hl: optionalString(client.hl), gl: optionalString(client.gl), visitorData: optionalString(client.visitorData) };
190
+ }
191
+ return fail('anonymous client configuration');
192
+ }
193
+ export function parseYouTubeVideoId(value) {
194
+ if (typeof value !== 'string')
195
+ throw new TypeError('A YouTube video ID or URL is required');
196
+ if (/^[A-Za-z0-9_-]{11}$/.test(value))
197
+ return value;
198
+ let url;
199
+ try {
200
+ url = new URL(value);
201
+ }
202
+ catch {
203
+ throw new TypeError('Invalid YouTube video ID or URL');
204
+ }
205
+ if (!['https:', 'http:'].includes(url.protocol) || url.username || url.password || url.port)
206
+ throw new TypeError('Invalid YouTube video URL');
207
+ const host = url.hostname.toLowerCase();
208
+ const id = host === 'youtu.be' ? url.pathname.slice(1) : ['youtube.com', 'www.youtube.com', 'm.youtube.com', 'www.youtube-nocookie.com'].includes(host) ? url.pathname === '/watch' ? url.searchParams.get('v') : /^\/(?:shorts|embed|live)\/([A-Za-z0-9_-]{11})\/?$/.exec(url.pathname)?.[1] : undefined;
209
+ if (typeof id !== 'string' || !/^[A-Za-z0-9_-]{11}$/.test(id))
210
+ throw new TypeError('Invalid YouTube video URL');
211
+ return id;
212
+ }
213
+ //# sourceMappingURL=parsers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parsers.js","sourceRoot":"","sources":["../../src/youtube/parsers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ export interface YouTubeConfig {
2
+ fetch?: typeof globalThis.fetch;
3
+ locale?: string;
4
+ region?: string;
5
+ timeoutMs?: number;
6
+ }
7
+ export interface YouTubeRequestOptions {
8
+ signal?: AbortSignal;
9
+ }
10
+ export interface YouTubeThumbnail {
11
+ url: string;
12
+ width?: number;
13
+ height?: number;
14
+ }
15
+ export interface YouTubeCaptionTrack {
16
+ languageCode: string;
17
+ name: string;
18
+ baseUrl: string;
19
+ kind?: string;
20
+ isTranslatable?: boolean;
21
+ raw: Record<string, unknown>;
22
+ }
23
+ export interface YouTubeVideo {
24
+ id: string;
25
+ url: string;
26
+ title?: string;
27
+ author?: string;
28
+ channelId?: string;
29
+ description?: string;
30
+ lengthSeconds?: number;
31
+ viewCount?: string;
32
+ keywords?: string[];
33
+ isLiveContent?: boolean;
34
+ thumbnails: YouTubeThumbnail[];
35
+ playability: {
36
+ status: string;
37
+ reason?: string;
38
+ raw: Record<string, unknown>;
39
+ };
40
+ captions: YouTubeCaptionTrack[];
41
+ raw: Record<string, unknown>;
42
+ initialData?: Record<string, unknown>;
43
+ }
44
+ export interface YouTubeSearchItem {
45
+ type: 'video' | 'channel' | 'playlist';
46
+ id: string;
47
+ title: string;
48
+ url: string;
49
+ description?: string;
50
+ author?: string;
51
+ channelId?: string;
52
+ duration?: string;
53
+ viewCount?: string;
54
+ publishedTime?: string;
55
+ thumbnails: YouTubeThumbnail[];
56
+ raw: Record<string, unknown>;
57
+ }
58
+ export interface YouTubeSearchCursor {
59
+ token: string;
60
+ client: {
61
+ clientName: 'WEB';
62
+ clientVersion: string;
63
+ hl?: string;
64
+ gl?: string;
65
+ visitorData?: string;
66
+ };
67
+ }
68
+ export interface YouTubeSearchPage {
69
+ items: YouTubeSearchItem[];
70
+ estimatedResults?: string;
71
+ continuation?: YouTubeSearchCursor;
72
+ raw: Record<string, unknown>;
73
+ }
74
+ export interface YouTubeOEmbed {
75
+ title: string;
76
+ author_name: string;
77
+ author_url: string;
78
+ type: string;
79
+ height: number;
80
+ width: number;
81
+ version: string;
82
+ provider_name: string;
83
+ provider_url: string;
84
+ thumbnail_height: number;
85
+ thumbnail_width: number;
86
+ thumbnail_url: string;
87
+ html: string;
88
+ [key: string]: unknown;
89
+ }
90
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/youtube/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/youtube/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,9 @@
1
+ export { YouTubeClient } from './youtube/client.js';
2
+ export { YouTubeError } from './youtube/errors.js';
3
+ export type { YouTubeErrorKind } from './youtube/errors.js';
4
+ export { parseYouTubeVideoId } from './youtube/parsers.js';
5
+ export type * from './youtube/types.js';
6
+ import { YouTubeClient } from './youtube/client.js';
7
+ import type { YouTubeConfig } from './youtube/types.js';
8
+ export declare function youtube(config?: YouTubeConfig): YouTubeClient;
9
+ //# sourceMappingURL=youtube.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"youtube.d.ts","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC3D,mBAAmB,oBAAoB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,wBAAgB,OAAO,CAAC,MAAM,GAAE,aAAkB,GAAG,aAAa,CAAsC"}
@@ -0,0 +1,6 @@
1
+ export { YouTubeClient } from './youtube/client.js';
2
+ export { YouTubeError } from './youtube/errors.js';
3
+ export { parseYouTubeVideoId } from './youtube/parsers.js';
4
+ import { YouTubeClient } from './youtube/client.js';
5
+ export function youtube(config = {}) { return new YouTubeClient(config); }
6
+ //# sourceMappingURL=youtube.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"youtube.js","sourceRoot":"","sources":["../src/youtube.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAE3D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,MAAM,UAAU,OAAO,CAAC,SAAwB,EAAE,IAAmB,OAAO,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC"}
package/docs/books.md ADDED
@@ -0,0 +1,18 @@
1
+ # Google Books public metadata
2
+
3
+ ```ts
4
+ import { googleBooks } from 'googlemaps-kit/books';
5
+
6
+ const book = await googleBooks().get('zyTCAlFPjgYC');
7
+ console.log(book.title, book.authors, book.identifiers, book.pageCount);
8
+ ```
9
+
10
+ This client reads an observed public bibliographic page at `books.google.com/books?id=...&hl=en`. It returns the title, bibliographic title, authors, publisher/year, edition, ISBNs, page count, optional description, canonical link and original table values. Fields missing from the page remain undefined or empty. It does not retrieve book pages, full text, purchased content, account libraries or previews.
11
+
12
+ The web metadata request succeeded anonymously on October 29, 2026. The documented Books v1 search and volume endpoints returned HTTP 429 quota errors from the same environment. This module uses the verified web surface; it is not a wrapper presented as successful v1 API access. Search by query, browsing bookshelves, v1 API operations and broad pagination are outside the current implementation.
13
+
14
+ `googleBooks({ fetch?, timeoutMs? })` accepts an injected fetch and defaults to a 30-second request deadline including the response body. `get(id, { signal? })` accepts a Google volume ID, requests the English page, and makes no automatic retries. Unknown layouts, mismatched volume IDs and HTTP failures throw `GoogleWebError` rather than returning empty fabricated metadata. Regional redirects are handled by normal fetch behavior; bibliographic parsing is verified only for the captured page structure.
15
+
16
+ `parseGoogleBooksHtml(html, id)` exposes the same parser for saved HTML. It never executes scripts. Sanitized actual fixture provenance is in `tests/fixtures/books/README.md`.
17
+
18
+ See the [independent research ledger](./google-ai-books-research.md) for observed behavior and unresolved gaps.
@@ -0,0 +1,65 @@
1
+ # Weather, Air Quality and Cloud Vision access boundaries
2
+
3
+ Audited on 2026-10-29. These products have supported Google APIs with project
4
+ identity and billing/quota rules. A public consumer widget is a different
5
+ contract from those APIs.
6
+
7
+ ## Direct API observations
8
+
9
+ Requests deliberately supplied no API key, OAuth token or account cookies:
10
+
11
+ | API | Request | Observed result |
12
+ | --- | --- | --- |
13
+ | Weather current conditions | `GET weather.googleapis.com/v1/currentConditions:lookup` with location | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
14
+ | Air Quality current conditions | `POST airquality.googleapis.com/v1/currentConditions:lookup` with JSON location | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
15
+ | Vision text detection | `POST vision.googleapis.com/v1/images:annotate` with Google's public logo URL | HTTP 403, `PERMISSION_DENIED`, consumer identity required |
16
+
17
+ These failures establish that the tested official routes do not accept
18
+ unregistered callers. They do not establish successful access to the protected
19
+ data. No project credential was borrowed or extracted and no supported API's
20
+ paid feature is claimed anonymously available.
21
+
22
+ ## Existing consumer capabilities
23
+
24
+ `maps.environment.weather.getCurrentConditions` parses the weather chip from a
25
+ Maps viewport response. It requires a current in-page viewport `psi` supplied
26
+ by the caller or a `psiProvider`. It does not produce a full forecast. A bare
27
+ degree symbol has no established Celsius/Fahrenheit meaning, so the parser now
28
+ preserves the value/display while leaving `unit` unset unless C or F is explicit.
29
+
30
+ A fresh ordinary Maps viewport capture for HSR Layout on 2026-10-29 returned
31
+ the expected cache-metadata stub followed by two populated responses. The
32
+ existing parser extracted `HSR Layout`, `28°`, and `Sunny`. This revalidates the
33
+ bounded current-condition chip contract, not a forecast or numerical AQI API.
34
+
35
+ `maps.environment.airQuality.getHeatmapTile` reads the existing raster overlay
36
+ surface. A tile is not a numerical point AQI lookup, and a returned placeholder
37
+ does not prove meaningful overlay coverage. The existing batchexecute parser
38
+ remains a separate partially established, session-dependent interface.
39
+
40
+ ## Corrected supported-API contracts
41
+
42
+ The audit identified two existing request bugs and added offline regressions:
43
+
44
+ - Air Quality `lookup` now sends Google's documented JSON POST location instead
45
+ of GET query parameters. It accepts only a caller-configured API key.
46
+ - Weather `lookupForecast` now calls `forecast/days:lookup`, returning actual
47
+ daily records rather than calling current conditions. It accepts `days` and
48
+ `pageSize` from 1 to 10 and an optional `pageToken`, preserving Google's
49
+ pagination response. It still requires the caller's API credential.
50
+
51
+ The shared Maps HTTP client now has `postJson`, which preserves scheduling,
52
+ authentication options, error handling and statistics while parsing ordinary
53
+ JSON objects. Automatic retries are disabled by default for JSON POSTs.
54
+ These request fixes were tested offline; a successful authenticated/billable
55
+ Weather/Air Quality response was not claimed or attempted in this pass.
56
+
57
+ References: [Weather daily forecast](https://developers.google.com/maps/documentation/weather/reference/rest/v1/forecast.days/lookup),
58
+ [Weather setup](https://developers.google.com/maps/documentation/weather/get-api-key),
59
+ [Air Quality current conditions](https://developers.google.com/maps/documentation/air-quality/reference/rest/v1/currentConditions/lookup),
60
+ [Air Quality authentication](https://developers.google.com/maps/documentation/air-quality/get-api-key),
61
+ [Vision pricing](https://cloud.google.com/vision/pricing).
62
+
63
+ Consumer Lens is investigated separately from Cloud Vision. Similar OCR or
64
+ visual-search capabilities do not establish identical output, licensed data,
65
+ throughput, model selection or paid API parity.
@@ -0,0 +1,153 @@
1
+ # Google Finance consumer client
2
+
3
+ Investigated and verified on **2026-10-29**, build
4
+ `boq_finhub-uiserver_20261026.07_p0`. This client implements the public consumer
5
+ quote, instrument-suggestion, and sampled-price chart surfaces. It does not
6
+ claim to reproduce all of Google Finance, provide a licensed market-data feed,
7
+ or expose paid/AI research features.
8
+
9
+ ```ts
10
+ import { finance } from 'googlemaps-kit/finance';
11
+
12
+ const client = finance();
13
+ const quote = await client.quote('GOOGL:NASDAQ');
14
+ const suggestions = await client.search('Microsoft');
15
+ const chart = await client.chart('GOOGL:NASDAQ', { range: '1M' });
16
+
17
+ console.log(quote.price, quote.currency, quote.time);
18
+ console.log(quote.extendedMarket);
19
+ console.log(suggestions.matches);
20
+ console.log(chart.sessions.flatMap(session => session.points));
21
+ ```
22
+
23
+ Instrument strings use **symbol:exchange** order, as Google Finance URLs do.
24
+ Objects `{ symbol: 'GOOGL', exchange: 'NASDAQ' }` are also accepted. `search`
25
+ returns identifiable instrument suggestions, deduplicating repeated UI groups;
26
+ it does not return an arbitrary natural-language or AI answer.
27
+
28
+ Configuration supports `fetch`, `timeoutMs`, `language`, and `userAgent`.
29
+ Methods accept an `AbortSignal`. Requests have a body-read deadline and do not
30
+ automatically retry a block or failure. `FinanceError` exports the shared
31
+ `GoogleWebError` class with `kind`, optional HTTP `status`, `rpcCode`, and
32
+ `retryAfterMs`. Rate-limit/automated-query responses remain errors.
33
+
34
+ ## Runtime and static evidence
35
+
36
+ - Ordinary headless Chromium rendered a complete GOOGL quote page. A generic
37
+ non-browser user agent had previously received an unsupported-client page.
38
+ The client therefore uses the exact captured browser user-agent family for
39
+ device negotiation; users may override it. Runtime browser evidence:
40
+ `ev_8b8ce4e3adf9f17541b4db84cde49b10828e312435ad8735c6596efac93c2ccd`.
41
+ - REA analyzed **66 observed scripts**, providing static descriptors and field
42
+ access evidence:
43
+ `ev_681d6f6b8601b800f9884383e2c34fd76024911ff6b8305bd91f61b0f7c97950`.
44
+ Static analysis does not establish endpoint execution; direct HTTP replay
45
+ below supplies the runtime verification.
46
+ - Direct anonymous HTTP replay returned 200 with real data for quote summary,
47
+ search suggestions, pricing details, and all eight chart ranges. No API key
48
+ or signed-in cookies were supplied. The complete client also passed an
49
+ opted-in live test for quote, search, and monthly chart.
50
+ - Original runtime HTML, requests, responses, and scripts remain in untracked
51
+ scratch storage. Offline tests use copied public-data payloads under
52
+ `tests/fixtures/finance/`; shipped code has no dependency on scratch files.
53
+
54
+ ## Verified protocol
55
+
56
+ Bootstrap `https://www.google.com/finance/?hl=en` and read `WIZ_global_data`:
57
+ `eptZe=/finance/_/FinHubUi/`, `FdrFJe` session, and `cfb2h` build. Calls POST
58
+ form-encoded `f.req` to
59
+ `https://www.google.com/finance/_/FinHubUi/data/batchexecute`, passing `rpcids`,
60
+ `source-path`, `f.sid`, `bl`, `hl`, and `rt=c`. Responses contain XSSI-prefixed,
61
+ framed `wrb.fr` JSON payloads. Captured anonymous requests omitted `at`.
62
+
63
+ | RPC | Shipped descriptor | Verified arguments | Client method |
64
+ | --- | --- | --- | --- |
65
+ | `gCvqoe` | `/FinanceHubService.ListEntitySummary` | `[[[null,[symbol,exchange]]]]` | `quote` |
66
+ | `XB3kn` | `/FinanceHubService.GetSearchSuggestions` | `[query,null,1]` | `search` |
67
+ | `c2u4wc` | `/FinanceHubService.ListHistoricalPricingData` | `[[[null,[symbol,exchange]]],rangeEnum]` | `chart` |
68
+ | `dlNq8b` | Pricing-detail surface | `[[[null,[symbol,exchange]]],1,1,1]` | Captured and replayed; not exposed by this client |
69
+
70
+ Browser traffic also registered and sometimes executed earnings/research RPCs,
71
+ including `Xs5i3b` (GetEarningsTranscriptHighlights), `Iaiw6c` (GetEarningsFiles),
72
+ and `TNo8E` (GetRelatedEarnings). Those are not the quote/search endpoints and
73
+ are not part of the public SDK contract. No claim of paid research parity is
74
+ made from their presence in a bundle.
75
+
76
+ ### Quote fields
77
+
78
+ `gCvqoe` response field 1 is repeated EntitySummary; each entry's field 1 is a
79
+ security node. The following are one-based security field numbers:
80
+
81
+ | Field | Meaning established by capture and renderer |
82
+ | --- | --- |
83
+ | 1 | Entity ID |
84
+ | 2 | `[symbol,exchange]` |
85
+ | 3 | Display name |
86
+ | 5 | Currency |
87
+ | 6 | Regular price tuple `[price,change,changePercent,...]` |
88
+ | 8 | Previous close |
89
+ | 12 | Reported data timestamp `[seconds,nanos]` |
90
+ | 13 | Exchange time-zone name |
91
+ | 14 | UTC offset seconds |
92
+ | 17 | Extended-session price tuple |
93
+ | 18 | Regular price timestamp |
94
+ | 19 | Extended-session price timestamp |
95
+ | 25 | Source enum; returned as an opaque code when present |
96
+
97
+ The successful GOOGL capture contained regular price **324.89 USD** and
98
+ extended price **292.50 USD**. These are fixture observations, not current
99
+ recommendations or promised live prices. The parser keeps them separate and
100
+ preserves zero prices/changes and original precision.
101
+
102
+ `reportedTime`, `time`, and `extendedMarket.time` are distinct source values.
103
+ The payload does not establish a guaranteed delay interval, so `delayStatus`
104
+ is `not-disclosed`; the SDK does not label every quote real-time. Some exchanges
105
+ or instruments can be delayed, missing, or unsupported. See Google's
106
+ [Finance data disclaimer](https://www.google.com/googlefinance/disclaimer/) and
107
+ [GOOGLEFINANCE limitations](https://support.google.com/docs/answer/3093281?hl=en).
108
+ The Sheets function and this consumer web transport are separate interfaces.
109
+
110
+ ### Historical charts
111
+
112
+ The UI's range enum is statically explicit and each range was replayed
113
+ successfully for GOOGL:
114
+
115
+ | Range | Enum | Observed interval seconds | Observed points |
116
+ | --- | --- | --- | --- |
117
+ | `1D` | 1 | 60 | 632 across regular and extended sessions |
118
+ | `5D` | 2 | 1800 | 70 |
119
+ | `1M` | 3 | 86400 | 23 |
120
+ | `6M` | 4 | 86400 | 128 |
121
+ | `YTD` | 5 | 86400 | 209 |
122
+ | `1Y` | 6 | 86400 | 252 |
123
+ | `5Y` | 7 | 604800 | 262 |
124
+ | `MAX` | 8 | 604800 | 1159 |
125
+
126
+ These intervals/counts describe the captured responses and may vary. `MAX`
127
+ does not imply a complete daily trading history. The response's field 4 groups
128
+ session headers and points. Each point is `[DateTime,priceTuple,volume]`.
129
+ DateTime months are one-based, and field 8 contains a UTC-offset message;
130
+ converting to ISO time must apply that offset rather than the execution host's
131
+ time zone. Session codes remain numeric: `1` and `3` were observed for regular
132
+ and extended data in the day capture.
133
+
134
+ Only verified price, time, and volume are normalized for chart points. Other
135
+ price-tuple values vary with the selected chart baseline and remain available
136
+ in `raw`, avoiding an incorrect “percent change” interpretation.
137
+
138
+ ## Validation and limits
139
+
140
+ Sixteen offline unit tests cover captured layouts, duplicate suggestions,
141
+ regular/extended separation, zero values, UTC offsets, malformed/missing data,
142
+ the request envelope, blocking, cancellation, and local validation.
143
+
144
+ ```sh
145
+ npx vitest run tests/unit/finance
146
+ GMAPS_LIVE=1 FINANCE_LIVE=1 npx vitest run tests/live/finance.test.ts
147
+ npm run type-check
148
+ ```
149
+
150
+ All passed during implementation. Live tests require explicit opt-in and are
151
+ excluded from the ordinary unit suite. Authentication-gated portfolios,
152
+ watchlists, premium research, AI generation, and undocumented tuple fields
153
+ remain outside this client's verified scope.
@@ -0,0 +1,43 @@
1
+ # Google Finance
2
+
3
+ ```ts
4
+ import { finance } from 'googlemaps-kit/finance';
5
+
6
+ const market = finance();
7
+ const quote = await market.quote('GOOGL:NASDAQ');
8
+ console.log(quote.name, quote.price, quote.currency, quote.time);
9
+ console.log(quote.extendedMarket);
10
+
11
+ const matches = await market.search('Microsoft');
12
+ const chart = await market.chart('GOOGL:NASDAQ', { range: '1M' });
13
+ console.log(matches.matches, chart.sessions);
14
+ ```
15
+
16
+ Instrument strings use `symbol:exchange`, matching the website's quote URL.
17
+ Objects `{ symbol, exchange }` are also accepted. Charts support `1D`, `5D`,
18
+ `1M`, `6M`, `YTD`, `1Y`, `5Y`, and `MAX`. Their sampling interval and available
19
+ session groups come from Google, not a locally reconstructed price history.
20
+
21
+ Quote results separate regular and extended-session prices and timestamps.
22
+ They also preserve currency, previous close, source-reported time, exchange
23
+ timezone and UTC offset where returned. `delayStatus` is `not-disclosed`;
24
+ the client does not infer that a quote is real-time. Raw positional payloads
25
+ remain available on all results.
26
+
27
+ Configuration accepts `fetch`, `timeoutMs` (default 30 seconds), `language`
28
+ (default `en`) and `userAgent`. The default user agent is the ordinary browser
29
+ used for the successful capture, because Google served an unsupported-device
30
+ page to a generic HTTP client. All methods accept `signal`; requests are not
31
+ automatically retried. `FinanceError` exposes `kind`, HTTP `status`, RPC code
32
+ and `retryAfterMs` where available. A captured missing-instrument status is
33
+ reported with RPC code 5.
34
+
35
+ This is a public quote/search/chart interface, with no API key or browser
36
+ runtime dependency. It does not implement portfolios, account operations,
37
+ AI investment answers, every asset type, fundamentals or exchange-data
38
+ licensing. See Google's [data information](https://www.google.com/googlefinance/disclaimer/)
39
+ and the [protocol research](finance-research.md) for exact contracts, live
40
+ evidence and remaining limits.
41
+
42
+ Run all public-client probes with `npm run test:google-public:live` or Finance
43
+ alone with `GMAPS_LIVE=1 FINANCE_LIVE=1 npx vitest run tests/live/finance.test.ts`.