tablefacts 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 (98) hide show
  1. package/.env.example +14 -0
  2. package/CHANGELOG.md +12 -0
  3. package/LICENSE +21 -0
  4. package/README.md +313 -0
  5. package/bin/tablefacts.mjs +28 -0
  6. package/package.json +77 -0
  7. package/src/index.mjs +52 -0
  8. package/src/instagram/README.md +135 -0
  9. package/src/instagram/download.mjs +62 -0
  10. package/src/instagram/index.mjs +355 -0
  11. package/src/instagram/links.mjs +55 -0
  12. package/src/instagram/record.mjs +18 -0
  13. package/src/lib/edge.mjs +49 -0
  14. package/src/lib/env.mjs +35 -0
  15. package/src/lib/errors.mjs +39 -0
  16. package/src/lib/files.mjs +10 -0
  17. package/src/lib/images.mjs +20 -0
  18. package/src/lib/log.mjs +17 -0
  19. package/src/lib/photos.mjs +42 -0
  20. package/src/lib/playwright.mjs +13 -0
  21. package/src/lib/project.mjs +42 -0
  22. package/src/lib/text.mjs +7 -0
  23. package/src/lib/types.mjs +247 -0
  24. package/src/menu/README.md +97 -0
  25. package/src/menu/cluvi/config.mjs +33 -0
  26. package/src/menu/cluvi/extract.mjs +24 -0
  27. package/src/menu/cluvi/import.mjs +30 -0
  28. package/src/menu/cluvi/source.mjs +156 -0
  29. package/src/menu/index.mjs +9 -0
  30. package/src/menu/lib/db.mjs +119 -0
  31. package/src/menu/lib/import.mjs +126 -0
  32. package/src/menu/lib/menu.mjs +95 -0
  33. package/src/menu/lib/run.mjs +83 -0
  34. package/src/menu/raw/config.mjs +38 -0
  35. package/src/menu/raw/extract.mjs +72 -0
  36. package/src/menu/raw/import.mjs +99 -0
  37. package/src/menu/raw/normalize.mjs +120 -0
  38. package/src/menu/raw/source.mjs +116 -0
  39. package/src/menu/raw/vision.mjs +252 -0
  40. package/src/research/README.md +69 -0
  41. package/src/research/index.mjs +147 -0
  42. package/src/research/lib/google.mjs +93 -0
  43. package/src/research/lib/hours.mjs +109 -0
  44. package/src/research/lib/merge.mjs +119 -0
  45. package/src/research/lib/osm.mjs +49 -0
  46. package/src/research/lib/report.mjs +118 -0
  47. package/src/research/lib/social.mjs +49 -0
  48. package/src/research/lib/util.mjs +104 -0
  49. package/src/research/lib/website.mjs +285 -0
  50. package/src/research/research.mjs +67 -0
  51. package/src/tripadvisor/README.md +78 -0
  52. package/src/tripadvisor/index.mjs +178 -0
  53. package/src/tripadvisor/links.mjs +78 -0
  54. package/src/tripadvisor/photos.mjs +55 -0
  55. package/types/index.d.mts +65 -0
  56. package/types/instagram/download.d.mts +1 -0
  57. package/types/instagram/index.d.mts +13 -0
  58. package/types/instagram/links.d.mts +14 -0
  59. package/types/instagram/record.d.mts +1 -0
  60. package/types/lib/edge.d.mts +14 -0
  61. package/types/lib/env.d.mts +12 -0
  62. package/types/lib/errors.d.mts +25 -0
  63. package/types/lib/files.d.mts +1 -0
  64. package/types/lib/images.d.mts +6 -0
  65. package/types/lib/log.d.mts +5 -0
  66. package/types/lib/photos.d.mts +30 -0
  67. package/types/lib/playwright.d.mts +1677 -0
  68. package/types/lib/project.d.mts +32 -0
  69. package/types/lib/text.d.mts +4 -0
  70. package/types/lib/types.d.mts +668 -0
  71. package/types/menu/cluvi/config.d.mts +13 -0
  72. package/types/menu/cluvi/extract.d.mts +2 -0
  73. package/types/menu/cluvi/import.d.mts +35 -0
  74. package/types/menu/cluvi/source.d.mts +37 -0
  75. package/types/menu/index.d.mts +6 -0
  76. package/types/menu/lib/db.d.mts +23 -0
  77. package/types/menu/lib/import.d.mts +11 -0
  78. package/types/menu/lib/menu.d.mts +24 -0
  79. package/types/menu/lib/run.d.mts +27 -0
  80. package/types/menu/raw/config.d.mts +18 -0
  81. package/types/menu/raw/extract.d.mts +2 -0
  82. package/types/menu/raw/import.d.mts +64 -0
  83. package/types/menu/raw/normalize.d.mts +29 -0
  84. package/types/menu/raw/source.d.mts +19 -0
  85. package/types/menu/raw/vision.d.mts +13 -0
  86. package/types/research/index.d.mts +9 -0
  87. package/types/research/lib/google.d.mts +12 -0
  88. package/types/research/lib/hours.d.mts +22 -0
  89. package/types/research/lib/merge.d.mts +87 -0
  90. package/types/research/lib/osm.d.mts +36 -0
  91. package/types/research/lib/report.d.mts +6 -0
  92. package/types/research/lib/social.d.mts +118 -0
  93. package/types/research/lib/util.d.mts +45 -0
  94. package/types/research/lib/website.d.mts +283 -0
  95. package/types/research/research.d.mts +1 -0
  96. package/types/tripadvisor/index.d.mts +11 -0
  97. package/types/tripadvisor/links.d.mts +13 -0
  98. package/types/tripadvisor/photos.d.mts +1 -0
@@ -0,0 +1,13 @@
1
+ declare const _default: {
2
+ url: string;
3
+ categories: {
4
+ slug: string;
5
+ name: string;
6
+ from: string[];
7
+ }[];
8
+ sections: {
9
+ "Cócteles Autor Cannario": string;
10
+ Mocktails: string;
11
+ };
12
+ };
13
+ export default _default;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Reads and normalizes the menu: `{ menu, notes, title }`, ready for importMenu.
3
+ * `config` is the restaurant-specific part (see config.mjs); the default is that file's.
4
+ */
5
+ export declare function fetchCluviMenu({ url, service, lang, config }?: {
6
+ config?: {
7
+ url: string;
8
+ categories: {
9
+ slug: string;
10
+ name: string;
11
+ from: string[];
12
+ }[];
13
+ sections: {
14
+ "Cócteles Autor Cannario": string;
15
+ Mocktails: string;
16
+ };
17
+ } | undefined;
18
+ }): Promise<{
19
+ menu: {
20
+ slug: any;
21
+ name: any;
22
+ sections: {
23
+ name: any;
24
+ products: any;
25
+ }[];
26
+ }[];
27
+ notes: string[];
28
+ title: string;
29
+ }>;
30
+ /**
31
+ * Reads the menu from Cluvi and imports it. Takes importMenu's options too.
32
+ * @param {import('../../lib/types.mjs').ImportCluviOptions} [options]
33
+ * @returns {Promise<import('../../lib/types.mjs').ImportResult>}
34
+ */
35
+ export declare function importCluvi({ url, service, lang, config, ...importOptions }?: import('../../lib/types.mjs').ImportCluviOptions): Promise<import('../../lib/types.mjs').ImportResult>;
@@ -0,0 +1,37 @@
1
+ /** https://<restaurant>.cluvi.co/<supplier>/maincategories gives "<supplier>". */
2
+ export declare function supplierSlug(menuUrl: any): string;
3
+ /**
4
+ * `service` picks which of the restaurant's menus to read. `on_table` is the
5
+ * digital menu guests open from the table QR code and is the complete one:
6
+ * `delivery` and `take_away` only list what the restaurant sells that way.
7
+ */
8
+ export declare function fetchCluvi({ url, service, lang }: {
9
+ lang?: string | undefined;
10
+ service?: string | undefined;
11
+ url: any;
12
+ }): Promise<{
13
+ supplier: any;
14
+ raw: any;
15
+ service: string;
16
+ }>;
17
+ /**
18
+ * Cluvi's response to the shape lib/menu.mjs describes. Main categories are
19
+ * folded into the categories of `config.categories`, subcategories become
20
+ * sections, and products keep the order Cluvi shows them in (their `order`
21
+ * field, not their position in the subcategory's product_ids).
22
+ */
23
+ export declare function normalizeCluvi({ supplier, raw }: {
24
+ raw: any;
25
+ supplier: any;
26
+ }, config: any): {
27
+ menu: {
28
+ slug: any;
29
+ name: any;
30
+ sections: {
31
+ name: any;
32
+ products: any;
33
+ }[];
34
+ }[];
35
+ notes: string[];
36
+ currency: string;
37
+ };
@@ -0,0 +1,6 @@
1
+ export { importMenu } from "./lib/import.mjs";
2
+ export { importCluvi } from "./cluvi/import.mjs";
3
+ export { importImageMenu, listMenuImages } from "./raw/import.mjs";
4
+ export { cleanText, countMenu, sectionName, slugify, validateMenu } from "./lib/menu.mjs";
5
+ export { normalizePages, parsePrice } from "./raw/normalize.mjs";
6
+ export { defaultProvider, providers } from "./raw/vision.mjs";
@@ -0,0 +1,23 @@
1
+ /** Opens the connection. `label` names the target without the credentials. */
2
+ export declare function connect(url: any, { env }?: {}): Promise<{
3
+ client: any;
4
+ label: string;
5
+ }>;
6
+ /** What an import would replace: the categories it writes, or the whole menu. */
7
+ export declare function inspect(client: any, menu: any, { replaceAll }?: {
8
+ replaceAll?: boolean | undefined;
9
+ }): Promise<any>;
10
+ /**
11
+ * Replaces the menu in one transaction, so readers see the old menu or the new
12
+ * one and a failure changes nothing. By default only the categories in `menu`
13
+ * are replaced (deleting a category cascades to its sections and products);
14
+ * `replaceAll` empties the menu first. Ids are generated here so the rows can
15
+ * be inserted in bulk, a column at a time.
16
+ */
17
+ export declare function replaceMenu(client: any, menu: any, { replaceAll }?: {
18
+ replaceAll?: boolean | undefined;
19
+ }): Promise<{
20
+ categories: any;
21
+ sections: any;
22
+ products: any;
23
+ }>;
@@ -0,0 +1,11 @@
1
+ /** Things the site needs that this menu does not give it, read from the template's own files. */
2
+ export declare function templateHints(menu: any, { projectDir }?: {}): Promise<string[]>;
3
+ /**
4
+ * Checks `menu` (the shape of lib/menu.mjs) and writes it to the database.
5
+ * `notes` are what the source wants the user to know; `title` heads the log.
6
+ * Resolves to `{ totals, notes, written, dryRun, database }`, `database` being
7
+ * `{ label, current }` once it was inspected and null when it was not reached.
8
+ * @param {import('../../lib/types.mjs').ImportMenuOptions} options
9
+ * @returns {Promise<import('../../lib/types.mjs').ImportResult>}
10
+ */
11
+ export declare function importMenu({ menu, notes, title, dryRun, json, replaceAll, force, databaseUrl, env, projectDir, log: logOption, }?: import('../../lib/types.mjs').ImportMenuOptions): Promise<import('../../lib/types.mjs').ImportResult>;
@@ -0,0 +1,24 @@
1
+ declare const squash: (text: any) => string;
2
+ /** Collapses runs of whitespace (Cluvi labels carry stray spaces). */
3
+ export declare const cleanText: typeof squash;
4
+ /** Lowercase, accent-free key, to compare labels typed by different people. */
5
+ export declare const matchKey: (text: any) => string;
6
+ export declare const slugify: (text: any) => string;
7
+ export declare const sectionName: (text: any) => string;
8
+ /** Rich-text descriptions (<p>, <br>, <span style>) to plain text, one line per paragraph. */
9
+ export declare function htmlToText(html: any): string | null;
10
+ /** An invalid code would make Intl.NumberFormat throw in the site's formatPrice. */
11
+ export declare const isCurrency: (code: any) => boolean;
12
+ /**
13
+ * Totals of a menu.
14
+ * @param {import('../../lib/types.mjs').Menu} menu
15
+ * @returns {import('../../lib/types.mjs').MenuTotals}
16
+ */
17
+ export declare function countMenu(menu: import('../../lib/types.mjs').Menu): import('../../lib/types.mjs').MenuTotals;
18
+ /**
19
+ * Throws a TablefactsError (EFAILED) on anything the database or the site could not take, naming the culprit.
20
+ * @param {import('../../lib/types.mjs').Menu} menu
21
+ * @returns {void}
22
+ */
23
+ export declare function validateMenu(menu: import('../../lib/types.mjs').Menu): void;
24
+ export {};
@@ -0,0 +1,27 @@
1
+ /** The option names the menu library uses in its messages, as the flags the CLI shows. */
2
+ export declare const menuFlags: {
3
+ only: string;
4
+ provider: string;
5
+ model: string;
6
+ minWidth: string;
7
+ replaceAll: string;
8
+ force: string;
9
+ dryRun: string;
10
+ };
11
+ /** A library message with option names turned into flags. */
12
+ export declare const flagText: (message: any) => string;
13
+ /**
14
+ * The CLI's logger: info and warn lines (progress, notes, "left untouched") go to stdout as
15
+ * they always did, errors to stderr, and option names in the text become flags.
16
+ */
17
+ export declare const cliLog: (message: any, level?: string) => void;
18
+ /**
19
+ * `fetchMenu({ values, positionals })` returns `{ menu, notes, title }`: the
20
+ * menu in the shape of lib/menu.mjs, what the source wants the user to know,
21
+ * and a heading. `options` are the source's own flags, in util.parseArgs form.
22
+ */
23
+ export declare function runImport({ usage, options, fetchMenu }: {
24
+ fetchMenu: any;
25
+ options?: {} | undefined;
26
+ usage: any;
27
+ }): Promise<void>;
@@ -0,0 +1,18 @@
1
+ declare const _default: {
2
+ url: string;
3
+ currency: string;
4
+ thousands: string;
5
+ decimal: string;
6
+ scale: number;
7
+ categories: {
8
+ slug: string;
9
+ name: string;
10
+ groups: string[];
11
+ }[];
12
+ placeIn: {};
13
+ sections: {
14
+ "Cócteles de Autor": string;
15
+ };
16
+ skipSections: never[];
17
+ };
18
+ export default _default;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,64 @@
1
+ /** Every image found, and the numbered ones `only` selects. `config` defaults to config.mjs. */
2
+ export declare function findPages({ urls, only, minWidth, config }?: {
3
+ config?: {
4
+ url: string;
5
+ currency: string;
6
+ thousands: string;
7
+ decimal: string;
8
+ scale: number;
9
+ categories: {
10
+ slug: string;
11
+ name: string;
12
+ groups: string[];
13
+ }[];
14
+ placeIn: {};
15
+ sections: {
16
+ "Cócteles de Autor": string;
17
+ };
18
+ skipSections: never[];
19
+ } | undefined;
20
+ minWidth?: number | undefined;
21
+ urls?: never[] | undefined;
22
+ }): Promise<{
23
+ pages: any[];
24
+ chosen: any[];
25
+ }>;
26
+ /**
27
+ * The pictures the CLI's `--list` prints, numbered. `only` narrows them.
28
+ * @param {import('../../lib/types.mjs').ListMenuImagesOptions} [options]
29
+ * @returns {Promise<import('../../lib/types.mjs').MenuImage[]>}
30
+ */
31
+ export declare function listMenuImages(options?: import('../../lib/types.mjs').ListMenuImagesOptions): Promise<import('../../lib/types.mjs').MenuImage[]>;
32
+ /** Reads the pages and normalizes them: `{ menu, notes, title }`, ready for importMenu. */
33
+ export declare function fetchImageMenu({ urls, only, provider, model, minWidth, refresh, apiKey, env, projectDir, config, log: logOption }?: {
34
+ config?: {
35
+ url: string;
36
+ currency: string;
37
+ thousands: string;
38
+ decimal: string;
39
+ scale: number;
40
+ categories: {
41
+ slug: string;
42
+ name: string;
43
+ groups: string[];
44
+ }[];
45
+ placeIn: {};
46
+ sections: {
47
+ "Cócteles de Autor": string;
48
+ };
49
+ skipSections: never[];
50
+ } | undefined;
51
+ minWidth?: number | undefined;
52
+ refresh?: boolean | undefined;
53
+ urls?: never[] | undefined;
54
+ }): Promise<{
55
+ menu: import("../../lib/types.mjs").Menu;
56
+ notes: string[];
57
+ title: string;
58
+ }>;
59
+ /**
60
+ * Reads the menu from pictures with a vision model and imports it. Takes importMenu's options too.
61
+ * @param {import('../../lib/types.mjs').ImportImageMenuOptions} [options]
62
+ * @returns {Promise<import('../../lib/types.mjs').ImportResult>}
63
+ */
64
+ export declare function importImageMenu({ urls, only, provider, model, minWidth, refresh, apiKey, env, config, ...importOptions }?: import('../../lib/types.mjs').ImportImageMenuOptions): Promise<import('../../lib/types.mjs').ImportResult>;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * "$95.000" to 95000. `thousands` and `decimal` are the separators the menu
3
+ * prints (Colombia: "." and ","); `scale` multiplies the result for menus that
4
+ * print "95" meaning 95.000. Returns null for text with no number.
5
+ * @param {string} text
6
+ * @param {import('../../lib/types.mjs').PriceFormat} [format]
7
+ * @returns {number | null}
8
+ */
9
+ export declare function parsePrice(text: string, { thousands, decimal, scale }?: import('../../lib/types.mjs').PriceFormat): number | null;
10
+ /**
11
+ * `pages` is the transcription of each page, in page order. A section with no
12
+ * title continues the section before it (a list that runs onto the next page),
13
+ * and sections with the same title are merged. Each section is placed in the
14
+ * category of `config.categories` that lists its group (food, drink), unless
15
+ * `config.placeIn` names it. An item with several priced columns becomes one
16
+ * product per column, "Name (Botella)", because a product has one price.
17
+ * @param {{ number?: number, notes?: string[], sections?: any[] }[]} pages transcriptions, one per page
18
+ * @param {import('../../lib/types.mjs').RawConfig} config
19
+ * @returns {{ menu: import('../../lib/types.mjs').Menu, notes: string[], currency: string }}
20
+ */
21
+ export declare function normalizePages(pages: {
22
+ number?: number;
23
+ notes?: string[];
24
+ sections?: any[];
25
+ }[], config: import('../../lib/types.mjs').RawConfig): {
26
+ menu: import('../../lib/types.mjs').Menu;
27
+ notes: string[];
28
+ currency: string;
29
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * The picture URLs of a page, in document order. Lazy-loaders keep the real
3
+ * address in data-orig-src / data-src and put a placeholder in src, so those
4
+ * come first. Images declaring a width under `minWidth` (logos, icons) and
5
+ * anything that is not a JPG, PNG or WebP (SVG logos) are skipped.
6
+ */
7
+ export declare function findImages(html: any, pageUrl: any, { minWidth }?: {
8
+ minWidth?: number | undefined;
9
+ }): any[];
10
+ /** Each argument is a page to scan or a direct image URL. */
11
+ export declare function discoverPages(inputs: any, options: any): Promise<any[]>;
12
+ export declare const pageId: (url: any) => string;
13
+ /** Downloads one page image into the cache (once) and returns where it is and what it is. */
14
+ export declare function downloadPage(page: any, host: any, { projectDir }?: {}): Promise<{
15
+ id: string;
16
+ dir: string;
17
+ file: string;
18
+ mediaType: string;
19
+ }>;
@@ -0,0 +1,13 @@
1
+ /** @type {Record<string, import('../../lib/types.mjs').VisionProvider>} */
2
+ export declare const providers: Record<string, import('../../lib/types.mjs').VisionProvider>;
3
+ export declare const defaultProvider = "anthropic";
4
+ /** `file` is a downloaded picture; returns `{ sections, notes }` as the schema above describes. */
5
+ export declare function readPage({ file, mediaType }: {
6
+ file: any;
7
+ mediaType: any;
8
+ }, { provider, model, apiKey, env }?: {
9
+ provider?: string | undefined;
10
+ }): Promise<{
11
+ sections: any;
12
+ notes: any;
13
+ }>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Researches a restaurant from public sources and writes profile.json, report.md and
3
+ * setup-answers.txt. Silent unless `log` is given; a source that fails becomes a note in the
4
+ * report, not an error. Throws a TablefactsError with code 'EUSAGE' (and `option` 'name') when
5
+ * `name` is missing.
6
+ * @param {import('../lib/types.mjs').ResearchOptions} options
7
+ * @returns {Promise<import('../lib/types.mjs').ResearchResult>}
8
+ */
9
+ export declare function research(options?: import('../lib/types.mjs').ResearchOptions): Promise<import('../lib/types.mjs').ResearchResult>;
@@ -0,0 +1,12 @@
1
+ /** Returns { place, candidates }: `place` is the first result whose name matches, or null. */
2
+ export declare function searchGoogle({ name, location, country, key }: {
3
+ country: any;
4
+ key: any;
5
+ location: any;
6
+ name: any;
7
+ }): Promise<{
8
+ place: any;
9
+ candidates: any;
10
+ }>;
11
+ /** Downloads up to `count` photos into `dir`, returns what was saved. The key stays out of the result. */
12
+ export declare function downloadPhotos(place: any, key: any, count: any, save: any): Promise<any[]>;
@@ -0,0 +1,22 @@
1
+ /** Google `regularOpeningHours.periods` (day 0 = Sunday). */
2
+ export declare function fromGoogle(periods?: any[]): {
3
+ week: string[][][];
4
+ } | null;
5
+ /** OpenStreetMap / schema.org `openingHours` syntax: "Mo-Th 12:00-22:00; Fr,Sa 12:00-00:00; Su off". */
6
+ export declare function fromOsm(text: any): {
7
+ week: string[][][];
8
+ partial?: undefined;
9
+ } | {
10
+ week: never[][];
11
+ partial: boolean;
12
+ } | null;
13
+ /** schema.org `openingHoursSpecification` entries. */
14
+ export declare function fromSpec(specs?: any[]): {
15
+ week: never[][];
16
+ } | null;
17
+ export declare const weekSignature: (week: any) => any;
18
+ /** Rows for `visit.hoursRows`: { label, value }, matching the template's wording. */
19
+ export declare function formatRows(week: any, lang: any): {
20
+ label: any;
21
+ value: any;
22
+ }[];
@@ -0,0 +1,87 @@
1
+ export declare function buildProfile({ query, google, osm, site, hub, instagram, tripadvisor }: {
2
+ google: any;
3
+ hub: any;
4
+ instagram: any;
5
+ osm: any;
6
+ query: any;
7
+ site: any;
8
+ tripadvisor: any;
9
+ }): {
10
+ query: any;
11
+ generatedAt: string;
12
+ warnings: string[];
13
+ fields: {
14
+ name: any;
15
+ street: any;
16
+ locality: any;
17
+ region: any;
18
+ country: any;
19
+ coordinates: any;
20
+ phone: any;
21
+ email: any;
22
+ instagram: any;
23
+ facebook: any;
24
+ tiktok: any;
25
+ tripadvisor: any;
26
+ website: any;
27
+ reserveUrl: any;
28
+ priceRange: any;
29
+ mapsUrl: any;
30
+ descriptor: any;
31
+ };
32
+ hours: {
33
+ source: string;
34
+ week: any;
35
+ rows: {
36
+ es: {
37
+ label: any;
38
+ value: any;
39
+ }[];
40
+ en: {
41
+ label: any;
42
+ value: any;
43
+ }[];
44
+ };
45
+ confidence: string;
46
+ conflicts: {
47
+ source: string;
48
+ rows: {
49
+ label: any;
50
+ value: any;
51
+ }[];
52
+ }[];
53
+ } | null;
54
+ textHours: any[];
55
+ links: {
56
+ menu: any[];
57
+ delivery: any[];
58
+ reserve: any[];
59
+ waze: any[];
60
+ hubs: any[];
61
+ };
62
+ ratings: any[];
63
+ images: {
64
+ logos: any[];
65
+ site: any;
66
+ hub: any;
67
+ googlePhotos: any;
68
+ instagramImage: any;
69
+ themeColor: any;
70
+ };
71
+ copySources: {
72
+ googleSummary: any;
73
+ siteDescription: any;
74
+ instagramBio: any;
75
+ tripadvisor: any;
76
+ headings: any;
77
+ paragraphs: any;
78
+ };
79
+ social: {
80
+ instagram: {
81
+ handle: any;
82
+ followers: any;
83
+ posts: any;
84
+ blocked: any;
85
+ } | null;
86
+ };
87
+ };
@@ -0,0 +1,36 @@
1
+ export declare function searchOsm({ name, location, country }: {
2
+ country: any;
3
+ location: any;
4
+ name: any;
5
+ }): Promise<{
6
+ place: {
7
+ source: string;
8
+ name: any;
9
+ street: string;
10
+ locality: any;
11
+ region: any;
12
+ country: any;
13
+ postcode: any;
14
+ coords: {
15
+ lat: number;
16
+ lng: number;
17
+ };
18
+ phone: any;
19
+ whatsapp: any;
20
+ email: any;
21
+ website: any;
22
+ instagram: any;
23
+ facebook: any;
24
+ cuisines: any;
25
+ hours: {
26
+ week: string[][][];
27
+ partial?: undefined;
28
+ } | {
29
+ week: never[][];
30
+ partial: boolean;
31
+ } | null;
32
+ hoursRaw: any;
33
+ osmUrl: string;
34
+ } | null;
35
+ candidates: any;
36
+ }>;
@@ -0,0 +1,6 @@
1
+ export declare function renderReport(p: any, { notes, photos }: {
2
+ notes: any;
3
+ photos: any;
4
+ }): string;
5
+ /** One line per prompt of `data/scripts/setup.mjs`, in its order. Blank keeps the current value. */
6
+ export declare function setupAnswers(p: any): string;
@@ -0,0 +1,118 @@
1
+ /**
2
+ * Public Instagram profile metadata. Without a login the page only exposes the
3
+ * share card: "1,234 Followers, 56 Following, 789 Posts - Name (@handle) on
4
+ * Instagram: "bio"". The bio often carries the phone, the area and a hub link.
5
+ */
6
+ export declare function readInstagram(handle: any): Promise<{
7
+ handle: any;
8
+ url: string;
9
+ blocked: any;
10
+ displayName?: undefined;
11
+ followers?: undefined;
12
+ posts?: undefined;
13
+ bio?: undefined;
14
+ phones?: undefined;
15
+ links?: undefined;
16
+ image?: undefined;
17
+ } | {
18
+ blocked?: undefined;
19
+ handle: any;
20
+ url: string;
21
+ displayName: any;
22
+ followers: any;
23
+ posts: any;
24
+ bio: any;
25
+ phones: any[];
26
+ links: any;
27
+ image: any;
28
+ }>;
29
+ /** TripAdvisor: schema.org JSON-LD when the page loads; DataDome often blocks it. */
30
+ export declare function readTripadvisor(url: any, { browser }?: {}): Promise<{
31
+ url: any;
32
+ blocked: string;
33
+ jsonld?: undefined;
34
+ description?: undefined;
35
+ hoursText?: undefined;
36
+ images?: undefined;
37
+ } | {
38
+ blocked?: undefined;
39
+ url: any;
40
+ jsonld: {
41
+ name: any;
42
+ telephone: any;
43
+ email: any;
44
+ priceRange: any;
45
+ cuisines: string[];
46
+ address: {
47
+ street: any;
48
+ locality: any;
49
+ region: any;
50
+ postcode: any;
51
+ country: any;
52
+ };
53
+ geo: {
54
+ lat: number;
55
+ lng: number;
56
+ } | null;
57
+ sameAs: string[];
58
+ logo: any;
59
+ rating: {
60
+ value: number;
61
+ count: number | null;
62
+ } | null;
63
+ hours: {
64
+ week: string[][][];
65
+ partial?: undefined;
66
+ } | {
67
+ week: never[][];
68
+ } | null;
69
+ } | null;
70
+ description: any;
71
+ hoursText: any;
72
+ images: any[];
73
+ }>;
74
+ /** A link-in-bio hub (Linktree, Beacons, bio.link): its links, classified like a website's. */
75
+ export declare function readHub(url: any, { browser }?: {}): Promise<{
76
+ links?: undefined;
77
+ images?: undefined;
78
+ url: any;
79
+ blocked: string;
80
+ title?: undefined;
81
+ meta?: undefined;
82
+ anchors?: undefined;
83
+ logos?: undefined;
84
+ } | {
85
+ blocked?: undefined;
86
+ url: any;
87
+ title: any;
88
+ meta: {
89
+ siteName: any;
90
+ title: any;
91
+ description: any;
92
+ themeColor: any;
93
+ };
94
+ links: {
95
+ tel: never[];
96
+ mail: never[];
97
+ whatsapp: never[];
98
+ reserve: never[];
99
+ menu: never[];
100
+ delivery: never[];
101
+ maps: never[];
102
+ waze: never[];
103
+ facebook: never[];
104
+ tiktok: never[];
105
+ tripadvisor: never[];
106
+ hubs: never[];
107
+ instagram: never[];
108
+ };
109
+ anchors: {
110
+ href: string | null;
111
+ text: any;
112
+ }[];
113
+ logos: {
114
+ url: string | null;
115
+ kind: any;
116
+ }[];
117
+ images: any[];
118
+ }>;