# hexasync-cli-nodejs

HexaSync CLI is a command-line tool for building, managing, and testing HexaSync integration profiles. It provides commands for profile initialization, component generation (tasks, pullers, pushers, tables, connections, etc.), composition, and local testing.

https://github.com/hexasync-saas/hexasync-cli-nodejs/assets/103476940/4dde436b-6c83-4c32-9264-8c2cb653a4f7

## Example Template Code

- [ecwid/standalone](https://github.com/hexasync-saas/templates/tree/hexasync-demos/demos/ecwid/standalone)
- [tiktokshop-V2/ecwid](https://github.com/hexasync-saas/templates/tree/hexasync-demos/demos/tiktokshop-V2/ecwid)

## Installation

```console
npm run build-and-install
```

Or run directly during development:

```console
npm run cli -- <command> [options]
```

## Quick Start

```console
# Login to a HexaSync cluster
hexasync login hexasync.com

# Initialize a new project
hexasync profile init ./my-project

# Switch to a profile
hexasync profile set-context ./my-project/partials

# Compose the profile
hexasync compose -f ./my-project/partials
```

---

## Table of Contents

- [Commands Overview](#commands-overview)
- [login](#login)
- [version](#version)
- [profile](#profile)
  - [profile set-context](#profile-set-context)
  - [profile init](#profile-init)
  - [profile include](#profile-include)
  - [profile override](#profile-override)
  - [profile show-info](#profile-show-info)
  - [profile notifications](#profile-notifications)
- [compose](#compose)
- [task](#task)
  - [task generate](#task-generate)
  - [task regenerate](#task-regenerate)
  - [task link](#task-link)
  - [task set-keys / set-source-id / track-changes / set-visibility / set-position](#task-set-keys)
  - [task files](#task-files)
  - [task table-columns](#task-table-columns)
- [table](#table)
- [puller](#puller)
- [pusher](#pusher)
- [connection](#connection) / [dependency](#dependency) / [report](#report) / [schema](#schema) / [webhook](#webhook) / [validation](#validation) / [transformation](#transformation) / [step](#step)
- [connector](#connector)
- [worker](#worker)
- [test](#test)
- [Template Directives](#template-directives)
- [Common Errors & Guidance](#common-errors--guidance)
- [For Developers](#for-developers)

---

## Commands Overview

| Command          | Alias | Description                                                                       |
| ---------------- | ----- | --------------------------------------------------------------------------------- |
| `login`          | `l`   | Login to a HexaSync cluster                                                       |
| `version`        | `v`   | Show CLI version                                                                  |
| `profile`        | `p`   | Profile management (init, switch, include, override, show info)                   |
| `compose`        | `c`   | Compose YAML components into a single HexaSync profile template                   |
| `task`           | `ta`  | Task CRUD, linking, column management                                             |
| `table`          | `tb`  | ⚠️ **Obsolete.** Use `task table-columns` and `task set-*` commands instead       |
| `puller`         | `pl`  | Puller generation and step management                                             |
| `pusher`         | `ps`  | Pusher generation and step management                                             |
| `connection`     | `co`  | Connection generation                                                             |
| `dependency`     | `d`   | Dependency generation                                                             |
| `report`         | `r`   | ⚠️ **Obsolete.** Report generation — use `task generate --type REFERENCE` instead |
| `schema`         | `sc`  | ⚠️ **Obsolete.** Schema generation — use `task generate --type REFERENCE` instead |
| `webhook`        | `wh`  | Webhook generation, event & listener management                                   |
| `validation`     | `va`  | Validation generation                                                             |
| `transformation` | `tr`  | Transformation generation                                                         |
| `step`           | `st`  | Step generation                                                                   |
| `connector`      | `cn`  | Connector management                                                              |
| `worker`         | `w`   | Worker environment configuration                                                  |
| `test`           | `te`  | Test pull/push actions against a local worker                                     |

### Global Options

| Flag        | Description                                                                                                        |
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
| `--verbose` | Show full stack trace on errors. By default, errors display a short message with a hint to rerun with `--verbose`. |

---

## login

Login to a HexaSync cluster. Prompts for username, password, client ID, client secret, and redirect URI. Authenticates via SSO authorization code flow.

```console
hexasync login <host>
```

| Argument | Description                                        |
| -------- | -------------------------------------------------- |
| `host`   | The HexaSync cluster hostname, e.g. `hexasync.com` |

---

## version

Display the current CLI version.

```console
hexasync version
```

---

## profile

Profile management commands for initializing, switching, including, and inspecting HexaSync integration profiles.

```console
hexasync profile <subcommand>   # or: hexasync p <subcommand>
```

| Subcommand      | Alias | Description                        |
| --------------- | ----- | ---------------------------------- |
| `set-context`   | `sc`  | Switch active profile context      |
| `init`          | `in`  | Initialize a new project           |
| `include`       | `ic`  | Include files from another project |
| `override`      | `o`   | Create .override.yaml files        |
| `show-info`     | `si`  | Show entity information            |
| `notifications` | `n`   | Notification management            |

### profile set-context

Switch the active profile context. Caches all entities (tasks, pullers, pushers, reports, tables, schemas, connections) and fixes variables/task associations.

```console
hexasync profile set-context <folder>
```

| Argument | Description                |
| -------- | -------------------------- |
| `folder` | Path to the target project |

### profile init

Initialize a new HexaSync integration project. Creates the directory structure with `partials/`, `main.yaml`, `variables.yaml`, `deployment.yaml`, and sub-folders for pullers, pushers, dependencies, webhooks, reports, and objects.

```console
hexasync profile init <folder> [options]
```

| Argument | Description                |
| -------- | -------------------------- |
| `folder` | Path to the target project |

| Flag                         | Description                                 |
| ---------------------------- | ------------------------------------------- |
| `-c, --create-empty-profile` | Request HexaSync to create an empty profile |

### profile include

Include files (components) from another project into the current profile. Supports including specific entity types and enables variable key replacements or full cloning with variable overrides.

```console
hexasync profile include <folder> [options]
```

| Argument | Description                           |
| -------- | ------------------------------------- |
| `folder` | Path to the source project/components |

| Flag                | Description                                                                                                          |
| ------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `-t, --type <type>` | Entity type: `all`, `task`, `connection`, `pusher`, `dependency`, `transformation`, `validation`, `report`, `schema` |
| `-c, --clone`       | Clone/duplicate the components (prompts for variable key and value replacements)                                     |
| `-r, --replace`     | Prompt to add variable key replacements for external files                                                           |
| `-n, --name <name>` | Search components by name, e.g.: `product`, `sales order`                                                            |

### profile override

Create `.override.yaml` files for selected profile components. Copies the source component into the current profile as an override file.

```console
hexasync profile override <folder> [options]
```

| Argument | Description                           |
| -------- | ------------------------------------- |
| `folder` | Path to the source project/components |

| Flag                | Description                                       |
| ------------------- | ------------------------------------------------- |
| `-t, --type <type>` | Entity type to override (same types as `include`) |
| `-n, --name <name>` | Search components by name                         |

### profile show-info

Display detailed information about a profile entity (currently supports tasks).

```console
hexasync profile show-info [options]
```

| Flag                       | Description                                       |
| -------------------------- | ------------------------------------------------- |
| `-t, --type <entity-type>` | Entity type: `task`, `puller`, `pusher`, `report` |
| `-n, --name <entity-name>` | Entity name, e.g.: `product`, `sales order`       |

### profile notifications

Commands for generating and configuring notifications.

**`profile notifications generate`** — Generate notification components according to profile configurations.

```console
hexasync profile notifications generate [options]
```

| Flag                    | Description                                                                   |
| ----------------------- | ----------------------------------------------------------------------------- |
| `-i, --id <id>`         | The notification ID in configuration, to regenerate a specific notification   |
| `-o, --output <output>` | Output notification type: `trello`, `lark`, `email`, etc. (default: `trello`) |
| `-e, --entity <entity>` | The entity for the notification, e.g.: `Sales Orders`                         |

**`profile notifications configure-task-details`** — Preconfigure which task details are shown in a notification.

```console
hexasync profile notifications configure-task-details -i <taskId>
```

---

## compose

Compose multiple HexaSync YAML components into a single profile template. Merges all component files referenced by `main.yaml`, substitutes variables, and produces an `output.yaml` file.

```console
hexasync compose [options]
```

| Flag                         | Description                                                                     |
| ---------------------------- | ------------------------------------------------------------------------------- |
| `-f, --folder <folder_path>` | Path to the folder containing the profile (defaults to current profile)         |
| `--raw [raw]`                | Keep raw variable tokens in output instead of replacing them (default: `false`) |

**Example:**

```console
cd demos/ecwid/standalone
hexasync compose -f ./partials
```

```text
demos/
└── ecwid/
    └── standalone/
        ├── partials
        ├── local.env
        └── output.yaml
```

**Behavior:**

- Reads `main.yaml` to discover externals and component files
- Resolves `variables.yaml` and performs variable substitution (unless `--raw`)
- Inlines `!md[path]` Markdown includes per file (relative to each file) before merge
- Merges components using key/id-based deep merge strategy
- Sorts arrays by `id` for deterministic output
- Outputs `output.yaml` (or `output-raw.yaml` when `--raw`)

### compose description

Resolve **only** the `!md[...]` Markdown includes in a single YAML file — no merge, no inheritance, no variable substitution — and write the result next to it as `<file>.output.yaml`.

```console
hexasync compose description <path/to/file.yaml>   # alias: hexasync compose desc
```

Use this to preview one component with its long Markdown descriptions inlined. Placeholder tokens (e.g. `**SomeId**`) are left untouched.

---

## task

Task-related commands for generating, linking, and managing HexaSync tasks.

```console
hexasync task <subcommand>   # or: hexasync ta <subcommand>
```

| Subcommand       | Alias | Description                           |
| ---------------- | ----- | ------------------------------------- |
| `generate`       | `g`   | Generate a new task                   |
| `regenerate`     | `rg`  | Regenerate task columns               |
| `link`           | `l`   | Link task to puller/pusher/table      |
| `set-keys`       | `sk`  | Set KEY columns                       |
| `set-source-id`  | `ss`  | Set SOURCE_ID column                  |
| `track-changes`  | `tc`  | Configure change tracking             |
| `set-visibility` | `sv`  | Set column visibility                 |
| `set-position`   | `sp`  | Set column positions                  |
| `files`          | `f`   | Show related files                    |
| `table-columns`  | `tb`  | Manage table columns (`g`, `a`, `rm`) |

### task generate

Generate a new HexaSync task. Interactively creates a task, associated table, and optionally creates or links a puller and pusher.

```console
hexasync task generate [options]
```

| Flag                          | Description                                                           |
| ----------------------------- | --------------------------------------------------------------------- |
| `-n, --task-name <task-name>` | Name for the task                                                     |
| `-t, --type <type>`           | Task type: `SYNC`, `REFERENCE`, `REPORT`, `MAPPING` (default: `SYNC`) |

**Task types:**

| Type        | Description                                                           |
| ----------- | --------------------------------------------------------------------- |
| `SYNC`      | Standard synchronization task with `ignoreRemoval: true`              |
| `REFERENCE` | Reference data task (e.g., audit, lookup) with `ignoreRemoval: false` |
| `REPORT`    | Reporting task                                                        |
| `MAPPING`   | Data mapping task                                                     |

> The `--type` flag is case-insensitive: `--type sync` and `--type SYNC` are equivalent.

**Connection selection:**

During task generation, the CLI prompts for pull and push connections. The connection list includes both project connections and built-in prefixes:

| Prefix      | Description             |
| ----------- | ----------------------- |
| `None`      | No connection prefix    |
| `Audit`     | Audit-related tasks     |
| `Reference` | Reference data tasks    |
| `HexaSync`  | HexaSync internal tasks |

**Post-create columns prompt:**

After generating the task, puller, and pusher, the CLI prompts to manage table columns:

- **Generate columns from puller** — auto-generate columns from the puller's `PULL_DATA` step response filters
- **Add columns manually** — add columns interactively
- **Skip** — skip column management

**File naming convention:**

Generated file names use `__` (double underscore) to separate the connection prefix from the entity name, and `_` (single underscore) to separate name parts from the entity type suffix:

| Prefix                         | Entity Name          | Generated File                                        |
| ------------------------------ | -------------------- | ----------------------------------------------------- |
| `[Business Central > Shopify]` | `Item Bonded Stocks` | `BusinessCentral_Shopify__ItemBondedStocks_Task.yaml` |
| `[Audit]`                      | `Orphan Customers`   | `Audit__OrphanCustomers_Task.yaml`                    |
| `[Google Sheets]`              | `Excluded Products`  | `GoogleSheets__ExcludedProducts_Task.yaml`            |
| _(empty)_                      | `Item Stocks`        | `ItemStocks_Task.yaml`                                |

Variable keys follow the same convention (e.g., `BusinessCentral_Shopify__ItemBondedStocks_Task_Id`, `Audit__OrphanCustomers_Task_Table_Name`).

### task regenerate

Regenerate task columns from the puller's `PULL_DATA` step response filters.

```console
hexasync task regenerate -n <name>
```

### task link

Link a task to a puller, pusher, or table.

```console
hexasync task link [options]
```

| Flag                | Description                                    |
| ------------------- | ---------------------------------------------- |
| `-n, --name <name>` | Search task by name                            |
| `-t, --type <type>` | Entity to link: `puller`, `pusher`, or `table` |

### task set-keys

Set KEY columns for the task's related table. The commands `set-source-id`, `track-changes`, `set-visibility`, and `set-position` follow the same pattern.

```console
hexasync task set-keys -n <name>
hexasync task set-source-id -n <name>
hexasync task track-changes -n <name>
hexasync task set-visibility -n <name>
hexasync task set-position -n <name>
```

All accept `-i, --id <id>` and `-n, --name <name>`.

### task set-position

Set the display position of columns in the task's related table. Visible columns **always** have a position (required). Hidden columns have optional positions.

The auto-assign feature assigns default positions based on priority:

| Priority    | Index Group         | Description                             |
| ----------- | ------------------- | --------------------------------------- |
| 1 (highest) | `SOURCE_ID`         | Source identifier columns come first    |
| 2           | `KEYS`              | Key columns                             |
| 3           | `TRACK_FOR_CHANGES` | Change-tracked columns                  |
| 4 (lowest)  | _(other)_           | Remaining columns sorted alphabetically |

After auto-assignment, an interactive grid is displayed for manual adjustments.

### task files

Show files related to a task (task, puller, pusher, table) with paths and metadata.

```console
hexasync task files -n <name>
```

### task table-columns

Manage columns for a task's related table.

```console
hexasync task table-columns <subcommand>
```

| Subcommand | Description                                                                |
| ---------- | -------------------------------------------------------------------------- |
| `generate` | Auto-generate table columns from the puller's response filters (API steps) |
| `add`      | Add new columns to a task's table interactively                            |
| `remove`   | Remove columns from a task's table                                         |

All accept `-n, --name <name>` (and `add`/`remove` also accept `-i, --id <id>`).

> After generating, adding, or removing columns, the CLI automatically triggers the `set-position` flow to assign column positions.

---

## table

> **⚠️ Obsolete:** The `table` command is obsolete. Use `task table-columns` for column management and `task set-keys`, `task set-source-id`, `task track-changes`, `task set-visibility`, `task set-position` instead.

Table-related commands for managing columns and index groups independently (outside of a task context).

```console
hexasync table <subcommand>   # or: hexasync tb <subcommand>
```

| Subcommand         | Alias | Description                            |
| ------------------ | ----- | -------------------------------------- |
| `set-keys`         | `sk`  | Set KEY columns for a table            |
| `set-source-id`    | `ss`  | Set SOURCE_ID for a table              |
| `track-changes`    | `tc`  | Track changes for table columns        |
| `set-visibility`   | `sv`  | Set column visibility                  |
| `set-position`     | `sp`  | Set column positions                   |
| `set-index-groups` | `si`  | Add, update, or overwrite index groups |

All accept `-i, --id <id>` and `-n, --name <name>`. `set-index-groups` also accepts `-t, --type <type>` (`task`, `report`, `schema`).

---

## puller

Puller-related commands.

```console
hexasync puller <subcommand>   # or: hexasync pl <subcommand>
```

### puller generate (alias: `g`)

Generate a new HexaSync puller component.

```console
hexasync puller generate [options]
```

| Flag                                     | Description               |
| ---------------------------------------- | ------------------------- |
| `-c, --connection-name <connection>`     | Search connection by name |
| `-n, --name <name>`                      | Name of the puller        |
| `-ts, --use-time-based <use-time-based>` | Enable time-based pulling |

### puller steps generate

Generate a step for a puller (e.g., API call, SQL query). Steps sub-command alias: `s`, generate alias: `g`.

```console
hexasync puller steps generate [options]
```

| Flag                    | Description                                                     |
| ----------------------- | --------------------------------------------------------------- |
| `-n, --name <name>`     | Name of the step                                                |
| `-x, --sample <sample>` | CURL sample request or path to a file containing a CURL request |

---

## pusher

Pusher-related commands.

```console
hexasync pusher <subcommand>   # or: hexasync ps <subcommand>
```

### pusher generate (alias: `g`)

Generate a new HexaSync pusher component.

```console
hexasync pusher generate [options]
```

| Flag                                      | Description                   |
| ----------------------------------------- | ----------------------------- |
| `-t, --task-name <task-name>`             | Search for the task by name   |
| `-c, --connection-name <connection-name>` | Search for connection by name |

### pusher steps generate

Generate a step for a pusher. Same interactive flow as puller steps. Steps alias: `s`, generate alias: `g`.

```console
hexasync pusher steps generate -n <name> [-x <sample>]
```

---

## connection

```console
hexasync connection generate   # or: hexasync co g
```

Generate a new connection component.

## dependency

```console
hexasync dependency generate   # or: hexasync d g
```

Generate a new dependency component.

## report

> **⚠️ Obsolete:** The `report` command is obsolete and will not be approved. Use `task generate --type REFERENCE` for reference tasks or `task generate --type SYNC` for audit tasks instead.

```console
hexasync report <subcommand>   # or: hexasync r <subcommand>
```

| Subcommand       | Alias | Description                                      |
| ---------------- | ----- | ------------------------------------------------ |
| `generate`       | `g`   | Generate a new report component                  |
| `generate-table` | `gt`  | Generate a table for a report                    |
| `set-source-id`  | `ss`  | Set SOURCE_ID for the report's table             |
| `set-keys`       | `sk`  | Set KEY columns for the report's table           |
| `track-changes`  | `tc`  | Configure change tracking for the report's table |
| `set-visibility` | `sv`  | Set column visibility for the report's table     |

All `set-*` subcommands accept `-i, --id <id>` and `-n, --name <name>`.

## schema

> **⚠️ Obsolete:** The `schema` command is obsolete and will not be approved. Use `task generate --type REFERENCE` for reference tasks or `task generate --type SYNC` for audit tasks instead.

```console
hexasync schema <subcommand>   # or: hexasync sc <subcommand>
```

| Subcommand       | Alias | Description                                      |
| ---------------- | ----- | ------------------------------------------------ |
| `generate`       | `g`   | Generate a new schema component                  |
| `regenerate`     | `rg`  | Regenerate schema columns                        |
| `set-source-id`  | `ss`  | Set SOURCE_ID for the schema's table             |
| `set-keys`       | `sk`  | Set KEY columns for the schema's table           |
| `track-changes`  | `tc`  | Configure change tracking for the schema's table |
| `set-visibility` | `sv`  | Set column visibility for the schema's table     |

All `set-*` subcommands accept `-i, --id <id>` and `-n, --name <name>`.

## webhook

```console
hexasync webhook <subcommand>   # or: hexasync wh <subcommand>
```

| Subcommand     | Alias | Description                      |
| -------------- | ----- | -------------------------------- |
| `generate`     | `g`   | Generate a new webhook component |
| `add-event`    | `ae`  | Add an event to a webhook        |
| `add-listener` | `al`  | Add a listener to a webhook      |

## validation

```console
hexasync validation generate   # or: hexasync va g
```

Generate a new validation component.

## transformation

```console
hexasync transformation generate   # or: hexasync tr g
```

Generate a new transformation component.

## step

```console
hexasync step generate   # or: hexasync st g
```

Generate a new step component (standalone, outside of puller/pusher context).

---

## connector

Commands for managing connectors.

```console
hexasync connector create   # or: hexasync cn c
```

Create a new connector interactively. Prompts for name, connector ID (UUID), full name, description, and slug. Saves to the global connector configuration file.

---

## worker

Commands for configuring the HexaSync Worker development environment.

### worker set-context

Set a profile and configuration location for testing with a local HexaSync Worker. Updates the worker's `.env` file with the selected profile ID, database name, storage path, and development-mode environment variables.

```console
hexasync worker set-context --worker <workerPath> --profile <profileName>
# or: hexasync w sc --worker <workerPath> --profile <profileName>
```

| Flag                      | Description                     |
| ------------------------- | ------------------------------- |
| `--worker <workerPath>`   | Path to the worker directory    |
| `--profile <profileName>` | Profile name or alias to search |

Behavior: Reads `profiles.yaml` from the worker directory, uses fuzzy search to match profiles by alias, and updates `.env` in `<workerPath>/hexasync.api/` with `HEXASYNC_PROFILE_ID`, `HEXASYNC_DB_NAME`, `HEXASYNC_PROFILES_STORAGE`, and development-mode flags.

---

## test

Test pull/push actions against a local HexaSync Worker instance.

```console
hexasync test <type> [options]   # or: hexasync te <type>
```

| Argument | Description                                                 |
| -------- | ----------------------------------------------------------- |
| `type`   | Action type to test: `pull`, `push`, `enqueue`, `transform` |

| Flag                           | Description                                                        |
| ------------------------------ | ------------------------------------------------------------------ |
| `-i, --task-id <taskId>`       | Task ID (at least one of `--task-id` or `--task-name` is required) |
| `-n, --task-name <taskName>`   | Task name. Use `*` for all tasks                                   |
| `-p, --profile-id <profileId>` | Profile ID                                                         |
| `-w, --worker-url <workerUrl>` | Worker URL (default: `http://localhost:4004`)                      |

**Examples:**

```console
hexasync test pull -n "Product"
hexasync test pull -n "*"             # all tasks
hexasync test pull -i "abc-123" -w "http://localhost:5000"
```

> **Note:** Currently only the `pull` action type is implemented.

---

## Template Directives

Beside properties of [`ProfileDefinition`](https://github.com/hexasync-saas/hexasync.libraries/blob/main/src/hexasync.profiles.definitions/Profile/ProfileDefinition.cs), there are directives defined by the Composer for serving features. These directives are used in compose-time only, not included in the final code.

## `usings`

- Define using which code in `official-templates`

```yaml
# template: demos/tiktokshop-V2/ecwid/partials/usings.yaml

usings:
  - key: tiktokshop-V2
    type: OFFLINE
    metadata:
      type: FOLDER
      path: /tiktokshop-V2/partials
      filePathFilterPattern:
        flags: i
        exclude: (StockDataPusher|Utility|Delete|UpdateDeliveredPusher)
  - key: ecwid
    type: OFFLINE
    metadata:
      type: FOLDER
      path: /ecwid/partials
      filePathFilterPattern:
        flags: i
        exclude: (Stock|OrderStatus)
  - key: generic
    type: OFFLINE
    metadata:
      type: FOLDER
      path: /generic/partials
  - key: hexasync
    type: OFFLINE
    metadata:
      type: FOLDER
      path: /hexasync/partials
```

## `variables`

- Supported define variables locally inside any files, no need of global preserved `variables.yaml` files. These code will be hoisted in compose-time

```yaml
# templates: demos/tiktokshop-V2/ecwid/partials/components/compositions/transformations/Order/SalesOrder/SalesOrderTrackingInformationEcwidToTikTokShopTransformation.yaml

variables:
  '**SalesOrderTrackingInformationEcwidToTikTokShopTransformationObjectId**': '236eab02-5358-4720-a2b2-a0467d8b7ff8'

objectAssociations:
  '**EcwidOrderTrackingInformationDataObjectId**':
    pusher:
      id: '**TikTokShopShipPackagePusherId**' # Defined in `official-templates: tiktokshop-V2/partials/tasks/variables/common/Order/SalesOrder.yaml`

startupTasks:
  - key: ENABLE_ORDER_TRACKING_INFORMATION_SYNC_ECWID_TO_TIKTOKSHOP
    targetType: SCHEDULER
    targetId: '**EcwidOrderTrackingInformationDataObjectId**'
    metadata:
      scheduler_expression: '0/15 * * ? * * *'
      is_enabled: true
      is_running: true
```

## `validators`

- Same concept as `validations` in `ProfileDefinition`. But the syntax provide way to refactor
- In final code, will be composed to `validations`

```yaml
# templates: demos/tiktokshop-V2/ecwid/partials/components/compositions/transformations/Product/ProductEcwidToTikTokShopTransformation.yaml

variables:
  '**EcwidProductDataValidatorId**': '9729074e-de61-4e80-8a9f-0c3f9bca5dd1'

validators:
  - id: '**EcwidProductDataValidatorId**'
    usings:
      # Defined in `official-templates`, not `templates`, because `TikTokShopActiveProductDataPusher` require Product data to satisfy the same validations
      # Below define `columns` for mapping the correct name defined in TikTokShop validator to be Ecwid property name
      # See the `official-templates` code below
      - '**TikTokShopActiveProductDataPusherValidatorId**'
    columns:
      - id: 4bbfcb53-e172-4426-b3cb-5627ebb323b0
        metadata:
          field_name: sku
      - id: 0cb420ec-b14e-4cdb-8e1d-3dd0e89dd398
        metadata:
          field_name: name
    # ... and more ...

objectAssociations:
  '**EcwidProductDataObjectId**':
    pusher:
      id: '**TikTokShopActiveProductDataPusherId**'
    validator:
      id: '**EcwidProductDataValidatorId**'
```

```yaml
# official-templates: tiktokshop-V2/partials/pushers/Product/TikTokShopActiveProductDataPusher.yaml

validators:
  - id: '**TikTokShopActiveProductDataPusherValidatorId**'
    columns:
      - id: 4bbfcb53-e172-4426-b3cb-5627ebb323b0
        type: NOT_EMPTY
        metadata:
          field_name: seller_sku
      - id: 0cb420ec-b14e-4cdb-8e1d-3dd0e89dd398
        type: MIN_LENGTH
        metadata:
          field_name: product_name
          value: '25'
    # ... and more ...
```

```yaml
# template output: demos/tiktokshop-V2/ecwid/output.yaml

validations:
  4e857bc8-78ed-4e17-aebd-fab5fedebae2:
    - id: 4bbfcb53-e172-4426-b3cb-5627ebb323b0
      type: NOT_EMPTY
      metadata:
        field_name: sku
      index: 0
    - id: 0cb420ec-b14e-4cdb-8e1d-3dd0e89dd398
      type: MIN_LENGTH
      metadata:
        field_name: name
        value: '25'
```

## `customs`

- Use to create custom component from existing `ProfileDefinition` property and Composer directives (HOC pattern)
- FEATURE IS IN DEVELOPMENT...

---

## Common Errors & Guidance

## YAMLParseError: Map keys must be unique at line 97, column 1

1. Check if any `key`, `id`, `GUID` defined is duplicated. Common case is declare PullerId/ObjectId/PusherId copy/paste but forgot to generate random UUID
2. Check if in a single file, declare duplicate fields, i.e: `objects`, `pullers`, ...

```yaml
objects:
  - id: '**EcwidProductDataObjectId**'
    ignoreRemoval: true
    dependencies:
      IMAGE:
        dependedOn: '**ProductImageEcwidToTikTokShopTransformationObjectId**'
        type: KEYS
        data:
          nullable: false
          constraints:
            - synced
          keys:
            product_id: product_id

objects:
  - id: '**ProductEcwidToTikTokShopTransformationObjectId**'
    valueTableName: '**ProductEcwidToTikTokShopTransformationObjectTableName**'
    name: '**ProductEcwidToTikTokShopTransformationObjectName**'
    ignoreRemoval: true
```

## TypeError: Cannot read properties of undefined (reading 'filter')

Check if current folder contain reserved folder `partials`

---

## For Developers

## Debugging

```console
npm run debugger:sample-template # Using `mocks/sample-template`
npm run debugger:real-template # Path to specific `templates` folder
```

## Merge mechanism based entirely on `id`/`key` of Array/Object

- For `key`, user has inputed into
- For `id`, DO NOT CODE IN COMPOSER TO AUTOGENERATE `uuid` FOR IT.

## Useful Breakpoints

### DeepMergeHelper.ts > `if (typeof sourceElem !== "object")`

```js
sourceElem?.id == '**EcwidProductDataPullerId**';
```

### compose.ts > `_convertTemplateToProfile()`

```js
key === '<template/profile key name>';
```

## CLI Design

### Primary

- [Building a TypeScript CLI with Commander](https://blog.logrocket.com/building-typescript-cli-node-js-commander/)

### Secondary

- [Creating a CLI tool with Node.js](https://blog.logrocket.com/creating-a-cli-tool-with-node-js/)

### Currently choose "Caught Exceptions"/"Uncaught Exceptions" before run the script will cause debugger to be hang
