Skip to content

Conversation

@ziyang-lin-404
Copy link
Contributor

No description provided.

… type definitions, and implementation plan for a new centralized configuration system
interface SingleMutation {
id: string;
label: string;
action: string; // Built-in action name
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using string for action names bypasses TypeScript's type checking. A typo like 'createAcount' won't be caught until runtime. Consider using a const enum or union type: type ActionName = 'createAccount' | 'createBucket' | ...

Comment on lines +572 to +664
{
id: 'veeamFolder',
label: 'Prepare Veeam repository: {{name}}',
action: 'putObject',
variables: (form, prev, item) => ({
Bucket: item.name,
Key: `${VEEAM_XML_PREFIX}/`,
Body: '',
}),
},
{
id: 'veeamSystem',
label: 'Enforce Veeam repository: {{name}}',
action: 'putObject',
variables: (form, prev, item) => ({
Bucket: item.name,
Key: `${VEEAM_XML_PREFIX}/system.xml`,
Body: SYSTEM_XML_CONTENT,
ContentType: 'text/xml',
}),
},
{
id: 'veeamCapacity',
label: 'Set repository capacity: {{name}}',
action: 'putObject',
variables: (form, prev, item) => ({
Bucket: item.name,
Key: `${VEEAM_XML_PREFIX}/capacity.xml`,
Body: `<capacity>${item.capacityBytes}</capacity>`,
ContentType: 'text/xml',
}),
when: (form, item) => item.capacity > 0,
},
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mixing low-level S3 operations with high-level business concepts. This exposes low-level S3 API details (putObject, Key, ContentType) in the template. Template authors shouldn't need to know Veeam's internal folder structure. Maybe consider a composite action that encapsulates these operations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not “implementation details” but “business requirements.”

Veeam requires system.xml to be in a specific path—that’s not our implementation choice, it’s Veeam’s specification. Hiding it inside a composite action only shifts the complexity from A to B; it doesn’t eliminate it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right that the Veeam XML structure is a business requirement, not an implementation detail we're hiding. The putObject calls directly reflect Veeam's specification.

My concern was primarily about reuse if multiple Veeam templates (VBR, VBO) share this logic. However, the Composable Blocks pattern (Section 11) already addresses this — Veeam-specific bucketSteps can be extracted as a reusable block rather than a composite action.

The current design also provides better retry granularity at each step, which is a valid trade-off.

Comment on lines 363 to 370
| Field | Description | Source |
|-------|-------------|--------|
| `_sosApiAvailable` | Whether SOS API is available | `useCheckSOSAPIStatus` |
| `_existingAccountArn` | Selected existing account's role ARN | Account selection |
| `_existingAccountId` | Selected existing account's ID | Account selection |
| `_iamUserType` | 'create' or 'existing' | IAM user selection |

These are prefixed with `_` to indicate they are system-injected, not user input.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These _-prefixed fields are "magic" runtime injections invisible in the template definition. This creates hidden dependencies. Consider:

  1. Documenting all injected fields in the template type
  2. Or making injection explicit via a context parameter separate from form

label: string; // Supports template syntax: {{name}}, {{capacity}}
action: string;
variables: LoopVariablesConfig;
when?: (form: FormData, item: any) => boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent when signatures: SingleMutation.when receives (form), but LoopStep.when receives (form, item). This asymmetry could confuse developers. Consider a unified signature or clearly distinct naming (when vs itemWhen).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The signatures differ because the contexts differ - just like Array.reduce(acc, item) vs Array.map(item), and TypeScript will error if you misuse them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants