Files

5.9 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-generators 02 execute 2
02-01
src/generators/rclone-conf.ts
true
CONF-01
truths artifacts key_links
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
path provides exports min_lines
src/generators/rclone-conf.ts buildRcloneConf pure function
buildRcloneConf
25
from to via pattern
src/generators/rclone-conf.ts src/store/types.ts import type { WizardState } from '../store/types' WizardState
from to via pattern
RCLONE_TYPE_MAP rclone backend type strings Record<string, string> lookup 's3-compatible': 's3'
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.

<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>

@.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

From src/store/types.ts:

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:

export type BackendType = 'azureblob' | 's3' | 's3-compatible';

Critical type mapping (from research — verified against rclone.org):

// 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
Task 1: Implement buildRcloneConf src/generators/rclone-conf.ts - 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(...) }` 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.
npm test -- src/generators/rclone-conf.test.ts 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). 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.

<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>

After completion, create `.planning/phases/02-generators/02-02-SUMMARY.md`