4.9 KiB
Architecture Documentation
System Overview
This project serves as a bridge between Google Sheets and Shopify. It enables a two-way sync (primarily Sheets to Shopify for products) and allows managing inventory directly from a spreadsheet.
Core Flows
-
Product Updates:
- User edits a cell in the "product_inventory" sheet.
onEditQueuetrigger fires, capturing the SKU and timestamp.- Edits are batched in
PropertiesService(script properties). - A time-based trigger runs
processBatchedEditsevery minute. - The processing function locks the script, reads the queue, and pushes changes to Shopify via the Admin API.
-
Order Sync:
- Users can run menu commands to fetch orders from Shopify.
- The
Shopclass fetches orders via the REST API, handling pagination. - Data is populated into specific sheets (
_orders,_line_items,_customer, etc.).
Key Components
1. Queue System (src/onEditQueue.ts)
To avoid hitting Shopify API rate limits and Google Apps Script execution time limits, edits are not processed immediately.
-
onEditQueue(e):- Triggered on every cell edit.
- Checks if the edit is valid (correct sheet, valid SKU).
- Acquires a
DocumentLock. - Updates a JSON list in
ScriptProperties(pendingEdits). - Debounces edits (updates timestamp if SKU is already pending).
-
processBatchedEdits():- Run via time-based trigger (every 1 minute).
- Acquires a
ScriptLock. - Reads
pendingEdits. - Filters for edits older than
BATCH_INTERVAL_MS(30s) to allow for multiple quick edits to the same SKU. - Iterates through valid edits and calls
Product.UpdateShopifyProduct.
2. Shopify Integration (src/shopifyApi.ts)
The project uses a hybrid approach for the Shopify Admin API:
- REST API: Used primarily for fetching Orders (legacy support).
- GraphQL API: Used for fetching and updating Products and Inventory.
The Shop class handles authentication using credentials stored in the "vars" sheet.
3. Configuration (src/config.ts)
Configuration, including API keys, is stored in a dedicated Google Sheet named "vars". The Config class reads these values at runtime using a vlookup style helper.
Required "vars" columns:
key: The name of the configuration variable.value: The actual value.
4. Global Entry Points (src/global.ts)
Since Apps Script functions must be top-level to be triggered or attached to buttons, src/global.ts explicitly exposes necessary functions from the modules to the global scope.
5. Status Automation (src/statusHandlers.ts)
A modular system handles changes to the status column. It uses a registry of StatusHandler implementations:
- Published: Sets Shopify Status
ACTIVE, Quantity1. - Sold/Artist Swap: Sets Shopify Status
ACTIVE, Quantity0. - Drafted: Sets Shopify Status
DRAFT.
Triggers
Triggers are managed programmatically via src/triggers.ts. Running reinstallTriggers will wipe existing project triggers and set up the standard set:
onEdit->onEditHandler(Main Router)TimeBased (1 min)->processBatchedEditsTimeBased (10 min)->checkRecentSales
5. Troubleshooting Panel (src/sidebar.ts, src/Sidebar.html)
A dedicated side panel provides visibility into the background queue system.
-
Backend (
src/sidebar.ts):getQueueStatus(): Returns the current state of the queue and global toggle.setQueueEnabled(): Toggles the globalqueueEnabledscript property.deleteEdit()/pushEdit(): Manages specific items in the queue with safety checks.
-
Frontend (
src/Sidebar.html):- Displays pending edits with timestamps.
- Provides controls to globally enable/disable processing.
- Allows manual intervention (delete/push) for individual items.
6. Service Layer, Testing & Quality
To enable unit testing without Google Apps Script dependencies, the project uses a Service pattern with Dependency Injection.
Architecture
ISpreadsheetService: Interface for all sheet interactions.GASSpreadsheetService: Production implementation wrappingSpreadsheetApp.MockSpreadsheetService: In-memory implementation for tests.
Quality Assurance
We use Husky and lint-staged to enforce quality standards at the commit level:
- Pre-commit Hook: Automatically runs
npm test -- --onlyChanged --coverage. - Coverage Policy: Any file modified in a commit must meet an 80% line coverage threshold. This ensures the codebase quality improves monotonically ("Boy Scout Rule").
Classes (like Product) should accept an ISpreadsheetService in their constructor. This allows providing the Mock service during tests to verify logic without touching real Google Sheets.