# API Reference: SBlueprint

`SBlueprint` is the method-chain class used in ApexBlueprint to declare **a blueprint for a single record**. You start from `of(...)`, then stack values, identifiers, parent-child relationships, bulk generation, and references via the chain, and finally hand it to `SOrchestrator` to execute.

For usage and typical scenarios, see [Declaring a Single Record with SBlueprint](/apex-stem/docs/apex-blueprint-sblueprint-guide) and [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk).

## Static Factory

| Method | Purpose |
|---|---|
| `SBlueprint.of(System.Type recordType)` | The starting point of an SBlueprint. Declare the target SObject type, in the form `SBlueprint.of(Account.class)` |

Passing `null` or a non-SObject type to `recordType` raises an exception.

## Value Setters (Set & Template)

| Method | Purpose |
|---|---|
| `set(String fieldName, Object value)` | Set a value on a single field. Subsequent calls to the same field follow "last wins". Can override values set by `template` |
| `set(String fieldName, Object value, Integer startAt, Integer interval)` | Specify the **start** and **step** of the `{#}` placeholder. `set('Name', 'Acc-{#}', 10, 2)` → `'Acc-10'` / `'Acc-12'` / `'Acc-14'` |
| `template(Map<String, Object> templateMap)` | Apply a Map of default values all at once. Recommended in combination with the practice of consolidating shared settings (RecordType, required fields) into `Blueprints.cls` |

Passing a **negative value** to `startAt` / `interval` raises an exception.

```apex
SBlueprint accountBp = SBlueprint.of(Account.class)
    .template(Blueprints.accBasic())     // shared defaults
    .set('Name', 'CustomName')              // individual override
    .set('Index', 'No.{#}', 1, 1);          // {#} sequence
```

## Identifier (Alias)

| Method | Purpose |
|---|---|
| `alias(String aliasName)` | Attach a unique reference name to this blueprint. Later, it can be referenced via `.use(alias, ...)` or `SOrchestrator.getByAlias(alias)` |
| `alias(String aliasName, Integer startAt)` | For aliases containing `{#}`, specify the start of expansion |
| `alias(String aliasName, Integer startAt, Integer interval)` | Specify the start and step |

Aliases **must be unique** within `SOrchestrator`; duplicates raise `Duplicate alias detected` at runtime. When combining with `.times(n)`, use `{#}`-bearing aliases like `'con_{#}'` so that unique values are issued after expansion.

```apex
SBlueprint.of(Contact.class)
    .alias('con_{#}')        // con_1 / con_2 / con_3
    .times(3);
```

## Reference (Use)

A multi-purpose API for mapping a value from another blueprint into a field on this one. Usable both for "copying an Id into a child's lookup (creating a relationship)" and "copying an arbitrary field value".

| Method | Purpose |
|---|---|
| `use(String aliasName, String fromField, String toField)` | The basic form. Copy `fromField` from the blueprint named `aliasName` into this blueprint's `toField` |
| `use(String aliasName, String fromField, String toField, Integer startAt)` | When referencing a `{#}`-bearing alias, specify the start of expansion |
| `use(String aliasName, String fromField, String toField, Integer startAt, Integer interval)` | Specify the start and step |

Passing a **negative value** to `startAt` / `interval` raises an exception. For detailed usage and "uneven mapping" patterns, see [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk).

```apex
SBlueprint.of(Contact.class)
    .use('acc_{#}', 'Id', 'AccountId', 6)   // reference acc_6 to acc_10
    .alias('con_{#}', 6)                    // children also start from 6
    .times(5);
```

## Bulk Generation (Times)

| Method | Purpose |
|---|---|
| `times(Integer n)` | Generate `n` copies of the same blueprint. Passing `n <= 0` raises an exception |

Using `.times(n)` **inside nested `.withChildren(...)`** causes record counts to multiply across hierarchies (parent 2 × child 2 = 4 children). See [Relations, Bulk Generation, and Reference Patterns > Multiplication](/apex-stem/docs/apex-blueprint-relations-and-bulk).

## Ordering-Only Dependency (After)

| Method | Purpose |
|---|---|
| `after(String alias)` | Declares only "insert this in a later layer than that alias", with no value copied |
| `after(String alias, Integer startAt)` | Sets the starting number when referencing an alias containing `{#}` |
| `after(String alias, Integer startAt, Integer interval)` | Sets the starting number and step |

`use()` exists to build a reference, so it always carries a value. Use `after()` when **you don't want the value but do need the order** — for example when a trigger requires that A already exists before B lands.

```apex
SOrchestrator.start()
  .add(SBlueprint.of(Account.class).template(Blueprints.accBasic()).alias('acc'))
  .add(
    SBlueprint.of(Contact.class)
      .set('LastName', 'Yamada')
      .after('acc')   // just place it in a later layer than acc; copy nothing
  );
```

## Owner & Sharing (Owner & Share)

| Method | Purpose |
|---|---|
| `owner(User user)` | Sets the record owner. Sugar for `set('OwnerId', user.Id)` |
| `sharedWith(User user, String accessLevel)` | **Declares a manual share as a final state.** `accessLevel` is `'Read'` or `'Edit'` |

Writing `sharedWith` makes `create()` **auto-generate a sibling blueprint** (`Foo__Share` / `AccountShare`) that is inserted one layer after the record itself. The parent Id wiring is automatic too.

These live on the blueprint because "who owns this record, and who can see it" is **part of the declared final state**, exactly like a field value.

```apex
// Owned by an admin, rep gets Read only — the "hostile data" of a runAs audit test
SOrchestrator.start()
  .add(
    SBlueprint.of(Invoice__c.class).alias('inv')
      .owner(admin)
      .sharedWith(rep, 'Read')
  );
```

It composes with `times` / nesting / `{Pn}` (a child's share multiplies along with the child). An object whose OWD is Public, a share aimed at the owner itself, and an invalid `accessLevel` are all rejected **fail-fast**.

## Parent-Child Relationships

| Method | Purpose |
|---|---|
| `withChildren(SBlueprint child)` | Nest children inside the parent blueprint. The parent Id is automatically copied into the child's lookup. To place children of different SObject types under the same parent, call multiple times: `.withChildren(...).withChildren(...)` |
| `parentIdField(String fieldName)` | When the child has multiple lookups, specify which one receives the parent Id. Not needed when the lookup is unambiguous |

```apex
SBlueprint.of(Account.class)
    .alias('acc')
    .withChildren(
        SBlueprint.of(Contact.class)
            .parentIdField('AccountId')      // specify when multiple lookups exist
            .set('LastName', 'TestContact')
    );
```

## Placeholders

Special placeholders that can be used inside string arguments to `.set` / `.alias` / `.use`.

| Placeholder | Expansion Rule |
|---|---|
| `{#}` | Numeric sequence `1`, `2`, `3`, .... Expanded for `n` copies via `.times(n)`. `startAt` / `interval` change the start and step |
| `{A}` | Uppercase alphabetic sequence `'A'`, `'B'`, `'C'`, ... |
| `{a}` | Lowercase alphabetic sequence `'a'`, `'b'`, `'c'`, ... |
| `{P0}` / `{P1}` / `{P2}` / ... | Hierarchically resolves "the true parent for me" using **absolute depth from the root**. Mostly used as the first argument to `.use('{P1}', ...)` to reference the true parent |

`{P0}` ~ `{Pn}` are the structural solution to the problem where, in nested structures with `.times(...)` at each tier, the `{#}` expansion of an alias alone cannot identify "the true parent for me". For motivation and mechanics, see [Relations, Bulk Generation, and Reference Patterns > {P0} / {P1} / ...](/apex-stem/docs/apex-blueprint-relations-and-bulk).

## Common Exceptions

Errors the framework detects are thrown as **`ApexBlueprintException`**.

| Situation | Exception type / message (excerpt) |
|---|---|
| `of(...)` with null or a non-SObject type | `ApexBlueprintException`: invalid type |
| `times(0)` or below | `ApexBlueprintException`: `Times must be greater than 0` |
| Negative value for `startAt` / `interval` on `set` / `alias` / `use` | `ApexBlueprintException`: negative value not allowed |
| Duplicate alias (at `create()` time) | `ApexBlueprintException`: `Duplicate alias detected` |
| Reference to a non-existent alias (typo in `use`, at `create()` time) | `ApexBlueprintException`: `Circular or invalid reference detected` |
| Ambiguity with multiple lookups (no `parentIdField`, at `create()` time) | `ApexBlueprintException`: `multiple parent relationships with the same parent object` |
| Field application failure (non-existent / formula / auto-number / non-createable / type mismatch) | `ApexBlueprintException`: with diagnostics (`Reason:` for the cause, `Provided:` for the value) |
| Missing required field or validation-rule violation | **A plain `DmlException`, unchanged** |

### The exception type tells you where to look

When `create()` fails, **the type of the exception is itself the diagnosis**.

- **`ApexBlueprintException`** = a mistake in the declaration. **Fix the test code**
- **`DmlException`** = the org refused the insert. **Fix the template or the org configuration**

Field-application errors are diagnosed all the way down to "which blueprint (alias), through which path (`set` / `template` / `use`), and why (non-existent / formula / auto-number / non-createable / type mismatch)".

> ⚠️ This is a breaking change in v2.0.0. Previously a plain `DmlException` was thrown, so **existing `catch (DmlException)` blocks will no longer catch these**. Review your catch clauses when migrating.

## Related Documents

- [Declaring a Single Record with SBlueprint](/apex-stem/docs/apex-blueprint-sblueprint-guide): How to use the five core methods
- [Relations, Bulk Generation, and Reference Patterns](/apex-stem/docs/apex-blueprint-relations-and-bulk): Applications of `withChildren` / `times` / `{P0}` etc.
- [API Reference: SOrchestrator](/apex-stem/docs/apex-blueprint-api-sorchestrator): The execution engine API
- [Back to the ApexBlueprint Guide](/apex-stem/docs/apex-blueprint-guide)
