@cat-factory/app 0.101.0 → 0.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,11 @@
6
6
  // they succeed only on the local facade (elsewhere the backend returns a clear error surfaced as
7
7
  // a toast). Renders inline inside the Infrastructure window's "Shared stacks" tab.
8
8
  import { computed, reactive, ref } from 'vue'
9
- import type { SharedStack, SharedStackStatus } from '~/types/sharedStacks'
9
+ import type {
10
+ SharedStack,
11
+ SharedStackRecommendation,
12
+ SharedStackStatus,
13
+ } from '~/types/sharedStacks'
10
14
 
11
15
  const { t } = useI18n()
12
16
  const store = useSharedStacksStore()
@@ -16,6 +20,7 @@ const { confirmAction, toastDone } = useConfirmAction()
16
20
  const stacks = computed(() => store.stacks)
17
21
  const busyId = ref<string | null>(null)
18
22
  const saving = ref(false)
23
+ const detecting = ref(false)
19
24
  // null ⇒ the form is in "add" mode; a stack id ⇒ editing that stack's definition in place.
20
25
  const editingId = ref<string | null>(null)
21
26
 
@@ -23,12 +28,20 @@ const form = reactive({
23
28
  name: '',
24
29
  cloneUrl: '',
25
30
  gitRef: '',
31
+ // Subdirectory the compose stack lives in (monorepo) — a detect-time hint only, NOT persisted:
32
+ // the resolved `composeFiles` already carry the prefix. Absent ⇒ the repo root is scanned.
33
+ directory: '',
26
34
  composeFiles: '',
27
35
  composeProfiles: '',
28
36
  managedNetworks: '',
29
37
  allowHostCommands: false,
30
38
  })
31
39
 
40
+ // Env/config templates (`*-dist` → gitignored target) the autodetect scan surfaced. The form has no
41
+ // editor for them, so we carry the detected (or, on edit, the stack's existing) set through to the
42
+ // save payload rather than silently dropping them — they're materialized before `up`.
43
+ const detectedEnvFiles = ref<SharedStack['envFiles']>([])
44
+
32
45
  /** Status → badge colour. */
33
46
  const STATUS_COLOR: Record<SharedStackStatus, 'neutral' | 'warning' | 'success' | 'error'> = {
34
47
  stopped: 'neutral',
@@ -72,10 +85,12 @@ function resetForm() {
72
85
  form.name = ''
73
86
  form.cloneUrl = ''
74
87
  form.gitRef = ''
88
+ form.directory = ''
75
89
  form.composeFiles = ''
76
90
  form.composeProfiles = ''
77
91
  form.managedNetworks = ''
78
92
  form.allowHostCommands = false
93
+ detectedEnvFiles.value = []
79
94
  }
80
95
 
81
96
  /** Load a stack's definition into the form for in-place editing. */
@@ -84,10 +99,59 @@ function startEdit(stack: SharedStack) {
84
99
  form.name = stack.name
85
100
  form.cloneUrl = stack.cloneUrl
86
101
  form.gitRef = stack.gitRef ?? ''
102
+ form.directory = ''
87
103
  form.composeFiles = stack.composeFiles.join(', ')
88
104
  form.composeProfiles = stack.composeProfiles.join(', ')
89
105
  form.managedNetworks = stack.managedNetworks.join(', ')
90
106
  form.allowHostCommands = stack.allowHostCommands
107
+ // Preserve the stack's existing env templates so a save (or a later re-detect) doesn't drop them.
108
+ detectedEnvFiles.value = stack.envFiles
109
+ }
110
+
111
+ const canDetect = computed(() => Boolean(form.cloneUrl.trim()) && !detecting.value)
112
+
113
+ /**
114
+ * Read the repo at the entered clone URL (checkout-free, via the workspace's VCS connection) and
115
+ * PREFILL the compose-shaped fields from the recommendation. Non-binding: the user reviews + edits
116
+ * before saving. A SUCCESSFUL detection is authoritative for the compose-shaped fields — it
117
+ * overwrites them wholesale, including clearing a field the scan found empty (so re-detecting a
118
+ * different repo can't leave a stale managed network / profile behind). Manual entries survive only
119
+ * a `detected:false` result, which returns early and touches nothing. The name is suggested only
120
+ * when still blank (it's a user label, not a repo-derived fact).
121
+ */
122
+ async function autodetect() {
123
+ detecting.value = true
124
+ try {
125
+ const rec = await store.detect({
126
+ cloneUrl: form.cloneUrl.trim(),
127
+ ...(form.gitRef.trim() ? { gitRef: form.gitRef.trim() } : {}),
128
+ ...(form.directory.trim() ? { directory: form.directory.trim() } : {}),
129
+ })
130
+ if (!rec.detected) {
131
+ toast.add({
132
+ title: t('settings.sharedStacks.detect.nothing'),
133
+ description: rec.notes[0]?.message ?? '',
134
+ icon: 'i-lucide-info',
135
+ color: 'warning',
136
+ })
137
+ return
138
+ }
139
+ if (rec.name && !form.name.trim()) form.name = rec.name
140
+ form.composeFiles = rec.composeFiles.join(', ')
141
+ form.composeProfiles = rec.composeProfiles.join(', ')
142
+ form.managedNetworks = rec.managedNetworks.join(', ')
143
+ detectedEnvFiles.value = rec.envFiles
144
+ toast.add({
145
+ title: t('settings.sharedStacks.detect.detected'),
146
+ description: t('settings.sharedStacks.detect.detectedBody'),
147
+ icon: 'i-lucide-wand-sparkles',
148
+ color: 'success',
149
+ })
150
+ } catch (e) {
151
+ notifyError(t('settings.sharedStacks.detect.failed'), e)
152
+ } finally {
153
+ detecting.value = false
154
+ }
91
155
  }
92
156
 
93
157
  function notifyError(title: string, e: unknown) {
@@ -110,6 +174,7 @@ async function saveStack() {
110
174
  composeFiles: tokens(form.composeFiles),
111
175
  composeProfiles: tokens(form.composeProfiles),
112
176
  managedNetworks: tokens(form.managedNetworks),
177
+ envFiles: detectedEnvFiles.value,
113
178
  allowHostCommands: form.allowHostCommands,
114
179
  }
115
180
  try {
@@ -300,6 +365,42 @@ async function remove(stack: SharedStack) {
300
365
  />
301
366
  </UFormField>
302
367
 
368
+ <UFormField
369
+ :label="t('settings.sharedStacks.add.directory')"
370
+ :help="t('settings.sharedStacks.add.directoryHelp')"
371
+ >
372
+ <UInput
373
+ v-model="form.directory"
374
+ placeholder="shared"
375
+ class="w-full"
376
+ data-testid="shared-stack-directory"
377
+ />
378
+ </UFormField>
379
+
380
+ <div class="flex items-center gap-2">
381
+ <UButton
382
+ icon="i-lucide-wand-sparkles"
383
+ size="sm"
384
+ variant="soft"
385
+ :loading="detecting"
386
+ :disabled="!canDetect"
387
+ data-testid="shared-stack-autodetect"
388
+ @click="autodetect"
389
+ >
390
+ {{ t('settings.sharedStacks.detect.button') }}
391
+ </UButton>
392
+ <span class="text-[11px] text-slate-500">{{ t('settings.sharedStacks.detect.hint') }}</span>
393
+ </div>
394
+
395
+ <p
396
+ v-if="detectedEnvFiles.length"
397
+ class="text-[11px] text-slate-500"
398
+ data-testid="shared-stack-env-files"
399
+ >
400
+ {{ t('settings.sharedStacks.detect.envFiles') }}
401
+ {{ detectedEnvFiles.map((f) => `${f.template} → ${f.target}`).join(', ') }}
402
+ </p>
403
+
303
404
  <UFormField
304
405
  :label="t('settings.sharedStacks.add.composeFiles')"
305
406
  :help="t('settings.sharedStacks.add.composeFilesHelp')"
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  createSharedStackContract,
3
3
  deleteSharedStackContract,
4
+ detectSharedStackContract,
4
5
  ensureSharedStackUpContract,
5
6
  listSharedStacksContract,
6
7
  teardownSharedStackContract,
7
8
  updateSharedStackContract,
8
9
  } from '@cat-factory/contracts'
9
- import type { UpdateSharedStackInput } from '~/types/sharedStacks'
10
+ import type { DetectSharedStackInput, UpdateSharedStackInput } from '~/types/sharedStacks'
10
11
  import type { SendParams } from './client'
11
12
  import type { ApiContext } from './context'
12
13
 
@@ -23,6 +24,9 @@ export function sharedStacksApi({ send, ws }: ApiContext) {
23
24
  createSharedStack: (workspaceId: string, body: CreateSharedStackBody) =>
24
25
  send(createSharedStackContract, { pathPrefix: ws(workspaceId), body }),
25
26
 
27
+ detectSharedStack: (workspaceId: string, body: DetectSharedStackInput) =>
28
+ send(detectSharedStackContract, { pathPrefix: ws(workspaceId), body }),
29
+
26
30
  updateSharedStack: (workspaceId: string, stackId: string, body: UpdateSharedStackInput) =>
27
31
  send(updateSharedStackContract, {
28
32
  pathPrefix: ws(workspaceId),
@@ -1,6 +1,10 @@
1
1
  import { defineStore } from 'pinia'
2
2
  import { ref } from 'vue'
3
- import type { SharedStack, UpdateSharedStackInput } from '~/types/sharedStacks'
3
+ import type {
4
+ DetectSharedStackInput,
5
+ SharedStack,
6
+ UpdateSharedStackInput,
7
+ } from '~/types/sharedStacks'
4
8
  import { useWorkspaceStore } from '~/stores/workspace'
5
9
 
6
10
  /**
@@ -34,6 +38,11 @@ export const useSharedStacksStore = defineStore('sharedStacks', () => {
34
38
  return created
35
39
  }
36
40
 
41
+ async function detect(input: DetectSharedStackInput) {
42
+ const ws = useWorkspaceStore()
43
+ return api.detectSharedStack(ws.requireId(), input)
44
+ }
45
+
37
46
  async function update(stackId: string, patchInput: UpdateSharedStackInput) {
38
47
  const ws = useWorkspaceStore()
39
48
  const updated = await api.updateSharedStack(ws.requireId(), stackId, patchInput)
@@ -61,5 +70,5 @@ export const useSharedStacksStore = defineStore('sharedStacks', () => {
61
70
  return updated
62
71
  }
63
72
 
64
- return { stacks, hydrate, create, update, remove, ensureUp, teardown }
73
+ return { stacks, hydrate, create, detect, update, remove, ensureUp, teardown }
65
74
  })
@@ -5,4 +5,6 @@ export type {
5
5
  SharedStackStatus,
6
6
  CreateSharedStackInput,
7
7
  UpdateSharedStackInput,
8
+ DetectSharedStackInput,
9
+ SharedStackRecommendation,
8
10
  } from '@cat-factory/contracts'
@@ -530,6 +530,8 @@
530
530
  "cloneUrl": "Clone-URL des Repositorys",
531
531
  "cloneUrlHelp": "Das Git-Repository, in dem die Compose-Dateien des Stacks liegen.",
532
532
  "gitRef": "Branch oder Tag (optional)",
533
+ "directory": "Unterverzeichnis (optional)",
534
+ "directoryHelp": "Wird nur von der automatischen Erkennung verwendet: das Monorepo-Unterverzeichnis, in dem der Compose-Stack liegt.",
533
535
  "composeFiles": "Compose-Dateien",
534
536
  "composeFilesHelp": "Kommagetrennt, repo-relativ, in Override-Reihenfolge.",
535
537
  "composeProfiles": "Compose-Profile (optional)",
@@ -538,6 +540,15 @@
538
540
  "allowHostCommands": "Host-Command-Setup-Schritte erlauben",
539
541
  "save": "Stack hinzufügen"
540
542
  },
543
+ "detect": {
544
+ "button": "Automatisch erkennen",
545
+ "hint": "Das Repository lesen und Compose-Dateien, Profile und Netzwerke vorausfüllen.",
546
+ "detected": "Stack-Konfiguration erkannt",
547
+ "detectedBody": "Aus dem Repository vorausgefüllt. Überprüfen Sie die Felder vor dem Speichern.",
548
+ "nothing": "Nichts automatisch zu erkennen",
549
+ "failed": "Automatische Erkennung fehlgeschlagen",
550
+ "envFiles": "Env-Vorlagen, die vor dem Start materialisiert werden:"
551
+ },
541
552
  "edit": {
542
553
  "heading": "Gemeinsamen Stack bearbeiten",
543
554
  "save": "Änderungen speichern",
@@ -2224,6 +2224,8 @@
2224
2224
  "cloneUrl": "Repository clone URL",
2225
2225
  "cloneUrlHelp": "The git repository the stack's compose files live in.",
2226
2226
  "gitRef": "Branch or tag (optional)",
2227
+ "directory": "Subdirectory (optional)",
2228
+ "directoryHelp": "Used only by Autodetect: the monorepo subdirectory the compose stack lives in.",
2227
2229
  "composeFiles": "Compose files",
2228
2230
  "composeFilesHelp": "Comma-separated, repo-relative, in override order.",
2229
2231
  "composeProfiles": "Compose profiles (optional)",
@@ -2232,6 +2234,15 @@
2232
2234
  "allowHostCommands": "Allow host-command setup steps",
2233
2235
  "save": "Add stack"
2234
2236
  },
2237
+ "detect": {
2238
+ "button": "Autodetect",
2239
+ "hint": "Read the repository and prefill the compose files, profiles, and networks.",
2240
+ "detected": "Detected stack configuration",
2241
+ "detectedBody": "Prefilled from the repository. Review the fields before saving.",
2242
+ "nothing": "Nothing to autodetect",
2243
+ "failed": "Autodetection failed",
2244
+ "envFiles": "Env templates to materialize before start:"
2245
+ },
2235
2246
  "edit": {
2236
2247
  "heading": "Edit shared stack",
2237
2248
  "save": "Save changes",
@@ -2050,6 +2050,8 @@
2050
2050
  "cloneUrl": "URL de clonación del repositorio",
2051
2051
  "cloneUrlHelp": "El repositorio git donde viven los archivos de Compose del stack.",
2052
2052
  "gitRef": "Rama o etiqueta (opcional)",
2053
+ "directory": "Subdirectorio (opcional)",
2054
+ "directoryHelp": "Solo lo usa la detección automática: el subdirectorio del monorepo donde se encuentra el stack de compose.",
2053
2055
  "composeFiles": "Archivos de Compose",
2054
2056
  "composeFilesHelp": "Separados por comas, relativos al repositorio, en orden de anulación.",
2055
2057
  "composeProfiles": "Perfiles de Compose (opcional)",
@@ -2058,6 +2060,15 @@
2058
2060
  "allowHostCommands": "Permitir pasos de configuración con comandos del host",
2059
2061
  "save": "Añadir stack"
2060
2062
  },
2063
+ "detect": {
2064
+ "button": "Detectar automáticamente",
2065
+ "hint": "Lee el repositorio y rellena los archivos de compose, los perfiles y las redes.",
2066
+ "detected": "Configuración del stack detectada",
2067
+ "detectedBody": "Rellenado desde el repositorio. Revisa los campos antes de guardar.",
2068
+ "nothing": "No hay nada que detectar automáticamente",
2069
+ "failed": "La detección automática falló",
2070
+ "envFiles": "Plantillas de entorno que se materializarán antes de iniciar:"
2071
+ },
2061
2072
  "edit": {
2062
2073
  "heading": "Editar stack compartido",
2063
2074
  "save": "Guardar cambios",
@@ -2050,6 +2050,8 @@
2050
2050
  "cloneUrl": "URL de clonage du dépôt",
2051
2051
  "cloneUrlHelp": "Le dépôt git où se trouvent les fichiers Compose du stack.",
2052
2052
  "gitRef": "Branche ou tag (facultatif)",
2053
+ "directory": "Sous-répertoire (facultatif)",
2054
+ "directoryHelp": "Utilisé uniquement par la détection automatique : le sous-répertoire du monorepo où se trouve le stack compose.",
2053
2055
  "composeFiles": "Fichiers Compose",
2054
2056
  "composeFilesHelp": "Séparés par des virgules, relatifs au dépôt, dans l'ordre de surcharge.",
2055
2057
  "composeProfiles": "Profils Compose (facultatif)",
@@ -2058,6 +2060,15 @@
2058
2060
  "allowHostCommands": "Autoriser les étapes de configuration par commande hôte",
2059
2061
  "save": "Ajouter le stack"
2060
2062
  },
2063
+ "detect": {
2064
+ "button": "Détection automatique",
2065
+ "hint": "Lire le dépôt et préremplir les fichiers compose, les profils et les réseaux.",
2066
+ "detected": "Configuration de la pile détectée",
2067
+ "detectedBody": "Prérempli à partir du dépôt. Vérifiez les champs avant d'enregistrer.",
2068
+ "nothing": "Rien à détecter automatiquement",
2069
+ "failed": "Échec de la détection automatique",
2070
+ "envFiles": "Modèles d'environnement à matérialiser avant le démarrage :"
2071
+ },
2061
2072
  "edit": {
2062
2073
  "heading": "Modifier le stack partagé",
2063
2074
  "save": "Enregistrer les modifications",
@@ -2171,6 +2171,8 @@
2171
2171
  "cloneUrl": "כתובת שכפול של המאגר",
2172
2172
  "cloneUrlHelp": "מאגר ה-git שבו נמצאים קובצי ה-Compose של המקבץ.",
2173
2173
  "gitRef": "ענף או תג (אופציונלי)",
2174
+ "directory": "תת-ספרייה (אופציונלי)",
2175
+ "directoryHelp": "בשימוש רק על ידי הזיהוי האוטומטי: תת-הספרייה במונורפו שבה נמצא מקבץ ה-compose.",
2174
2176
  "composeFiles": "קובצי Compose",
2175
2177
  "composeFilesHelp": "מופרדים בפסיקים, יחסית למאגר, לפי סדר הדריסה.",
2176
2178
  "composeProfiles": "פרופילי Compose (אופציונלי)",
@@ -2179,6 +2181,15 @@
2179
2181
  "allowHostCommands": "אפשר שלבי הגדרה עם פקודות מארח",
2180
2182
  "save": "הוספת מקבץ"
2181
2183
  },
2184
+ "detect": {
2185
+ "button": "זיהוי אוטומטי",
2186
+ "hint": "קריאת המאגר ומילוי מראש של קובצי ה-compose, הפרופילים והרשתות.",
2187
+ "detected": "תצורת הסטאק זוהתה",
2188
+ "detectedBody": "מולא מראש מהמאגר. בדקו את השדות לפני השמירה.",
2189
+ "nothing": "אין מה לזהות אוטומטית",
2190
+ "failed": "הזיהוי האוטומטי נכשל",
2191
+ "envFiles": "תבניות env שיש לממש לפני ההפעלה:"
2192
+ },
2182
2193
  "edit": {
2183
2194
  "heading": "עריכת מקבץ משותף",
2184
2195
  "save": "שמירת שינויים",
@@ -530,6 +530,8 @@
530
530
  "cloneUrl": "URL di clone del repository",
531
531
  "cloneUrlHelp": "Il repository git in cui risiedono i file compose dello stack.",
532
532
  "gitRef": "Branch o tag (facoltativo)",
533
+ "directory": "Sottodirectory (facoltativo)",
534
+ "directoryHelp": "Usato solo dal rilevamento automatico: la sottodirectory del monorepo in cui si trova lo stack compose.",
533
535
  "composeFiles": "File compose",
534
536
  "composeFilesHelp": "Separati da virgola, relativi al repository, in ordine di override.",
535
537
  "composeProfiles": "Profili compose (facoltativo)",
@@ -538,6 +540,15 @@
538
540
  "allowHostCommands": "Consenti passaggi di setup con comandi host",
539
541
  "save": "Aggiungi stack"
540
542
  },
543
+ "detect": {
544
+ "button": "Rilevamento automatico",
545
+ "hint": "Legge il repository e precompila i file compose, i profili e le reti.",
546
+ "detected": "Configurazione dello stack rilevata",
547
+ "detectedBody": "Precompilato dal repository. Controlla i campi prima di salvare.",
548
+ "nothing": "Niente da rilevare automaticamente",
549
+ "failed": "Rilevamento automatico non riuscito",
550
+ "envFiles": "Modelli di ambiente da materializzare prima dell'avvio:"
551
+ },
541
552
  "edit": {
542
553
  "heading": "Modifica stack condiviso",
543
554
  "save": "Salva le modifiche",
@@ -2172,6 +2172,8 @@
2172
2172
  "cloneUrl": "リポジトリのクローン URL",
2173
2173
  "cloneUrlHelp": "スタックの Compose ファイルが置かれている git リポジトリ。",
2174
2174
  "gitRef": "ブランチまたはタグ(任意)",
2175
+ "directory": "サブディレクトリ(任意)",
2176
+ "directoryHelp": "自動検出でのみ使用されます。compose スタックが存在するモノレポのサブディレクトリです。",
2175
2177
  "composeFiles": "Compose ファイル",
2176
2178
  "composeFilesHelp": "カンマ区切り、リポジトリ相対、オーバーライド順。",
2177
2179
  "composeProfiles": "Compose プロファイル(任意)",
@@ -2180,6 +2182,15 @@
2180
2182
  "allowHostCommands": "ホストコマンドのセットアップ手順を許可する",
2181
2183
  "save": "スタックを追加"
2182
2184
  },
2185
+ "detect": {
2186
+ "button": "自動検出",
2187
+ "hint": "リポジトリを読み取り、compose ファイル、プロファイル、ネットワークを事前入力します。",
2188
+ "detected": "スタック構成を検出しました",
2189
+ "detectedBody": "リポジトリから事前入力しました。保存する前にフィールドを確認してください。",
2190
+ "nothing": "自動検出するものがありません",
2191
+ "failed": "自動検出に失敗しました",
2192
+ "envFiles": "起動前に生成される env テンプレート:"
2193
+ },
2183
2194
  "edit": {
2184
2195
  "heading": "共有スタックを編集",
2185
2196
  "save": "変更を保存",
@@ -2050,6 +2050,8 @@
2050
2050
  "cloneUrl": "URL klonowania repozytorium",
2051
2051
  "cloneUrlHelp": "Repozytorium git, w którym znajdują się pliki Compose stosu.",
2052
2052
  "gitRef": "Gałąź lub tag (opcjonalnie)",
2053
+ "directory": "Podkatalog (opcjonalnie)",
2054
+ "directoryHelp": "Używane tylko przez automatyczne wykrywanie: podkatalog monorepo, w którym znajduje się stos compose.",
2053
2055
  "composeFiles": "Pliki Compose",
2054
2056
  "composeFilesHelp": "Rozdzielone przecinkami, względem repozytorium, w kolejności nadpisywania.",
2055
2057
  "composeProfiles": "Profile Compose (opcjonalnie)",
@@ -2058,6 +2060,15 @@
2058
2060
  "allowHostCommands": "Zezwól na kroki konfiguracji z poleceniami hosta",
2059
2061
  "save": "Dodaj stos"
2060
2062
  },
2063
+ "detect": {
2064
+ "button": "Wykryj automatycznie",
2065
+ "hint": "Odczytaj repozytorium i wypełnij wstępnie pliki compose, profile i sieci.",
2066
+ "detected": "Wykryto konfigurację stosu",
2067
+ "detectedBody": "Wypełniono wstępnie na podstawie repozytorium. Sprawdź pola przed zapisaniem.",
2068
+ "nothing": "Nie ma nic do automatycznego wykrycia",
2069
+ "failed": "Automatyczne wykrywanie nie powiodło się",
2070
+ "envFiles": "Szablony env do zmaterializowania przed uruchomieniem:"
2071
+ },
2061
2072
  "edit": {
2062
2073
  "heading": "Edytuj współdzielony stos",
2063
2074
  "save": "Zapisz zmiany",
@@ -2172,6 +2172,8 @@
2172
2172
  "cloneUrl": "Depo klonlama URL'si",
2173
2173
  "cloneUrlHelp": "Yığının Compose dosyalarının bulunduğu git deposu.",
2174
2174
  "gitRef": "Dal veya etiket (isteğe bağlı)",
2175
+ "directory": "Alt dizin (isteğe bağlı)",
2176
+ "directoryHelp": "Yalnızca otomatik algılama tarafından kullanılır: compose yığınının bulunduğu monorepo alt dizini.",
2175
2177
  "composeFiles": "Compose dosyaları",
2176
2178
  "composeFilesHelp": "Virgülle ayrılmış, depoya göreli, geçersiz kılma sırasında.",
2177
2179
  "composeProfiles": "Compose profilleri (isteğe bağlı)",
@@ -2180,6 +2182,15 @@
2180
2182
  "allowHostCommands": "Ana makine komutu kurulum adımlarına izin ver",
2181
2183
  "save": "Yığın ekle"
2182
2184
  },
2185
+ "detect": {
2186
+ "button": "Otomatik algıla",
2187
+ "hint": "Depoyu okuyup compose dosyalarını, profilleri ve ağları önceden doldurur.",
2188
+ "detected": "Yığın yapılandırması algılandı",
2189
+ "detectedBody": "Depodan önceden dolduruldu. Kaydetmeden önce alanları gözden geçirin.",
2190
+ "nothing": "Otomatik algılanacak bir şey yok",
2191
+ "failed": "Otomatik algılama başarısız oldu",
2192
+ "envFiles": "Başlatmadan önce oluşturulacak env şablonları:"
2193
+ },
2183
2194
  "edit": {
2184
2195
  "heading": "Paylaşılan yığını düzenle",
2185
2196
  "save": "Değişiklikleri kaydet",
@@ -2050,6 +2050,8 @@
2050
2050
  "cloneUrl": "URL клонування репозиторію",
2051
2051
  "cloneUrlHelp": "Git-репозиторій, у якому містяться файли Compose стека.",
2052
2052
  "gitRef": "Гілка або тег (необов'язково)",
2053
+ "directory": "Підкаталог (необов'язково)",
2054
+ "directoryHelp": "Використовується лише автовизначенням: підкаталог монорепозиторію, де розташований стек compose.",
2053
2055
  "composeFiles": "Файли Compose",
2054
2056
  "composeFilesHelp": "Через кому, відносно репозиторію, у порядку перевизначення.",
2055
2057
  "composeProfiles": "Профілі Compose (необов'язково)",
@@ -2058,6 +2060,15 @@
2058
2060
  "allowHostCommands": "Дозволити кроки налаштування з командами хоста",
2059
2061
  "save": "Додати стек"
2060
2062
  },
2063
+ "detect": {
2064
+ "button": "Автовизначення",
2065
+ "hint": "Прочитати репозиторій і попередньо заповнити файли compose, профілі та мережі.",
2066
+ "detected": "Виявлено конфігурацію стека",
2067
+ "detectedBody": "Попередньо заповнено з репозиторію. Перевірте поля перед збереженням.",
2068
+ "nothing": "Немає чого визначати автоматично",
2069
+ "failed": "Не вдалося виконати автовизначення",
2070
+ "envFiles": "Шаблони env, які буде матеріалізовано перед запуском:"
2071
+ },
2061
2072
  "edit": {
2062
2073
  "heading": "Редагувати спільний стек",
2063
2074
  "save": "Зберегти зміни",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.101.0",
3
+ "version": "0.102.0",
4
4
  "description": "Reusable Nuxt layer for the Agent Architecture Board SPA (components, stores, composables, pages). Consume it from a thin deployment app via `extends: ['@cat-factory/app']` and point it at your backend with NUXT_PUBLIC_API_BASE. See deploy/frontend for an example.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "valibot": "^1.4.2",
35
35
  "vue": "3.5.39",
36
36
  "wretch": "^3.0.9",
37
- "@cat-factory/contracts": "0.110.1"
37
+ "@cat-factory/contracts": "0.112.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@toad-contracts/testing": "0.3.2",