# 🚀 Getting started with Strapi

Strapi comes with a full featured [Command Line Interface](https://docs.strapi.io/dev-docs/cli) (CLI) which lets you scaffold and manage your project in seconds.

### `develop`

Start your Strapi application with autoReload enabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-develop)

```
npm run develop
# or
yarn develop
```

### `start`

Start your Strapi application with autoReload disabled. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-start)

```
npm run start
# or
yarn start
```

### `build`

Build your admin panel. [Learn more](https://docs.strapi.io/dev-docs/cli#strapi-build)

```
npm run build
# or
yarn build
```

## 🔌 Plugin: custom-snowflake-syncer

Il plugin `custom-snowflake-syncer` (in `src/plugins/custom-snowflake-syncer`) usa l'SDK ufficiale `snowflake-sdk` per sincronizzare gli eventi di scrittura/cancellazione Strapi verso una tabella Snowflake.

### Schema tabella Snowflake

```sql
CREATE TABLE RAW_ESG_EVENTS (
  INGESTED_AT   TIMESTAMP_NTZ(9) DEFAULT CURRENT_TIMESTAMP(),
  SOURCE_SYSTEM VARCHAR,   -- es. 'STRAPI' (da config.sourceSystem)
  ENTITY_TYPE   VARCHAR,   -- UID del content-type Strapi
  NATURAL_KEY   VARCHAR,   -- documentId Strapi
  PAYLOAD       VARIANT,   -- documento JSON completo
  PAYLOAD_HASH  VARCHAR,   -- MD5 del payload JSON
  USER_ACTION   VARCHAR    -- POST | PUT | DELETE
);
```

### Query di inserimento

```sql
INSERT INTO <database>.<schema>.<table>
  (SOURCE_SYSTEM, ENTITY_TYPE, NATURAL_KEY, PAYLOAD, PAYLOAD_HASH, USER_ACTION)
SELECT
  :1 AS source_system,
  :2 AS entity_type,
  :3 AS natural_key,
  TRY_PARSE_JSON(:4) AS payload,
  MD5(:5) AS payload_hash,
  :6 AS user_action;
```

> **Nota:** l'SDK `snowflake-sdk` Node.js richiede la sintassi `:1, :2, …` per i bind posizionali. Il placeholder `?` (Python/JDBC) non è supportato.

### Architettura della sync

La sincronizzazione avviene tramite un **unico middleware** registrato al livello `strapi.documents.use()` in `register.js`. Questo layer è comune a tutti i percorsi di scrittura:

| Percorso | Sync attiva |
|---|---|
| UI Strapi (Content Manager) | ✅ |
| Chiamate REST `/api/...` | ✅ |
| Chiamate dirette ai Strapi service | ✅ |

Per ogni operazione POST/PUT il middleware ri-fetcha il documento via `strapi.db.query().findOne()` con le relazioni configurate, così il payload inviato a Snowflake contiene sempre i dati completi e non `{ count: N }`.

### Configurazione `contentsToSync`

Ogni entry in `config.contentsToSync` (in `config/plugins.js`) supporta:

| Campo | Tipo | Uso |
|---|---|---|
| `element` | `string` | UID del content-type Strapi |
| `actions` | `string[]` | `'POST'`, `'PUT'`, `'DELETE'` |
| `findOptions` | `object` | Opzioni per `strapi.documents().findMany()` nel **full sync** |
| `dbPopulate` | `true \| object` | Populate per `strapi.db.query().findOne()` nel **real-time** |

#### Esempio con relazioni annidate

```js
{
  element: 'plugin::custom-esg-indicators-tracing.indicator',
  actions: ['POST', 'PUT', 'DELETE'],
  // Per il full sync (strapi.documents().findMany)
  findOptions: {
    populate: {
      versions: {
        populate: { sdg: true },
      },
    },
  },
  // Per il real-time refetch (strapi.db.query().findOne)
  dbPopulate: {
    versions: {
      populate: { sdg: true },
    },
  },
}
```

> **Nota per i componenti ripetibili:** per popolare relazioni dentro un componente occorre sempre la chiave `populate` annidata — es. `versions: { populate: { sdg: true } }`. Senza `populate`, Strapi non scende nel componente.

### Full sync manuale

```
POST /api/custom-snowflake-syncer/sync
```

Itera tutti i content-type configurati con azione `POST` e inserisce tutti i record come eventi di creazione.

### Variabili d'ambiente richieste

Aggiungere al file `.env`:

```
SNOWFLAKE_ACCOUNT=...
SNOWFLAKE_USERNAME=...
SNOWFLAKE_PASSWORD=...
SNOWFLAKE_WAREHOUSE=...
SNOWFLAKE_DATABASE=...
SNOWFLAKE_SCHEMA=RAW
SNOWFLAKE_ROLE=...
SNOWFLAKE_TABLE=RAW_ESG_EVENTS
SNOWFLAKE_SOURCE_SYSTEM=STRAPI   # opzionale, default: 'STRAPI'
```

### File `snowflake.log`

L'SDK `snowflake-sdk` tenta di scrivere un file `snowflake.log` nella directory radice del Backend. Questo file è **disabilitato** tramite la configurazione in `service.js`:

```js
snowflake.configure({ logLevel: 'OFF' });
```

Tutti i log rilevanti (connessione, query, errori) vengono scritti direttamente dal logger di Strapi.

---

## ⚙️ Deployment

Strapi gives you many possible deployment options for your project including [Strapi Cloud](https://cloud.strapi.io). Browse the [deployment section of the documentation](https://docs.strapi.io/dev-docs/deployment) to find the best solution for your use case.

```
yarn strapi deploy
```

## 📚 Learn more

- [Resource center](https://strapi.io/resource-center) - Strapi resource center.
- [Strapi documentation](https://docs.strapi.io) - Official Strapi documentation.
- [Strapi tutorials](https://strapi.io/tutorials) - List of tutorials made by the core team and the community.
- [Strapi blog](https://strapi.io/blog) - Official Strapi blog containing articles made by the Strapi team and the community.
- [Changelog](https://strapi.io/changelog) - Find out about the Strapi product updates, new features and general improvements.

Feel free to check out the [Strapi GitHub repository](https://github.com/strapi/strapi). Your feedback and contributions are welcome!

## ✨ Community

- [Discord](https://discord.strapi.io) - Come chat with the Strapi community including the core team.
- [Forum](https://forum.strapi.io/) - Place to discuss, ask questions and find answers, show your Strapi project and get feedback or just talk with other Community members.
- [Awesome Strapi](https://github.com/strapi/awesome-strapi) - A curated list of awesome things related to Strapi.

---

<sub>🤫 Psst! [Strapi is hiring](https://strapi.io/careers).</sub>
