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 (
+
+ )
+}
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",
+ },
]