@cat-factory/app 0.145.2 → 0.146.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.
@@ -0,0 +1,70 @@
1
+ <script setup lang="ts">
2
+ // The environment-setup wizard's stepper header, driven entirely by
3
+ // `useJourneyProgress` (modular-react#83, production-feedback item 4). The ordered
4
+ // steps, the live position, and the "Step X of N" total all come from
5
+ // `resolveStepSequence` walking the journey's transition graph — there is no
6
+ // hand-maintained step-order array to keep in sync (the old `ENV_STEP_ORDER` +
7
+ // `crumbState` is gone). Rendered inside `<JourneyHost>`, which hands it the live
8
+ // `instanceId`; each step's label is the i18n key carried in the journey's `steps`
9
+ // metadata.
10
+ import type { InstanceId } from '@modular-vue/journeys'
11
+ import { useJourneyProgress } from '@modular-vue/journeys'
12
+ import { environmentSetupJourney } from '~/modular/journeys/environmentSetup'
13
+ import type { EnvSetupInput } from '~/modular/journeys/environmentSetup.logic'
14
+
15
+ const props = defineProps<{
16
+ /** The live journey instance from `<JourneyHost>`, or null before it starts. */
17
+ instanceId: InstanceId | null
18
+ /** The launch input; frozen for the host's lifetime, so the resolved spine is
19
+ * stable (`useJourneyProgress` reads `sequence.input` once at setup). */
20
+ input: EnvSetupInput
21
+ }>()
22
+
23
+ const { t, te } = useI18n()
24
+
25
+ const { index, total, steps } = useJourneyProgress(
26
+ () => props.instanceId,
27
+ environmentSetupJourney,
28
+ { sequence: { input: props.input } },
29
+ )
30
+
31
+ /** Resolve a step's progress-label key (from the journey's `steps` metadata)
32
+ * through i18n, tolerating a locale that omits it rather than leaking the key. */
33
+ function stepLabel(key: string | undefined): string {
34
+ return key && te(key) ? t(key) : ''
35
+ }
36
+ </script>
37
+
38
+ <template>
39
+ <div class="space-y-2" data-testid="env-setup-stepper">
40
+ <p v-if="total" class="text-[11px] font-medium text-slate-400" data-testid="env-setup-progress">
41
+ {{ t('environmentWizard.progress', { index: index + 1, total }) }}
42
+ </p>
43
+ <ol class="flex items-center gap-2 text-[11px]">
44
+ <li
45
+ v-for="(step, i) in steps"
46
+ :key="step.entry"
47
+ class="flex items-center gap-2"
48
+ :data-testid="`env-setup-crumb-${step.entry}`"
49
+ >
50
+ <span
51
+ class="flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold"
52
+ :class="{
53
+ 'bg-primary-500 text-white': i === index,
54
+ 'bg-emerald-600/70 text-white': i < index,
55
+ 'bg-slate-700 text-slate-300': i > index,
56
+ }"
57
+ >{{ i + 1 }}</span
58
+ >
59
+ <span :class="i === index ? 'text-slate-100' : 'text-slate-500'">
60
+ {{ stepLabel(step.progressLabel) }}
61
+ </span>
62
+ <UIcon
63
+ v-if="i < steps.length - 1"
64
+ name="i-lucide-chevron-right"
65
+ class="h-3 w-3 text-slate-600"
66
+ />
67
+ </li>
68
+ </ol>
69
+ </div>
70
+ </template>
@@ -8,14 +8,15 @@
8
8
  // journey (`~/modular/journeys/environmentSetup`), hosted here by `<JourneyHost>`:
9
9
  // it starts the journey on open (RESUMING the in-flight instance for the same
10
10
  // frame when one was left mid-flow, via the Pinia persistence adapter), renders
11
- // the current step through `<JourneyOutlet>`, and abandons it on close. Each step
12
- // component drives the `environmentWizard` store for its data/actions and fires
13
- // the journey's exits to advance. On `complete` (the save step's Done) the journey
14
- // clears its persisted blob and we close the modal.
11
+ // the current step through `<JourneyOutlet>`, and abandons it on close. The
12
+ // stepper header + "Step X of N" are derived from the journey's transition graph
13
+ // by `<EnvSetupStepper>` (via `useJourneyProgress`), not a hand-maintained step
14
+ // list. Each step component drives the `environmentWizard` store for its
15
+ // data/actions and fires the journey's exits to advance. On `complete` (the save
16
+ // step's Done) the journey clears its persisted blob and we close the modal.
15
17
  import { computed } from 'vue'
16
18
  import { JourneyHost, JourneyOutlet } from '@modular-vue/journeys'
17
19
  import { environmentSetupHandle } from '~/modular/journeys/environmentSetup'
18
- import { ENV_STEP_ORDER, type EnvStep } from '~/modular/journeys/environmentSetup.logic'
19
20
 
20
21
  const ui = useUiStore()
21
22
  const { t } = useI18n()
@@ -30,23 +31,6 @@ const open = computed({
30
31
  // Read once at journey start; keyed for resume. Frozen for the host's lifetime,
31
32
  // so the modal remounts the host per open (it renders under `v-if` upstream).
32
33
  const input = computed(() => ({ frameId: ui.environmentWizardFrameId }))
33
-
34
- const STEP_LABEL = computed<Record<EnvStep, string>>(() => ({
35
- pick: t('environmentWizard.steps.pick'),
36
- review: t('environmentWizard.steps.review'),
37
- preflight: t('environmentWizard.steps.preflight'),
38
- save: t('environmentWizard.steps.save'),
39
- }))
40
-
41
- /** The crumb index of a step, relative to the current journey step. */
42
- function crumbState(
43
- entry: EnvStep,
44
- currentEntry: EnvStep | undefined,
45
- ): 'current' | 'done' | 'todo' {
46
- if (!currentEntry) return 'todo'
47
- if (entry === currentEntry) return 'current'
48
- return ENV_STEP_ORDER.indexOf(entry) < ENV_STEP_ORDER.indexOf(currentEntry) ? 'done' : 'todo'
49
- }
50
34
  </script>
51
35
 
52
36
  <template>
@@ -63,43 +47,9 @@ function crumbState(
63
47
  :input="input"
64
48
  @finished="ui.closeEnvironmentSetup()"
65
49
  >
66
- <template #default="{ instanceId, instance }">
67
- <!-- stepper header, driven by the journey's current step -->
68
- <ol class="flex items-center gap-2 text-[11px]">
69
- <li
70
- v-for="(s, i) in ENV_STEP_ORDER"
71
- :key="s"
72
- class="flex items-center gap-2"
73
- :data-testid="`env-setup-crumb-${s}`"
74
- >
75
- <span
76
- class="flex h-5 w-5 items-center justify-center rounded-full text-[10px] font-semibold"
77
- :class="{
78
- 'bg-primary-500 text-white':
79
- crumbState(s, (instance?.step?.entry as EnvStep) ?? undefined) === 'current',
80
- 'bg-emerald-600/70 text-white':
81
- crumbState(s, (instance?.step?.entry as EnvStep) ?? undefined) === 'done',
82
- 'bg-slate-700 text-slate-300':
83
- crumbState(s, (instance?.step?.entry as EnvStep) ?? undefined) === 'todo',
84
- }"
85
- >{{ i + 1 }}</span
86
- >
87
- <span
88
- :class="
89
- crumbState(s, (instance?.step?.entry as EnvStep) ?? undefined) === 'current'
90
- ? 'text-slate-100'
91
- : 'text-slate-500'
92
- "
93
- >
94
- {{ STEP_LABEL[s] }}
95
- </span>
96
- <UIcon
97
- v-if="i < ENV_STEP_ORDER.length - 1"
98
- name="i-lucide-chevron-right"
99
- class="h-3 w-3 text-slate-600"
100
- />
101
- </li>
102
- </ol>
50
+ <template #default="{ instanceId }">
51
+ <!-- stepper header, derived from the journey graph -->
52
+ <EnvSetupStepper :instance-id="instanceId" :input="input" />
103
53
 
104
54
  <!-- the current step (pick / review / preflight / save) -->
105
55
  <div class="mt-4">
@@ -1,20 +1,28 @@
1
1
  import { describe, expect, it } from 'vitest'
2
+ import { resolveStepSequence } from '@modular-vue/journeys'
2
3
  import {
3
- ENV_STEP_ORDER,
4
+ ENV_MODULE_ID,
5
+ environmentSetupJourney,
4
6
  envInitialState,
5
- envNextAfter,
6
7
  envStartStep,
7
8
  } from './environmentSetup.logic'
9
+ import en from '../../../i18n/locales/en.json'
8
10
 
9
- // Pure navigation graph for the environment-setup journey (slice 3). `envNextAfter`
10
- // is the source of truth the journey's `advance` transitions derive their target
11
- // entries from (see `environmentSetup.ts`), so pinning the order, start branch, and
12
- // forward edges here means a wiring regression can't silently reorder or drop a step.
13
- describe('environment-setup journey logic', () => {
14
- it('orders the steps pick → review → preflight → save', () => {
15
- expect(ENV_STEP_ORDER).toEqual(['pick', 'review', 'preflight', 'save'])
16
- })
11
+ /** Dot-path lookup into the real `en.json`, mirroring which keys actually ship. */
12
+ function hasKey(path: string): boolean {
13
+ return (
14
+ path.split('.').reduce<unknown>((node, seg) => {
15
+ return node && typeof node === 'object' ? (node as Record<string, unknown>)[seg] : undefined
16
+ }, en) !== undefined
17
+ )
18
+ }
17
19
 
20
+ // Pure navigation graph for the environment-setup journey (slice 3). The step
21
+ // order is derived from the annotated transition graph (production-feedback item
22
+ // 4), so `resolveStepSequenceResult` walking the real journey definition is the
23
+ // guard against a silent reorder or dropped step — no hand-maintained order array
24
+ // to pin separately.
25
+ describe('environment-setup journey logic', () => {
18
26
  it('seeds state from the launch input', () => {
19
27
  expect(envInitialState({ frameId: 'blk_1' })).toEqual({ frameId: 'blk_1' })
20
28
  expect(envInitialState({ frameId: null })).toEqual({ frameId: null })
@@ -25,10 +33,33 @@ describe('environment-setup journey logic', () => {
25
33
  expect(envStartStep({ frameId: null }, { frameId: null })).toBe('pick')
26
34
  })
27
35
 
28
- it('advances linearly and terminates after save', () => {
29
- expect(envNextAfter('pick')).toBe('review')
30
- expect(envNextAfter('review')).toBe('preflight')
31
- expect(envNextAfter('preflight')).toBe('save')
32
- expect(envNextAfter('save')).toBe('done')
36
+ it('derives the pick review → preflight → save order from the transition graph', () => {
37
+ const steps = resolveStepSequence(environmentSetupJourney, { input: { frameId: null } })
38
+ expect(steps.map((s) => s.entry)).toEqual(['pick', 'review', 'preflight', 'save'])
39
+ expect(steps.every((s) => s.module === ENV_MODULE_ID)).toBe(true)
40
+ expect(steps.map((s) => s.progressLabel)).toEqual([
41
+ 'environmentWizard.steps.pick',
42
+ 'environmentWizard.steps.review',
43
+ 'environmentWizard.steps.preflight',
44
+ 'environmentWizard.steps.save',
45
+ ])
46
+ })
47
+
48
+ it('starts the derived sequence at review when a frame is preselected', () => {
49
+ const steps = resolveStepSequence(environmentSetupJourney, { input: { frameId: 'blk_1' } })
50
+ expect(steps.map((s) => s.entry)).toEqual(['review', 'preflight', 'save'])
51
+ })
52
+
53
+ // The stepper resolves each label through a VARIABLE key (`t(step.progressLabel)`), so
54
+ // the tier-1 typed-message-keys check + `vue-i18n-extract` can no longer see these keys
55
+ // as used and can't catch a typo or a dropped key. Pin the missing-key guard here instead:
56
+ // every `progressLabel` the real definition emits must resolve to a shipping `en.json` key.
57
+ it('carries a shipping en.json label key for every derived step', () => {
58
+ const steps = resolveStepSequence(environmentSetupJourney, { input: { frameId: null } })
59
+ for (const step of steps) {
60
+ const key = step.progressLabel
61
+ expect(key, `missing i18n key for step "${step.entry}"`).toBeTruthy()
62
+ expect(hasKey(key ?? ''), `key "${key}" not in en.json`).toBe(true)
63
+ }
33
64
  })
34
65
  })
@@ -10,15 +10,26 @@
10
10
  * trial) stay in that Pinia store, which the step components still drive; the
11
11
  * journey just decides WHICH step shows and threads the target frame id.
12
12
  *
13
- * This file is deliberately free of Vue/`.vue`/`defineModule` imports so the
14
- * transition graph is unit-tested directly (`environmentSetup.spec.ts`); the
15
- * component wiring lives in `environmentSetup.ts`, which feeds these helpers into
16
- * `defineJourney`'s `transitions` map.
13
+ * The step ORDER is no longer spelled out a second time as an ordered array: it
14
+ * is DERIVED from the annotated transition graph below (production-feedback item
15
+ * 4 in modular-react#83). Each transition wraps its handler with
16
+ * `defineTransition({ targets, handle })` so the static `targets` declare where
17
+ * the flow can go; `resolveStepSequence` / `useJourneyProgress` walk that graph
18
+ * to produce the ordered step list and the wizard's "Step X of N" progress from
19
+ * the one place the flow is encoded. `steps` carries each step's progress-label
20
+ * key beside the transitions.
21
+ *
22
+ * This definition lives in the logic file (not the SFC-importing
23
+ * `environmentSetup.ts`) so the graph stays free of `.vue` imports and is
24
+ * unit-tested directly (`environmentSetup.logic.spec.ts`). It references the step
25
+ * module only as a TYPE (`import type`), which is erased at runtime, so importing
26
+ * this file pulls no components. `environmentSetup.ts` supplies the module (with
27
+ * its step components) and re-exports the journey + the launch handle + the
28
+ * persistence adapter.
17
29
  */
18
-
19
- /** The journey's ordered step entries (also the module's `entryPoints` keys). */
20
- export const ENV_STEP_ORDER = ['pick', 'review', 'preflight', 'save'] as const
21
- export type EnvStep = (typeof ENV_STEP_ORDER)[number]
30
+ import type { ExitCtx } from '@modular-vue/journeys'
31
+ import { defineJourney, defineTransition } from '@modular-vue/journeys'
32
+ import type { environmentSetupModule } from '~/modular/journeys/environmentSetup'
22
33
 
23
34
  /** The single module id every step entry lives under. */
24
35
  export const ENV_MODULE_ID = 'cat-factory:environment-setup' as const
@@ -52,35 +63,91 @@ export function envInitialState(input: EnvSetupInput): EnvSetupState {
52
63
  }
53
64
 
54
65
  /** First step: skip the picker when the launcher already chose a frame. */
55
- export function envStartStep(_state: EnvSetupState, input: EnvSetupInput): EnvStep {
66
+ export function envStartStep(_state: EnvSetupState, input: EnvSetupInput): 'pick' | 'review' {
56
67
  return input.frameId ? 'review' : 'pick'
57
68
  }
58
69
 
59
70
  /**
60
- * The step reached by advancing from `from` via its forward exit, or `'done'`
61
- * when the flow completes. The pick step advances via `select` (a distinct
62
- * exit); the rest via `advance`. Pure and total over `EnvStep`.
63
- *
64
- * This is the SINGLE SOURCE OF TRUTH for the linear forward chain: the journey
65
- * definition (`environmentSetup.ts`) derives its `advance` transitions' target
66
- * entries from it, so pinning this function in `environmentSetup.logic.spec.ts`
67
- * genuinely guards the wired graph against a silent reorder/drop. The overloads
68
- * narrow the return to a concrete entry (or `'done'`) so a transition handler can
69
- * feed the result straight into a `StepSpec` without a widened `EnvStep | 'done'`.
71
+ * The journey's module type map one module, referenced by its `typeof` so the
72
+ * transition + step maps resolve its literal entry/exit vocabulary with no casts.
73
+ * This is the case production-feedback item 3 (modular-react#83) fixed: before it,
74
+ * `defineModule` widened the descriptor, so `typeof environmentSetupModule` could
75
+ * not stand in as a `TModules` member without re-declaring the entry names by hand.
70
76
  */
71
- export function envNextAfter(from: 'pick'): 'review'
72
- export function envNextAfter(from: 'review'): 'preflight'
73
- export function envNextAfter(from: 'preflight'): 'save'
74
- export function envNextAfter(from: 'save'): 'done'
75
- export function envNextAfter(from: EnvStep): EnvStep | 'done' {
76
- switch (from) {
77
- case 'pick':
78
- return 'review'
79
- case 'review':
80
- return 'preflight'
81
- case 'preflight':
82
- return 'save'
83
- case 'save':
84
- return 'done'
85
- }
86
- }
77
+ export type EnvModules = { [ENV_MODULE_ID]: typeof environmentSetupModule }
78
+
79
+ /** Binder threading the journey generics into each annotated transition handler. */
80
+ const transition = defineTransition<EnvModules, EnvSetupState>()
81
+
82
+ /**
83
+ * The journey definition. `start` skips the picker when a frame was preselected.
84
+ * The forward chain is the annotated transitions' `targets`: pick →(select)→
85
+ * review →(advance)→ preflight →(advance)→ save →(advance)→ complete. Back
86
+ * navigation is handled by the entries' `allowBack` (declared on the module in
87
+ * `environmentSetup.ts`), not explicit transitions.
88
+ */
89
+ export const environmentSetupJourney = defineJourney<EnvModules, EnvSetupState>()({
90
+ id: 'environment-setup',
91
+ version: '1.0.0',
92
+ initialState: (input: EnvSetupInput) => envInitialState(input),
93
+ start: (state, input: EnvSetupInput) =>
94
+ envStartStep(state, input) === 'review'
95
+ ? { module: ENV_MODULE_ID, entry: 'review', input: { frameId: state.frameId } }
96
+ : { module: ENV_MODULE_ID, entry: 'pick', input: { frameId: state.frameId } },
97
+ steps: {
98
+ [ENV_MODULE_ID]: {
99
+ pick: { progressLabel: 'environmentWizard.steps.pick' },
100
+ review: { progressLabel: 'environmentWizard.steps.review' },
101
+ preflight: { progressLabel: 'environmentWizard.steps.preflight' },
102
+ save: { progressLabel: 'environmentWizard.steps.save' },
103
+ },
104
+ },
105
+ transitions: {
106
+ [ENV_MODULE_ID]: {
107
+ pick: {
108
+ [ENV_SELECT_EXIT]: transition({
109
+ targets: [{ module: ENV_MODULE_ID, entry: 'review' }],
110
+ handle: (ctx: ExitCtx<EnvSetupState, EnvSelectOutput, unknown>) => ({
111
+ next: {
112
+ module: ENV_MODULE_ID,
113
+ entry: 'review',
114
+ input: { frameId: ctx.output.frameId },
115
+ },
116
+ state: { frameId: ctx.output.frameId },
117
+ }),
118
+ }),
119
+ },
120
+ review: {
121
+ [ENV_ADVANCE_EXIT]: transition({
122
+ targets: [{ module: ENV_MODULE_ID, entry: 'preflight' }],
123
+ handle: (ctx) => ({
124
+ next: {
125
+ module: ENV_MODULE_ID,
126
+ entry: 'preflight',
127
+ input: { frameId: ctx.state.frameId },
128
+ },
129
+ }),
130
+ }),
131
+ },
132
+ preflight: {
133
+ [ENV_ADVANCE_EXIT]: transition({
134
+ targets: [{ module: ENV_MODULE_ID, entry: 'save' }],
135
+ handle: (ctx) => ({
136
+ next: {
137
+ module: ENV_MODULE_ID,
138
+ entry: 'save',
139
+ input: { frameId: ctx.state.frameId },
140
+ },
141
+ }),
142
+ }),
143
+ },
144
+ // `save` advances to journey completion.
145
+ save: {
146
+ [ENV_ADVANCE_EXIT]: transition({
147
+ targets: ['complete'],
148
+ handle: () => ({ complete: undefined }),
149
+ }),
150
+ },
151
+ },
152
+ },
153
+ })
@@ -1,6 +1,6 @@
1
1
  import { defineModule } from '@modular-vue/core'
2
2
  import { defineExit } from '@modular-frontend/core'
3
- import { defineJourney, defineJourneyHandle } from '@modular-vue/journeys'
3
+ import { defineJourneyHandle } from '@modular-vue/journeys'
4
4
  import EnvPickStep from '~/components/environments/steps/EnvPickStep.vue'
5
5
  import EnvReviewStep from '~/components/environments/steps/EnvReviewStep.vue'
6
6
  import EnvPreflightStep from '~/components/environments/steps/EnvPreflightStep.vue'
@@ -13,9 +13,7 @@ import {
13
13
  type EnvSelectOutput,
14
14
  type EnvSetupInput,
15
15
  type EnvSetupState,
16
- envInitialState,
17
- envNextAfter,
18
- envStartStep,
16
+ environmentSetupJourney,
19
17
  } from '~/modular/journeys/environmentSetup.logic'
20
18
 
21
19
  /**
@@ -25,6 +23,13 @@ import {
25
23
  * with a typed, back/rewind-capable, resumable journey; the per-step data + async
26
24
  * actions stay in that Pinia store, driven by the step components below.
27
25
  *
26
+ * This file supplies the step MODULE (it imports the step `.vue` components, so —
27
+ * like `result-views.ts` — it's registered from the client plugin, keeping the
28
+ * unit-tested `registry.ts` / `*.logic.ts` import graph free of SFCs) and re-exports
29
+ * the JOURNEY, whose transition graph + step metadata live in the SFC-free
30
+ * `environmentSetup.logic.ts` (so `resolveStepSequence` / `useJourneyProgress` and
31
+ * the ordering test have no `.vue` dependency).
32
+ *
28
33
  * Authoring notes (co-evolution): `defineModule` comes from the `@modular-vue/core`
29
34
  * binding, but the exit helper `defineExit` is only exported from the neutral
30
35
  * `@modular-frontend/core` engine (a direct dep) — the Vue binding doesn't re-export
@@ -36,10 +41,6 @@ import {
36
41
  * pick step and never changes mid-flow, so the snapshot input a transition places is
37
42
  * always current — even on `preserve-state` back-navigation — which keeps the module
38
43
  * type simple (no `buildInput`-optionality quirk) and the flow fully explicit.
39
- *
40
- * This file imports the step `.vue` components, so — like `result-views.ts` — it's
41
- * registered from the client plugin, keeping the unit-tested `registry.ts` /
42
- * `*.logic.ts` import graph free of SFCs.
43
44
  */
44
45
 
45
46
  /**
@@ -52,20 +53,20 @@ export const environmentSetupModule = defineModule({
52
53
  id: ENV_MODULE_ID,
53
54
  version: '1.0.0',
54
55
  entryPoints: {
55
- pick: { mountKinds: ['journey'] as const, component: EnvPickStep },
56
+ pick: { mountKinds: ['journey'], component: EnvPickStep },
56
57
  review: {
57
- mountKinds: ['journey'] as const,
58
- allowBack: 'preserve-state' as const,
58
+ mountKinds: ['journey'],
59
+ allowBack: 'preserve-state',
59
60
  component: EnvReviewStep,
60
61
  },
61
62
  preflight: {
62
- mountKinds: ['journey'] as const,
63
- allowBack: 'preserve-state' as const,
63
+ mountKinds: ['journey'],
64
+ allowBack: 'preserve-state',
64
65
  component: EnvPreflightStep,
65
66
  },
66
67
  save: {
67
- mountKinds: ['journey'] as const,
68
- allowBack: 'preserve-state' as const,
68
+ mountKinds: ['journey'],
69
+ allowBack: 'preserve-state',
69
70
  component: EnvSaveStep,
70
71
  },
71
72
  },
@@ -75,59 +76,7 @@ export const environmentSetupModule = defineModule({
75
76
  },
76
77
  })
77
78
 
78
- type EnvModules = { [ENV_MODULE_ID]: typeof environmentSetupModule }
79
-
80
- /**
81
- * The journey definition. `start` skips the picker when a frame was preselected;
82
- * transitions are the linear pick → review → preflight → save chain, terminating
83
- * with `complete` off the save step's `advance`. Back-navigation is handled by the
84
- * entries' `allowBack`, not explicit transitions.
85
- */
86
- export const environmentSetupJourney = defineJourney<EnvModules, EnvSetupState>()({
87
- id: 'environment-setup',
88
- version: '1.0.0',
89
- initialState: (input: EnvSetupInput) => envInitialState(input),
90
- start: (state, input: EnvSetupInput) =>
91
- envStartStep(state, input) === 'review'
92
- ? ({ module: ENV_MODULE_ID, entry: 'review', input: { frameId: state.frameId } } as const)
93
- : ({ module: ENV_MODULE_ID, entry: 'pick', input: { frameId: state.frameId } } as const),
94
- transitions: {
95
- [ENV_MODULE_ID]: {
96
- pick: {
97
- [ENV_SELECT_EXIT]: (ctx) => ({
98
- next: {
99
- module: ENV_MODULE_ID,
100
- entry: 'review',
101
- input: { frameId: ctx.output.frameId },
102
- } as const,
103
- state: { frameId: ctx.output.frameId },
104
- }),
105
- },
106
- review: {
107
- [ENV_ADVANCE_EXIT]: (ctx) => ({
108
- next: {
109
- module: ENV_MODULE_ID,
110
- entry: envNextAfter('review'),
111
- input: { frameId: ctx.state.frameId },
112
- } as const,
113
- }),
114
- },
115
- preflight: {
116
- [ENV_ADVANCE_EXIT]: (ctx) => ({
117
- next: {
118
- module: ENV_MODULE_ID,
119
- entry: envNextAfter('preflight'),
120
- input: { frameId: ctx.state.frameId },
121
- } as const,
122
- }),
123
- },
124
- // `save` advances to `envNextAfter('save') === 'done'`, i.e. journey completion.
125
- save: {
126
- [ENV_ADVANCE_EXIT]: () => ({ complete: undefined }),
127
- },
128
- },
129
- },
130
- })
79
+ export { environmentSetupJourney }
131
80
 
132
81
  /** Typed launch handle — callers `runtime.start(handle, { frameId })`. */
133
82
  export const environmentSetupHandle = defineJourneyHandle(environmentSetupJourney)
@@ -4808,6 +4808,7 @@
4808
4808
  }
4809
4809
  },
4810
4810
  "environmentWizard": {
4811
+ "progress": "Schritt {index} von {total}",
4811
4812
  "title": "Eine Testumgebung einrichten",
4812
4813
  "subtitle": "Erkenne, prüfe und speichere ein Docker-Compose-Rezept, damit der Deployer es bereitstellt.",
4813
4814
  "recommended": "empfohlen",
@@ -4941,6 +4941,7 @@
4941
4941
  }
4942
4942
  },
4943
4943
  "environmentWizard": {
4944
+ "progress": "Step {index} of {total}",
4944
4945
  "title": "Set up a test environment",
4945
4946
  "subtitle": "Detect, review, and save a Docker Compose recipe so the Deployer provisions it.",
4946
4947
  "recommended": "recommended",
@@ -4800,6 +4800,7 @@
4800
4800
  }
4801
4801
  },
4802
4802
  "environmentWizard": {
4803
+ "progress": "Paso {index} de {total}",
4803
4804
  "title": "Configurar un entorno de pruebas",
4804
4805
  "subtitle": "Detecta, revisa y guarda una receta de Docker Compose para que el Deployer la aprovisione.",
4805
4806
  "recommended": "recomendado",
@@ -4800,6 +4800,7 @@
4800
4800
  }
4801
4801
  },
4802
4802
  "environmentWizard": {
4803
+ "progress": "Étape {index} sur {total}",
4803
4804
  "title": "Configurer un environnement de test",
4804
4805
  "subtitle": "Détectez, vérifiez et enregistrez une recette Docker Compose pour que le Deployer la provisionne.",
4805
4806
  "recommended": "recommandé",
@@ -4811,6 +4811,7 @@
4811
4811
  }
4812
4812
  },
4813
4813
  "environmentWizard": {
4814
+ "progress": "שלב {index} מתוך {total}",
4814
4815
  "title": "הגדרת סביבת בדיקות",
4815
4816
  "subtitle": "זהו, סקרו ושמרו מתכון Docker Compose כדי שה-Deployer יקצה אותו.",
4816
4817
  "recommended": "מומלץ",
@@ -4808,6 +4808,7 @@
4808
4808
  }
4809
4809
  },
4810
4810
  "environmentWizard": {
4811
+ "progress": "Passaggio {index} di {total}",
4811
4812
  "title": "Configura un ambiente di test",
4812
4813
  "subtitle": "Rileva, rivedi e salva una ricetta Docker Compose in modo che il Deployer la esegua.",
4813
4814
  "recommended": "consigliato",
@@ -4812,6 +4812,7 @@
4812
4812
  }
4813
4813
  },
4814
4814
  "environmentWizard": {
4815
+ "progress": "ステップ {index} / {total}",
4815
4816
  "title": "テスト環境をセットアップ",
4816
4817
  "subtitle": "Docker Compose レシピを検出・確認・保存して、Deployer がプロビジョニングできるようにします。",
4817
4818
  "recommended": "推奨",
@@ -4800,6 +4800,7 @@
4800
4800
  }
4801
4801
  },
4802
4802
  "environmentWizard": {
4803
+ "progress": "Krok {index} z {total}",
4803
4804
  "title": "Skonfiguruj środowisko testowe",
4804
4805
  "subtitle": "Wykryj, przejrzyj i zapisz przepis Docker Compose, aby Deployer go udostępnił.",
4805
4806
  "recommended": "zalecane",
@@ -4812,6 +4812,7 @@
4812
4812
  }
4813
4813
  },
4814
4814
  "environmentWizard": {
4815
+ "progress": "Adım {index} / {total}",
4815
4816
  "title": "Bir test ortamı kur",
4816
4817
  "subtitle": "Deployer sağlasın diye bir Docker Compose tarifini algıla, gözden geçir ve kaydet.",
4817
4818
  "recommended": "önerilen",
@@ -4800,6 +4800,7 @@
4800
4800
  }
4801
4801
  },
4802
4802
  "environmentWizard": {
4803
+ "progress": "Крок {index} з {total}",
4803
4804
  "title": "Налаштувати тестове середовище",
4804
4805
  "subtitle": "Виявіть, перегляньте та збережіть рецепт Docker Compose, щоб Deployer його забезпечив.",
4805
4806
  "recommended": "рекомендовано",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/app",
3
- "version": "0.145.2",
3
+ "version": "0.146.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",
@@ -18,9 +18,9 @@
18
18
  "access": "public"
19
19
  },
20
20
  "dependencies": {
21
- "@modular-frontend/core": "^0.5.0",
22
- "@modular-vue/core": "^1.4.0",
23
- "@modular-vue/journeys": "^1.3.0",
21
+ "@modular-frontend/core": "^0.6.0",
22
+ "@modular-vue/core": "^1.5.0",
23
+ "@modular-vue/journeys": "^1.4.0",
24
24
  "@modular-vue/nuxt": "^0.4.0",
25
25
  "@modular-vue/runtime": "^1.4.1",
26
26
  "@modular-vue/vue": "^1.4.0",