diff --git a/connectors/registry.json b/connectors/registry.json index 4ce5ecc..d138fdd 100644 --- a/connectors/registry.json +++ b/connectors/registry.json @@ -62,6 +62,21 @@ "script": "sha256:665a010ce5cc1d44a5278f010a56dafa94ff00e4dcd6458fb22afe3d01a505a4", "metadata": "sha256:b556e27341f88d841cf09cf68e0f9b9fa262f64465b2aa2cf9b64c831fe0a6eb" } + }, + { + "id": "heb-playwright", + "company": "heb", + "version": "1.0.0", + "name": "H-E-B", + "description": "Exports your H-E-B account profile, order history, and product nutrition data using Playwright browser automation.", + "files": { + "script": "heb/heb-playwright.js", + "metadata": "heb/heb-playwright.json" + }, + "checksums": { + "script": "sha256:10fb9715d30d4484371c1f82b35521842e608ebf54e045c6fcc0d80444e13e2a", + "metadata": "sha256:b449085b127d03739a91880250f699dd0b1118f5469474733e647514757e4ae3" + } } ] } diff --git a/public/icons/heb.png b/public/icons/heb.png new file mode 100644 index 0000000..5affb09 Binary files /dev/null and b/public/icons/heb.png differ diff --git a/scripts/sync-connectors-dev.js b/scripts/sync-connectors-dev.js index 99b56f0..9d1609c 100644 --- a/scripts/sync-connectors-dev.js +++ b/scripts/sync-connectors-dev.js @@ -1,43 +1,60 @@ #!/usr/bin/env node /** - * Syncs project connectors to ~/.dataconnect/connectors/ for dev mode. + * Syncs connectors to ~/.dataconnect/connectors/ for dev mode. * - * The Rust backend checks ~/.dataconnect/connectors/ first (user overrides), - * falling back to the project's connectors/ directory. In production this - * allows OTA updates, but in dev it means local edits are shadowed by stale - * copies. This script copies the project connectors into the user directory - * so dev always runs the latest source tree version. + * If CONNECTORS_PATH is set, syncs from that directory (e.g. a local + * data-connectors repo checkout). Otherwise falls back to the project's + * own connectors/ directory. + * + * Usage: + * CONNECTORS_PATH=../data-connectors npm run tauri:dev */ -import { cpSync, existsSync, mkdirSync, readdirSync, statSync } from 'fs'; -import { join, dirname } from 'path'; +import { cpSync, existsSync, mkdirSync, readFileSync } from 'fs'; +import { join, dirname, resolve } from 'path'; import { fileURLToPath } from 'url'; import { homedir } from 'os'; const __dirname = dirname(fileURLToPath(import.meta.url)); const PROJECT_CONNECTORS = join(__dirname, '..', 'connectors'); +const SOURCE_CONNECTORS = process.env.CONNECTORS_PATH + ? resolve(process.env.CONNECTORS_PATH) + : PROJECT_CONNECTORS; const USER_CONNECTORS = join(homedir(), '.dataconnect', 'connectors'); function log(msg) { console.log(`[sync-connectors-dev] ${msg}`); } -// Only sync company/connector dirs (skip schemas/, types/, lib/, registry.json, etc.) -function isConnectorDir(name) { - const skipDirs = ['schemas', 'types', 'lib', 'node_modules']; - if (skipDirs.includes(name)) return false; - const fullPath = join(PROJECT_CONNECTORS, name); - return statSync(fullPath).isDirectory(); +// Derive connector directories from registry.json file paths. +function getConnectorDirs() { + const registryPath = join(SOURCE_CONNECTORS, 'registry.json'); + if (!existsSync(registryPath)) { + log(`No registry.json found at ${registryPath}`); + return []; + } + const registry = JSON.parse(readFileSync(registryPath, 'utf-8')); + const dirs = new Set(); + for (const connector of registry.connectors ?? []) { + for (const filePath of Object.values(connector.files ?? {})) { + dirs.add(filePath.split('/')[0]); + } + } + return [...dirs]; } function main() { - if (!existsSync(PROJECT_CONNECTORS)) { - log('No project connectors directory found, skipping'); + if (!existsSync(SOURCE_CONNECTORS)) { + log(`Connectors source not found: ${SOURCE_CONNECTORS}, skipping`); return; } - const dirs = readdirSync(PROJECT_CONNECTORS).filter(isConnectorDir); + if (process.env.CONNECTORS_PATH) { + log(`Using CONNECTORS_PATH: ${SOURCE_CONNECTORS}`); + } + + const dirs = getConnectorDirs(); if (dirs.length === 0) { log('No connector directories found, skipping'); @@ -48,7 +65,11 @@ function main() { let copied = 0; for (const dir of dirs) { - const src = join(PROJECT_CONNECTORS, dir); + const src = join(SOURCE_CONNECTORS, dir); + if (!existsSync(src)) { + log(`Skipping ${dir}/ (not found in ${SOURCE_CONNECTORS})`); + continue; + } const dest = join(USER_CONNECTORS, dir); cpSync(src, dest, { recursive: true }); copied++; diff --git a/src/components/icons/platform-heb.tsx b/src/components/icons/platform-heb.tsx new file mode 100644 index 0000000..cb76744 --- /dev/null +++ b/src/components/icons/platform-heb.tsx @@ -0,0 +1,13 @@ +import type { ComponentPropsWithoutRef } from "react" + +export const PlatformHebIcon = ( + props: ComponentPropsWithoutRef<"img"> & { style?: React.CSSProperties } +) => { + return ( + H-E-B + ) +} diff --git a/src/lib/platform/icons.ts b/src/lib/platform/icons.ts index 3ecfc36..3d3cd14 100644 --- a/src/lib/platform/icons.ts +++ b/src/lib/platform/icons.ts @@ -2,6 +2,7 @@ import type { ElementType } from "react" import { IconX } from "@/components/icons/icon-x" import { PlatformChatGPTIcon } from "@/components/icons/platform-chatgpt" import { PlatformGithubIcon } from "@/components/icons/platform-github" +import { PlatformHebIcon } from "@/components/icons/platform-heb" import { PlatformInstagramGlyphIcon } from "@/components/icons/platform-instagram-glyph" import { PlatformLinkedinIcon } from "@/components/icons/platform-linkedin" import { PlatformShopIcon } from "@/components/icons/platform-shop" @@ -18,6 +19,7 @@ export type PlatformIconComponent = ElementType<{ className?: string }> const PLATFORM_ICON_COMPONENTS: Record = { chatgpt: PlatformChatGPTIcon, github: PlatformGithubIcon, + heb: PlatformHebIcon, instagram: PlatformInstagramGlyphIcon, linkedin: PlatformLinkedinIcon, shop: PlatformShopIcon, diff --git a/src/lib/platform/registry.ts b/src/lib/platform/registry.ts index 8e9242f..20f161c 100644 --- a/src/lib/platform/registry.ts +++ b/src/lib/platform/registry.ts @@ -148,4 +148,16 @@ export const PLATFORM_REGISTRY: PlatformRegistryEntry[] = [ showInConnectList: true, ingestScope: "shop.orders", }, + { + id: "heb", + displayName: "H-E-B", + iconKey: "heb", + iconEmoji: "🛒", + primaryColor: "#E31837", + platformIds: ["heb-playwright"], + aliases: ["heb"], + availability: "requiresConnector", + showInConnectList: true, + ingestScope: "heb.orders", + }, ]