167 lines
5.9 KiB
Markdown
167 lines
5.9 KiB
Markdown
---
|
|
phase: 02-generators
|
|
plan: 02
|
|
type: execute
|
|
wave: 2
|
|
depends_on:
|
|
- 02-01
|
|
files_modified:
|
|
- src/generators/rclone-conf.ts
|
|
autonomous: true
|
|
requirements:
|
|
- CONF-01
|
|
|
|
must_haves:
|
|
truths:
|
|
- "buildRcloneConf(azureState) produces a valid INI block with type = azureblob and non-empty fields"
|
|
- "buildRcloneConf(s3State) produces type = s3 with provider = AWS"
|
|
- "buildRcloneConf(s3CompatState) produces type = s3 (not s3-compatible) with provider = Other"
|
|
- "Empty optional fields are omitted from the output (no 'sas_url =' line when sas_url is empty)"
|
|
- "All rclone-conf.test.ts assertions pass GREEN"
|
|
artifacts:
|
|
- path: "src/generators/rclone-conf.ts"
|
|
provides: "buildRcloneConf pure function"
|
|
exports: ["buildRcloneConf"]
|
|
min_lines: 25
|
|
key_links:
|
|
- from: "src/generators/rclone-conf.ts"
|
|
to: "src/store/types.ts"
|
|
via: "import type { WizardState } from '../store/types'"
|
|
pattern: "WizardState"
|
|
- from: "RCLONE_TYPE_MAP"
|
|
to: "rclone backend type strings"
|
|
via: "Record<string, string> lookup"
|
|
pattern: "'s3-compatible': 's3'"
|
|
---
|
|
|
|
<objective>
|
|
Implement buildRcloneConf() — the pure TypeScript function that converts WizardState into a valid rclone.conf INI string.
|
|
|
|
Purpose: CONF-01 — the foundational output artifact. Every downstream phase depends on this being correct. Wrong type values or included empty fields silently break rclone remotes.
|
|
Output: src/generators/rclone-conf.ts with all rclone-conf.test.ts assertions green.
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
|
|
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/ROADMAP.md
|
|
@.planning/phases/02-generators/02-01-SUMMARY.md
|
|
@src/store/types.ts
|
|
@src/schemas/registry.ts
|
|
@src/generators/rclone-conf.test.ts
|
|
</context>
|
|
|
|
<interfaces>
|
|
<!-- Types consumed by buildRcloneConf. -->
|
|
|
|
From src/store/types.ts:
|
|
```typescript
|
|
export interface WizardState {
|
|
currentStep: number;
|
|
remote: {
|
|
name: string;
|
|
backendType: BackendType | null; // null must throw
|
|
params: Record<string, string>; // iterate, skip empty values
|
|
};
|
|
deployment: {
|
|
includeInstall: boolean;
|
|
configPath: 'machine-wide' | 'user-profile';
|
|
scriptTargets: ('intune' | 'rmm')[];
|
|
};
|
|
}
|
|
```
|
|
|
|
From src/schemas/registry.ts:
|
|
```typescript
|
|
export type BackendType = 'azureblob' | 's3' | 's3-compatible';
|
|
```
|
|
|
|
Critical type mapping (from research — verified against rclone.org):
|
|
```typescript
|
|
// BackendType → rclone config 'type' value
|
|
// 'azureblob' → 'azureblob'
|
|
// 's3' → 's3'
|
|
// 's3-compatible' → 's3' (NOT 's3-compatible' — rclone does not recognize that string)
|
|
// S3-compatible backends use type = s3, differentiated by provider = Other
|
|
```
|
|
</interfaces>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto" tdd="true">
|
|
<name>Task 1: Implement buildRcloneConf</name>
|
|
<files>src/generators/rclone-conf.ts</files>
|
|
<behavior>
|
|
- azureblob: '[my-azure]\ntype = azureblob\naccount = mystorageaccount\nkey = BASE64KEY\n' (sas_url omitted — empty)
|
|
- s3: contains 'type = s3', 'provider = AWS', 'access_key_id = AKID', 'region = us-east-1'
|
|
- s3-compatible: contains 'type = s3', NOT 'type = s3-compatible', 'provider = Other', 'endpoint = https://s3.wasabisys.com', NOT 'region' line (empty optional field)
|
|
- throws Error if backendType is null
|
|
- throws Error if name is empty string
|
|
- output ends with '\n' (trailing newline — rclone convention)
|
|
- no empty value lines: `if (value !== '') { lines.push(...) }`
|
|
</behavior>
|
|
<action>
|
|
Create src/generators/rclone-conf.ts implementing buildRcloneConf(state: WizardState): string.
|
|
|
|
Follow this exact structure:
|
|
```typescript
|
|
import type { WizardState } from '../store/types';
|
|
|
|
// Maps our BackendType to rclone's internal type string.
|
|
// IMPORTANT: s3-compatible uses 'type = s3' — rclone does not recognize 's3-compatible' as a type.
|
|
// S3-compatible backends are differentiated by provider = Other in params.
|
|
const RCLONE_TYPE_MAP: Record<string, string> = {
|
|
azureblob: 'azureblob',
|
|
s3: 's3',
|
|
's3-compatible': 's3',
|
|
};
|
|
|
|
export function buildRcloneConf(state: WizardState): string {
|
|
const { name, backendType, params } = state.remote;
|
|
if (!backendType) throw new Error('buildRcloneConf: backendType is required');
|
|
if (!name) throw new Error('buildRcloneConf: remote name is required');
|
|
|
|
const rcloneType = RCLONE_TYPE_MAP[backendType];
|
|
const lines: string[] = [`[${name}]`, `type = ${rcloneType}`];
|
|
|
|
for (const [key, value] of Object.entries(params)) {
|
|
if (value !== '') {
|
|
lines.push(`${key} = ${value}`);
|
|
}
|
|
}
|
|
|
|
return lines.join('\n') + '\n';
|
|
}
|
|
```
|
|
|
|
Do NOT import BACKEND_REGISTRY — the function iterates over state.remote.params directly (already contains the right keys from the registry-driven form). Do NOT add any console.log or Write-Host equivalent — credentials must not be logged.
|
|
|
|
Anti-pattern to avoid: Do not write `type = s3-compatible`. The RCLONE_TYPE_MAP lookup handles the translation.
|
|
</action>
|
|
<verify>
|
|
<automated>npm test -- src/generators/rclone-conf.test.ts</automated>
|
|
</verify>
|
|
<done>
|
|
All rclone-conf.test.ts assertions pass GREEN. buildRcloneConf produces correct INI output for all three backends. Empty fields are omitted. Type mapping is correct (s3-compatible → type = s3).
|
|
</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<verification>
|
|
npm test -- src/generators/rclone-conf.test.ts is fully green.
|
|
npm test (full suite) still passes.
|
|
src/generators/rclone-conf.ts is importable from index.ts without TypeScript errors.
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
CONF-01 is satisfied: buildRcloneConf produces valid INI-format rclone.conf strings with correct key/value pairs for all three supported backends (azureblob, s3, s3-compatible).
|
|
</success_criteria>
|
|
|
|
<output>
|
|
After completion, create `.planning/phases/02-generators/02-02-SUMMARY.md`
|
|
</output>
|