Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 120 additions & 140 deletions packages/manager-tools/manager-muk-cli/README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# 🧩 manager-muk-cli

A Node.js CLI designed to **automate maintenance and synchronization** of the `@ovh-ux/manager-ui-kit` package with the **OVHcloud Design System (ODS)**.
It checks for new ODS releases, ensures component parity, and automatically generates missing component structures, hooks, constants, and type passthroughs while preserving test coverage and export integrity.
A Node.js CLI designed to **automate maintenance, synchronization, and documentation** of the `@ovh-ux/manager-ui-kit` with the **OVHcloud Design System (ODS)**.

It checks ODS versions, detects missing components, generates passthroughs (hooks, constants, types), and **synchronizes ODS component documentation** directly from GitHub, using a fully-streamed, cache-aware architecture.

---

## πŸš€ 1. Features Overview

### 1.1 `--check-versions`

Checks npm for new ODS package versions and compares them with those declared in `manager-ui-kit/package.json`.
Checks npm for new ODS package releases and compares them with the versions declared in `manager-ui-kit/package.json`.

```bash
yarn muk-cli --check-versions
```

**Example Output**

```
β„Ή πŸ” Checking ODS package versions...
⚠ Updates available:
Expand All @@ -29,21 +29,19 @@ yarn muk-cli --check-versions

### 1.2 `--check-components`

Compares components between `@ovhcloud/ods-react` and `manager-ui-kit/src/components`, identifying missing or outdated ones.
Compares ODS React components with those in `manager-ui-kit/src/components`, identifying missing or outdated ones.

```bash
yarn muk-cli --check-components
```

**Example Output**

```
β„Ή πŸ“ Found 34 local components
β„Ή πŸ“¦ Fetching ODS React v19.2.0 tarball...
⚠ Missing 8 ODS components:
β„Ή β€’ form-field
β„Ή β€’ form-field-label
β„Ή β€’ form-field-error
β„Ή β€’ range
β„Ή β€’ range-thumb
β„Ή β€’ range-track
Expand All @@ -53,14 +51,13 @@ yarn muk-cli --check-components

### 1.3 `--update-versions`

Updates all ODS dependencies in `package.json` to their latest versions, validates linting, and runs unit tests.
Automatically updates all ODS dependencies in `package.json` to their latest versions, validates, and runs post-update checks.

```bash
yarn muk-cli --update-versions
```

**Example Output**

```
βœ” Updated 3 ODS dependencies
βœ” @ovhcloud/ods-components: 18.6.2 β†’ 18.6.4
Expand All @@ -69,8 +66,7 @@ yarn muk-cli --update-versions
βœ” package.json successfully updated.
```

If all versions are up-to-date:

If all are current:
```
βœ… All ODS versions are already up to date!
✨ Done in 1.78s.
Expand All @@ -80,184 +76,168 @@ If all versions are up-to-date:

### 1.4 `--add-components`

Generates **missing ODS components** and subcomponents directly from the ODS React source tarball.
Generates **missing ODS components** from the ODS React source tarball, preserving hooks, constants, and external types.

```bash
yarn muk-cli --add-components
```

Supports:

* Simple components (without children, e.g. `badge`, `progress-bar`)
* Nested components (with children, e.g. `form-field`, `combobox`, `range`, `datepicker`)
* Hook passthroughs (e.g. `useFormField`)
* Constants passthroughs (e.g. `DatepickerConstants`)
* External type re-exports (from contexts or shared ODS types)
#### Supported Scenarios
* Simple components (no children, e.g. `badge`, `progress-bar`)
* Nested components (with subcomponents, e.g. `form-field`, `datepicker`, `range`)
* Hook passthroughs (`useFormField`)
* Constants passthroughs (`DatepickerConstants`)
* External type re-exports

---

## 🧱 2. Simple Components (Without Children)

A *simple* ODS component has no subcomponents or nested structure.

**Generated Structure**
### 1.5 `--add-components-documentation`

```
progress-bar/
β”œβ”€β”€ __tests__/
β”‚ └── ProgressBar.snapshot.test.tsx
β”œβ”€β”€ ProgressBar.component.tsx
β”œβ”€β”€ ProgressBar.props.ts
└── index.ts
```
Fetches and synchronizes **official ODS component documentation** (`.mdx` files) from the [ovh/design-system](https://github.com/ovh/design-system) repository directly into `manager-wiki`.

**Component**

```tsx
import { ProgressBar as OdsProgressBar } from '@ovhcloud/ods-react';
import { ProgressBarProps } from './ProgressBar.props';
```bash
yarn muk-cli --add-components-documentation
```

#### 🧠 What It Does
1. Detects the latest `@ovhcloud/ods-react` version from npm.
2. Downloads (or reuses) the GitHub tarball for that version.
3. Streams documentation files under `/storybook/stories/components/`.
4. Extracts per-component documentation and writes it to:
```
packages/manager-wiki/stories/manager-ui-kit/components/<component>/base-component-doc/
```
5. Caches the tarball for **7 days** to avoid redundant downloads.
6. Synchronizes Storybook base-documents:
```
packages/manager-wiki/stories/manager-ui-kit/base-documents/
```
7. Rewrites imports:
- `../../../src/` β†’ `../../../base-documents/`
- `ods-react/src/` β†’ `@ovhcloud/ods-react`

export const ProgressBar = (props: ProgressBarProps) => <OdsProgressBar {...props} />;
**Example Output**
```

**Index**

```ts
export { ProgressBar } from './ProgressBar.component';
export type { ProgressBarProps } from './ProgressBar.props';
β„Ή πŸ“¦ Starting Design System documentation sync…
β„Ή ℹ️ ODS React latest version: 19.2.1
βœ” πŸ’Ύ Served 85 documentation files from cache.
β„Ή πŸ“ Found existing component: 'accordion'
βœ” βœ… Sync complete β€” 45 new, 42 updated, 171 files streamed.
```

---

## πŸͺœ 3. Nested Components (With Children)

Nested components (e.g. `form-field`, `combobox`, `datepicker`, `range`) contain child components such as `form-field-label` or `datepicker-control`.

The CLI automatically:

1. Detects parent–child relationships
2. Generates base and subcomponent folders
3. Determines prop inheritance (own vs parent type)
4. Detects if components **have or lack children**
5. Creates passthroughs for hooks, constants, and external types
6. Consolidates all exports into the parent `index.ts`

**Example Structure**
## βš™οΈ 2. Streaming Architecture

### 2.1 High-Level Flow
```
form-field/
β”œβ”€β”€ __tests__/
β”‚ └── FormField.snapshot.test.tsx
β”œβ”€β”€ form-field-label/
β”‚ └── FormFieldLabel.component.tsx
β”œβ”€β”€ form-field-helper/
β”‚ └── FormFieldHelper.component.tsx
β”œβ”€β”€ form-field-error/
β”‚ └── FormFieldError.component.tsx
β”œβ”€β”€ constants/
β”‚ └── FormFieldConstants.ts
β”œβ”€β”€ hooks/
β”‚ └── useFormField.ts
β”œβ”€β”€ FormField.component.tsx
β”œβ”€β”€ FormField.props.ts
└── index.ts
GitHub tarball (.tar.gz)
β”‚
β”œβ”€β–Ά streamTarGz()
β”œβ”€β–Ά extractDesignSystemDocs()
β”œβ”€β–Ά createAsyncQueue()
└─▢ streamComponentDocs()
```

**Parent Index**

```ts
export { FormField, type FormFieldProps } from './FormField.component';
export { FormFieldError } from './form-field-error/FormFieldError.component';
export { FormFieldHelper } from './form-field-helper/FormFieldHelper.component';
export { FormFieldLabel } from './form-field-label/FormFieldLabel.component';
export * from './hooks/useFormField';
export * from './constants/FormFieldConstants';
### 2.2 Core Streaming Functions
#### Stream Extraction
```js
pipeline(
https.get(url),
zlib.createGunzip(),
tar.extract({ onentry(entry) { ... } })
);
```
Each `entry` is processed **as it’s read** β€” no full buffering.

---

### 3.1 Detection Logic

| Detection Type | Logic | Examples |
| ------------------ | ------------------------------------------------------------------------- | ------------------------------------------------------- |
| **Children** | Detects `PropsWithChildren`, `children:` props, or `props.children` usage | Differentiates with vs without children |
| **Subcomponent** | Scans ODS index exports to build parent–child tree | `form-field`, `datepicker` |
| **Hooks** | Detects any export containing `use` prefix | Generates `hooks/use<Component>.ts` passthrough |
| **Constants** | Extracts all non-type exports from `constants` paths | Creates `constants/<Component>Constants.ts` passthrough |
| **External Types** | Detects `type` or `interface` exports from non-component paths | Appends imports/exports in `.props.ts` |

---
#### Stream Bridge
```js
const queue = createAsyncQueue();
await extractDesignSystemDocs({ onFileStream: q.push });
await streamComponentDocs(queue);
```
Manages concurrency and backpressure.

### 3.2 Behavior Summary
#### Stream Consumer
```js
await pipeline(fileStream, fs.createWriteStream(destFile));
```
Backpressure-safe, cleans up on error.

| Type | Structure | Children | Hooks | Constants | Types | Index Linking | Test Coverage |
| --------------------- | -------------------- | -------- | -------- | --------- | ------------- | ------------- | --------------- |
| **Simple Component** | Single folder | No | Optional | Optional | Own | Root index | Snapshot |
| **Nested Component** | Parent + children | Yes/No | Auto | Auto | Parent or Own | Parent index | Snapshot + Spec |
| **Invalid Component** | Not found in tarball | β€” | β€” | β€” | β€” | Skipped | None |
#### Cache Layer
```
target/.cache/ods-docs/
β”œβ”€β”€ ods-docs-meta.json
└── ods-docs-files.json
```
TTL: 7 days β€” fully reusable offline.

---

## βš™οΈ 4. Architecture Overview

## 🧱 3. Codebase Layout
```
manager-muk-cli/
β”œβ”€ src/
β”‚ β”œβ”€ commands/
β”‚ β”‚ β”œβ”€ check-versions.js
β”‚ β”‚ β”œβ”€ check-components.js
β”‚ β”‚ β”œβ”€ update-version.js
β”‚ β”‚ └─ add-components.js
β”‚ β”œβ”€ core/
β”‚ β”‚ β”œβ”€ component-utils.js
β”‚ β”‚ β”œβ”€ ods-tarball-utils.js
β”‚ β”‚ β”œβ”€ file-utils.js
β”‚ β”‚ └─ tasks-utils.js
β”‚ β”œβ”€ config/
β”‚ β”‚ └─ muk-config.js
β”‚ └─ utils/
β”‚ β”œβ”€ log-manager.js
β”‚ └─ json-utils.js
└─ target/.cache/ods-docs/
```

---

## 🧠 5. Design Principles
## 🧠 4. Design Principles

| Principle | Description |
| ----------------------- | ---------------------------------------------------- |
| **Modular CLI** | Each command is standalone and composable |
| **Granular Heuristics** | Detects children, hooks, constants, and type exports |
| **Idempotent Safety** | Prevents overwriting or duplication |
| **Verbose Logging** | Colorized emoji logs for transparency |
| Principle | Description |
|------------|--------------|
| **Streaming-first** | All I/O ops use Node streams |
| **Memory-safe** | Constant memory footprint |
| **Composable** | Modular, small functions |
| **Idempotent** | Deterministic results |
| **Offline-safe** | Cache-first retry |
| **Verbose logging** | Emoji logs for visibility |
| **Configurable** | Rewrite rules in `muk-config.js` |

---

## βœ… 6. Advantages
## βœ… 5. Advantages
* πŸ” Auto-synced ODS documentation and base-docs
* ⚑ Cached and resumable (7-day TTL)
* 🧩 Full parity with ODS React components
* 🧠 Low-memory async pipeline
* 🧱 Modular, testable, CI-ready
* πŸ”§ Configurable rewriting rules

---

* Detects components **with and without children**
* Automatically generates **hooks**, **constants**, and **external types** passthroughs
* Builds fully linked exports for parent and subcomponents
* Modularized, reusable, and testable architecture
* Caches and reuses ODS tarball during execution
## 🧩 6. Cache Troubleshooting
```bash
rm -rf packages/manager-tools/manager-muk-cli/target/.cache/ods-docs
```
Rebuilds clean cache on rerun.

---

## 🧩 7. Example Output (Range + FormField)
## 🧩 7. Configuration Extraction

```
β„Ή πŸ“¦ Fetching ODS React v19.2.0 tarball...
πŸ‘Ά form-field supports children
🚫 range has no children
🧩 form-field-error exports its own Prop type
πŸͺ Created hook passthrough for FormField (1 identifier)
βš™οΈ Created constants passthrough for Datepicker (4 identifiers)
βœ” Component structure ready for FormField
βœ” Component structure ready for Range
`muk-config.js` centralizes regex, rewrite, and Storybook folder logic.

```js
export const MUK_IMPORT_REWRITE_RULES = [
{
name: 'base-documents',
pattern: /((?:\..\/){2,3})src\//g,
replacer: (_, prefix) => `${prefix}base-documents/`,
},
{
name: 'ods-react',
pattern: /(['"])[^'"]*ods-react\/src[^'"]*/g,
replacer: (_, quote) => `${quote}@ovhcloud/ods-react`,
},
];
```

---

## πŸͺͺ 8. License

BSD-3-Clause Β© OVH SAS
Loading
Loading