feat(bgm): model setup as ordered placements
Replace the path->parts setup map with an ordered list of placements, each moving its parts to a path. Entries apply in order, so a part listed in a later placement ends up on that placement's path.
This commit is contained in:
@@ -103,6 +103,8 @@ surfaces:
|
||||
- board#harbor
|
||||
- board#player
|
||||
setup:
|
||||
/dock/0: harbor:token#wood
|
||||
/deck: harbor:token#grain
|
||||
- path: /dock/0
|
||||
parts: harbor:token#wood
|
||||
- path: /deck
|
||||
parts: harbor:token#grain
|
||||
```
|
||||
@@ -48,5 +48,6 @@ role: setup
|
||||
type: game
|
||||
id: main
|
||||
setup:
|
||||
/factory/0: azul:tile#blue
|
||||
- path: /factory/0
|
||||
parts: azul:tile#blue
|
||||
```
|
||||
@@ -53,6 +53,8 @@ role: setup
|
||||
type: game
|
||||
id: main
|
||||
setup:
|
||||
/dock/0: harbor:token#wood
|
||||
/deck: harbor:token#grain
|
||||
- path: /dock/0
|
||||
parts: harbor:token#wood
|
||||
- path: /deck
|
||||
parts: harbor:token#grain
|
||||
```
|
||||
|
||||
@@ -55,10 +55,10 @@ describe('collectPackages', () => {
|
||||
expect([...harbor.setups.keys()]).toEqual(['game#main']);
|
||||
const setup = harbor.setups.get('game#main')!;
|
||||
expect(setup.surfaces).toEqual(['board#harbor', 'board#player']);
|
||||
expect(setup.setup).toEqual({
|
||||
'/dock/0': 'harbor:token#wood',
|
||||
'/deck': 'harbor:token#grain',
|
||||
});
|
||||
expect(setup.setup).toEqual([
|
||||
{ path: '/dock/0', parts: 'harbor:token#wood' },
|
||||
{ path: '/deck', parts: 'harbor:token#grain' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('scopes include patterns to the package declaration directory', () => {
|
||||
|
||||
@@ -60,11 +60,18 @@ const surfaceSchema = z.object({
|
||||
layout: z.array(route),
|
||||
});
|
||||
|
||||
const setupValue = z.union([z.string(), z.array(z.string())]);
|
||||
|
||||
const setupPlacement = z.object({
|
||||
path: z.string(),
|
||||
parts: setupValue,
|
||||
});
|
||||
|
||||
const setupSchema = z.object({
|
||||
type: z.string().min(1),
|
||||
id: z.string().min(1),
|
||||
surfaces: z.array(z.string()).optional(),
|
||||
setup: z.record(z.string(), z.union([z.string(), z.array(z.string())])),
|
||||
setup: z.array(setupPlacement),
|
||||
});
|
||||
|
||||
const packageSchema = z.object({
|
||||
|
||||
@@ -157,13 +157,25 @@ export interface Surface {
|
||||
|
||||
export type SetupValue = string | string[];
|
||||
|
||||
/** Seeds the state store: the enabled surfaces and a map from path to parts. */
|
||||
/**
|
||||
* One setup placement: move `parts` to `path`. Entries are applied in order,
|
||||
* so a part listed in a later entry ends up on that entry's path.
|
||||
*/
|
||||
export interface SetupPlacement {
|
||||
/** The path key to place the parts on. */
|
||||
path: string;
|
||||
/** Parts to place: a part id, a bare type (expands to all of that type), or a list of either. */
|
||||
parts: SetupValue;
|
||||
}
|
||||
|
||||
/** Seeds the state store: the enabled surfaces and an ordered list of placements. */
|
||||
export interface Setup {
|
||||
type: string;
|
||||
id: string;
|
||||
/** Surfaces (`type#id` refs) enabled at the start; omitted = all enabled. */
|
||||
surfaces?: string[];
|
||||
setup: Record<string, SetupValue>;
|
||||
/** Ordered placements; each moves its parts to its path. */
|
||||
setup: SetupPlacement[];
|
||||
}
|
||||
|
||||
export type Role = 'package' | 'part' | 'surface' | 'setup';
|
||||
|
||||
Reference in New Issue
Block a user