import {Meta, Source} from '@storybook/addon-docs/blocks';
import '../styles/shared.css';

<Meta title="Guide Du Dev/Migration/Depuis Bridge (Vue3)"/>


<div className="header">
  <h1>Migrer de Bridge (Vue3) vers Synapse</h1>
</div>

> **Nouveau Starter Kit** — depuis sa dernière version, le Starter Kit Synapse (`sksn_x`) est une application **Vue 3 + Vite** (SPA). Il n'utilise **plus Nuxt**. La structure de projet, le routeur, la configuration et le chargement des styles décrits ci-dessous suivent cette nouvelle stack.

## 1 - Commencer la migration

- Téléchargez la stack de migration [Starter Kit Synapse](https://gitlab.cnqd.cnamts.fr/human/developpement/sksn_x).

- Transférez les pages de votre projet du Starter Kit Bridge dans le dossier `src/views/` du projet Starter Kit Synapse&nbsp;; les composants peuvent être placés dans le dossier `src/components/`.

- Identifier les dépendances à conserver dans la nouvelle version.
Le package `@cnamts/synapse-bridge` a été remplacé par `@cnamts/synapse`.

### Styles globaux

Il n'y a plus de `nuxt.config.ts`. Les styles globaux sont importés directement dans le point d'entrée `src/main.ts` :

<Source dark language="ts" code={`
// src/main.ts
import 'vuetify/styles'
import '@cnamts/synapse/synapse.css'
import './assets/styles/index.scss' // vos styles globaux
`}
/>

### Variables de configuration

Deux mécanismes remplacent le `runtimeConfig` de Nuxt :

**1. Variables de build (Vite)** — exposées via `import.meta.env`. La version du projet est par exemple injectée depuis le `package.json` dans `vite.config.ts` :

<Source dark language="ts" code={`
// vite.config.ts
import { version } from './package.json'

process.env = Object.assign(process.env, {
  VITE_APP_VERSION: version,
})
`}
/>

<Source dark language="ts" code={`
// usage dans le code
console.log(import.meta.env.VITE_APP_VERSION)
`}
/>

**2. Variables d'exécution (runtime)** — un fichier JSON chargé au démarrage, modifiable **sans rebuild** (déploiement). Il est chargé dans `src/main.ts` puis fourni à l'application via une `InjectionKey`, en remplacement du `$config.public` de Nuxt :

<Source dark language="ts" code={`
// src/var.env.ts
import type { InjectionKey } from 'vue'

export type Config = {
  title: string
  message: string
  // ... vos variables
}

export const CONFIG_SYMBOL = Symbol('config') as InjectionKey<Config>
`}
/>

<Source dark language="ts" code={`
// src/main.ts
import { CONFIG_SYMBOL, type Config } from './var.env'

// le chemin du JSON est défini dans .env.development / .env.production
const res = await fetch(import.meta.env.VITE_JSON_FILE_NAME)
const config = (await res.json()) as Config

const app = createApp(App)
app.provide(CONFIG_SYMBOL, config)
`}
/>

Pour utiliser ces variables dans un composant, on les récupère avec `inject` (Composition API) :

<Source dark language="vue" code={`
<script setup lang="ts">
import { inject } from 'vue'
import { CONFIG_SYMBOL, type Config } from '@/var.env'

const config = inject(CONFIG_SYMBOL) as Config
</script>

<template>
  <div>{{ config.title }}</div>
</template>
`}
/>

## 2 - Migration du routeur

Il n'y a plus de routing automatique basé sur le dossier `pages/` (Nuxt). Le projet utilise désormais **Vue Router** déclaré explicitement dans `src/router/index.ts` :

<Source dark language="ts" code={`
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', name: 'index', component: HomeView },
    { path: '/home', name: 'home', component: HomeView },
    // ... vos routes
  ],
})

export default router
`}
/>

Le routeur est ensuite enregistré dans `src/main.ts` (`app.use(router)`), et `<RouterView />` est placé dans `App.vue`.

Voir le [guide de migration de vue-router](https://router.vuejs.org/guide/migration/) pour plus d'informations.

## 3 - Migration des stores VueX vers Pinia

Le Starter Kit utilise **Pinia** (enregistré dans `src/main.ts` via `app.use(createPinia())`).

Prenons un exemple de store Vuex :

<Source dark code={`
// Ancien store Vuex (store/index.js)
import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 0,
    user: null,
  },
  mutations: {
    increment(state) {
      state.count++
    },
    setUser(state, user) {
      state.user = user
    }
  },
  actions: {
    async fetchUser({ commit }) {
      const user = await fetch('/api/user').then(res => res.json())
      commit('setUser', user)
    }
  },
  getters: {
    isAuthenticated: state => !!state.user,
  }
})
`}
/>

Nouvelle version avec Pinia :

<Source dark code={`
// stores/counter.ts
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    user: null as null | { name: string; email: string }
  }),
  actions: {
    increment() {
      this.count++
    },
    async fetchUser() {
      const user = await fetch('/api/user').then(res => res.json())
      this.user = user
    }
  },
  getters: {
    isAuthenticated: (state) => !!state.user,
  }
})
`}
/>

Différences majeures entre Vuex et Pinia :
-	Plus besoin de mutations → On modifie l’état directement !
-	Les getters et actions sont dans le même objet
-	Plus léger et plus performant

Utilisation du store dans les composants Vue :

<Source dark code={`
// Avec Vuex
<script setup>
import { useStore } from 'vuex'
const store = useStore()

store.commit('increment')
console.log(store.state.count)
</script>
`}
/>

<Source dark code={`
// Avec Pinia
<script setup>
import { useCounterStore } from '@/stores/counter'
const counterStore = useCounterStore()

counterStore.increment()
console.log(counterStore.count)
</script>
`}
/>

Nb : pour la persistance des données vous pouvez utiliser le plugin [pinia-plugin-persistedstate](https://prazdevs.github.io/pinia-plugin-persistedstate/).

## 4 - Migration de la syntaxe des composants

La grande différence entre la version Bridge et la version Synapse est la syntaxe des composants qui passe de l'option API à la composition API.
Voir la documentation sur la composition API [ici](https://vuejs.org/guide/extras/composition-api-faq.html).

Vue 3 introduit la Composition API qui offre plusieurs avantages :

- Meilleure organisation du code pour les projets complexes
- Réutilisation facile avec des fonctions composables
- Meilleure performance grâce à une gestion plus optimisée du rendu
- Meilleur support TypeScript

L'Option API et la Composition API peuvent coexister dans un même projet, mais il est recommandé d'utiliser la composition API pour de meilleures performances et une meilleure organisation du code.

### 4.1 - Migration des `data()`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return {
      count: 0,
      user: {
        name: 'John Doe',
        age: 30
      }
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, reactive } from 'vue'

const count = ref(0)
const user = reactive({ name: 'John Doe', age: 30 })
</script>
`}
/>

### 4.2 Migration des `methods`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 0 }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref } from 'vue'

const count = ref(0)
const increment = () => count.value++
</script>
`}
/>

### 4.3 Migration des `computed`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 5 }
  },
  computed: {
    doubleCount() {
      return this.count * 2
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, computed } from 'vue'

const count = ref(5)
const doubleCount = computed(() => count.value * 2)
</script>
`}
/>

### 4.4 Migration des `watch`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  data() {
    return { count: 0 }
  },
  watch: {
    count(newValue, oldValue) {
      console.log('Count changed', oldValue, '->', newValue)
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newValue, oldValue) => {
  console.log('Count changed', oldValue, '->', newValue)
})
</script>
`}
/>

`watch()` fonctionne directement sur une variable réactive.

### 4.5 - Migration des Hooks de cycle de vie

Avant (Options API) :

<Source dark code={`
<script>
export default {
  created() {
    console.log('Component created')
  },
  mounted() {
    console.log('Component mounted')
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
import { onMounted, onBeforeMount } from 'vue'

onBeforeMount(() => {
  console.log('Component will be created')
})

onMounted(() => {
  console.log('Component mounted')
})
</script>
`}
/>

On remplace les hooks par `onMounted()`, `onBeforeMount()`, etc.

### 4.6 - Migration des `props`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  props: {
    msg: String
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
const props = defineProps({
  msg: String
})
</script>
`}
/>

### 4.7 - Migration des `emits`

Avant (Options API) :

<Source dark code={`
<script>
export default {
  methods: {
    handleClick() {
      this.$emit('clicked')
    }
  }
}
</script>
`}
/>

Après (Composition API) :

<Source dark code={`
<script setup>
const emit = defineEmits(['clicked'])

const handleClick = () => {
  emit('clicked')
}
</script>
`}
/>
