dreamboard 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +89 -0
- package/NOTICE +1 -0
- package/README.md +22 -178
- package/dist/{chunk-MP7IBNWW.js → chunk-BMYC6772.js} +577 -38
- package/dist/chunk-BMYC6772.js.map +1 -0
- package/dist/chunk-D4HDZEJT.js +37 -0
- package/dist/chunk-EM7NOFFC.js +19072 -0
- package/dist/chunk-EM7NOFFC.js.map +1 -0
- package/dist/chunk-SET56RVA.js +435 -0
- package/dist/chunk-SET56RVA.js.map +1 -0
- package/dist/{dist-B3R64F6G.js → dist-WJRJNFLI.js} +3 -3
- package/dist/global-config-VQJZ3JOA.js +15 -0
- package/dist/global-config-VQJZ3JOA.js.map +1 -0
- package/dist/index.js +23993 -24387
- package/dist/index.js.map +1 -1
- package/dist/keychain-backend-2DL3C6BS.js +125 -0
- package/dist/keychain-backend-2DL3C6BS.js.map +1 -0
- package/dist/{prompt-GMZABCJC.js → prompt-IV67HSPU.js} +2 -2
- package/dist/scaffold/assets/static/app/tsconfig.framework.json +24 -0
- package/dist/scaffold/assets/static/app/tsconfig.json +3 -0
- package/dist/scaffold/assets/static/ui/App.tsx +22 -0
- package/dist/scaffold/assets/static/ui/index.tsx +12 -0
- package/dist/scaffold/assets/static/ui/style.css +4 -0
- package/dist/scaffold/assets/static/ui/tsconfig.framework.json +31 -0
- package/dist/scaffold/assets/static/ui/tsconfig.json +5 -0
- package/dist/src-K2NK3A4P.js +626 -0
- package/dist/src-K2NK3A4P.js.map +1 -0
- package/package.json +41 -4
- package/skills/dreamboard/SKILL.md +126 -59
- package/skills/dreamboard/references/authoring-lifecycle.md +102 -0
- package/skills/dreamboard/references/board-surfaces.md +36 -0
- package/skills/dreamboard/references/board-topology.md +443 -0
- package/skills/dreamboard/references/boards-and-topology.md +100 -0
- package/skills/dreamboard/references/card-actions.md +107 -0
- package/skills/dreamboard/references/cli.md +120 -0
- package/skills/dreamboard/references/core-concepts.md +514 -0
- package/skills/dreamboard/references/custom-renderers.md +26 -0
- package/skills/dreamboard/references/derived-values.md +55 -0
- package/skills/dreamboard/references/effects.md +111 -0
- package/skills/dreamboard/references/game-contract.md +89 -0
- package/skills/dreamboard/references/game-definition.md +89 -0
- package/skills/dreamboard/references/game-shell.md +80 -0
- package/skills/dreamboard/references/hand-surfaces.md +33 -0
- package/skills/dreamboard/references/index.md +112 -0
- package/skills/dreamboard/references/inputs-and-targets.md +160 -0
- package/skills/dreamboard/references/interactions.md +158 -0
- package/skills/dreamboard/references/manifest-fields.md +137 -0
- package/skills/dreamboard/references/manifest.md +81 -0
- package/skills/dreamboard/references/package-surfaces.md +69 -0
- package/skills/dreamboard/references/phases.md +145 -0
- package/skills/dreamboard/references/prompts-and-choices.md +55 -0
- package/skills/dreamboard/references/quickstart.md +71 -0
- package/skills/dreamboard/references/rule-authoring.md +81 -77
- package/skills/dreamboard/references/setup-bootstrap.md +78 -0
- package/skills/dreamboard/references/stages-and-zones.md +59 -0
- package/skills/dreamboard/references/static-views.md +67 -0
- package/skills/dreamboard/references/table-queries-and-ops.md +103 -0
- package/skills/dreamboard/references/testing-bases.md +147 -0
- package/skills/dreamboard/references/testing-generated-contracts.md +142 -0
- package/skills/dreamboard/references/testing-runtime-assertions.md +124 -0
- package/skills/dreamboard/references/testing-scenarios.md +148 -0
- package/skills/dreamboard/references/testing-ui-tests.md +174 -0
- package/skills/dreamboard/references/testing.md +161 -0
- package/skills/dreamboard/references/ui-architecture.md +137 -0
- package/skills/dreamboard/references/ui-components.md +34 -0
- package/skills/dreamboard/references/views.md +72 -0
- package/skills/dreamboard/references/workspace-layout.md +136 -0
- package/dist/chunk-2H7UOFLK.js +0 -11
- package/dist/chunk-MP7IBNWW.js.map +0 -1
- package/dist/chunk-WM7TY7DV.js +0 -2328
- package/dist/chunk-WM7TY7DV.js.map +0 -1
- package/dist/embedded-harness-IHP7A2ZX.js +0 -344
- package/dist/embedded-harness-IHP7A2ZX.js.map +0 -1
- package/skills/dreamboard/references/adversarial-testing.md +0 -113
- package/skills/dreamboard/references/all-players-tracking.md +0 -75
- package/skills/dreamboard/references/api-reference.md +0 -197
- package/skills/dreamboard/references/app-best-practices.md +0 -98
- package/skills/dreamboard/references/building-your-first-game.md +0 -49
- package/skills/dreamboard/references/hands-vs-decks.md +0 -124
- package/skills/dreamboard/references/manifest-authoring.md +0 -328
- package/skills/dreamboard/references/phase-handlers.md +0 -134
- package/skills/dreamboard/references/scenario-format.md +0 -99
- package/skills/dreamboard/references/test-harness.md +0 -225
- package/skills/dreamboard/references/ui-best-practices.md +0 -156
- package/skills/dreamboard/references/ui-genre-resource-management.md +0 -187
- package/skills/dreamboard/references/ui-genre-trick-taking.md +0 -110
- package/skills/dreamboard/references/ui-genre-worker-placement.md +0 -143
- package/skills/dreamboard/references/ui-style-guide.md +0 -54
- package/skills/dreamboard/scripts/events-extract.mjs +0 -218
- /package/dist/{chunk-2H7UOFLK.js.map → chunk-D4HDZEJT.js.map} +0 -0
- /package/dist/{dist-B3R64F6G.js.map → dist-WJRJNFLI.js.map} +0 -0
- /package/dist/{prompt-GMZABCJC.js.map → prompt-IV67HSPU.js.map} +0 -0
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
# UI Guide: Worker Placement Games
|
|
2
|
-
|
|
3
|
-
Patterns for Agricola, Viticulture, Lords of Waterdeep, Caverna, and similar euro-style worker placement games.
|
|
4
|
-
|
|
5
|
-
## Game characteristics
|
|
6
|
-
|
|
7
|
-
- Players place **worker tokens** on shared **action slots** to gain resources or take actions.
|
|
8
|
-
- Slots may be exclusive (one player per round) or shared.
|
|
9
|
-
- Phases typically include: placement, resolution/harvest, and cleanup.
|
|
10
|
-
- Key UI signals: available slots, slot costs/rewards, number of workers remaining, resource counts.
|
|
11
|
-
|
|
12
|
-
## Recommended SDK components
|
|
13
|
-
|
|
14
|
-
### Primary
|
|
15
|
-
|
|
16
|
-
| Component | Usage |
|
|
17
|
-
| --------------------- | ----------------------------------------------------------------------------------------------------- |
|
|
18
|
-
| `SlotSystem` | Core board — renders all action slots with occupants. Use `layout="grouped"` to organize by category. |
|
|
19
|
-
| `DefaultSlotItem` | Pre-built slot renderer showing name, description, capacity, cost/reward labels. |
|
|
20
|
-
| `DefaultSlotOccupant` | Pre-built worker token display with player color. |
|
|
21
|
-
| `ResourceCounter` | Display each player's resource pool (wood, stone, food, etc.). |
|
|
22
|
-
| `ActionButton` | "Place Worker" button with integrated cost display and affordability check. |
|
|
23
|
-
|
|
24
|
-
### Supporting
|
|
25
|
-
|
|
26
|
-
| Component | Usage |
|
|
27
|
-
| ----------------------------- | ------------------------------------------------------------ |
|
|
28
|
-
| `ActionPanel` / `ActionGroup` | Group available actions (e.g., "Place Worker", "End Turn"). |
|
|
29
|
-
| `CostDisplay` | Show resource costs on slot details. |
|
|
30
|
-
| `PlayerInfo` | Show each player's name, workers remaining, and turn status. |
|
|
31
|
-
| `PhaseIndicator` | Distinguish placement phase from harvest/scoring phases. |
|
|
32
|
-
| `GameEndDisplay` | Final scoring with detailed breakdown. |
|
|
33
|
-
| `Drawer` | Mobile drawer for detailed slot inspection. |
|
|
34
|
-
|
|
35
|
-
### Hooks
|
|
36
|
-
|
|
37
|
-
| Hook | Usage |
|
|
38
|
-
| --------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
39
|
-
| `useSlotSystem(slots, occupants)` | Utility for slot lookups: `getSlot`, `isFull`, `getRemainingCapacity`, `getOccupantsByPlayer`. |
|
|
40
|
-
| `useMyResources()` | Current player's resource pool. |
|
|
41
|
-
| `useGameState` | Get `isMyTurn`, `currentState`, `currentPlayerIds`. |
|
|
42
|
-
| `useAction` | Submit place-worker or end-turn actions. |
|
|
43
|
-
| `useUIArgs` | Get phase-specific data (available slots, worker count, etc.). |
|
|
44
|
-
| `usePlayerInfo` | Map player IDs to names and colors. |
|
|
45
|
-
|
|
46
|
-
## Key patterns
|
|
47
|
-
|
|
48
|
-
### Slot board with placement
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
const { placementPhase } = useUIArgs();
|
|
52
|
-
const slots = placementPhase?.slots ?? [];
|
|
53
|
-
const occupants = placementPhase?.occupants ?? [];
|
|
54
|
-
const availableSlotIds = new Set(placementPhase?.availableSlotIds ?? []);
|
|
55
|
-
const slotApi = useSlotSystem(slots, occupants);
|
|
56
|
-
|
|
57
|
-
<SlotSystem
|
|
58
|
-
slots={slots}
|
|
59
|
-
occupants={occupants}
|
|
60
|
-
layout="grouped"
|
|
61
|
-
renderSlot={(slot, slotOccupants) => (
|
|
62
|
-
<DefaultSlotItem
|
|
63
|
-
name={slot.name}
|
|
64
|
-
description={slot.description}
|
|
65
|
-
capacity={slot.capacity}
|
|
66
|
-
occupantCount={slotOccupants.length}
|
|
67
|
-
isExclusive={slot.exclusive}
|
|
68
|
-
isAvailable={availableSlotIds.has(slot.id)}
|
|
69
|
-
costLabel={formatCost(slot.cost)}
|
|
70
|
-
rewardLabel={formatReward(slot.reward)}
|
|
71
|
-
onClick={() => handlePlaceWorker(slot.id)}
|
|
72
|
-
renderOccupants={() => (
|
|
73
|
-
<div className="flex gap-1">
|
|
74
|
-
{slotOccupants.map((o) => (
|
|
75
|
-
<DefaultSlotOccupant
|
|
76
|
-
key={o.pieceId}
|
|
77
|
-
color={playerColors[o.playerId]}
|
|
78
|
-
label={playerInfo[o.playerId]?.name}
|
|
79
|
-
/>
|
|
80
|
-
))}
|
|
81
|
-
</div>
|
|
82
|
-
)}
|
|
83
|
-
/>
|
|
84
|
-
)}
|
|
85
|
-
/>;
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Resource display
|
|
89
|
-
|
|
90
|
-
```tsx
|
|
91
|
-
const resources = useMyResources();
|
|
92
|
-
|
|
93
|
-
<ResourceCounter
|
|
94
|
-
resources={[
|
|
95
|
-
{
|
|
96
|
-
type: "wood",
|
|
97
|
-
label: "Wood",
|
|
98
|
-
icon: TreePine,
|
|
99
|
-
iconColor: "text-amber-700",
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
type: "stone",
|
|
103
|
-
label: "Stone",
|
|
104
|
-
icon: Mountain,
|
|
105
|
-
iconColor: "text-slate-400",
|
|
106
|
-
},
|
|
107
|
-
{ type: "food", label: "Food", icon: Apple, iconColor: "text-red-400" },
|
|
108
|
-
{ type: "gold", label: "Gold", icon: Coins, iconColor: "text-yellow-400" },
|
|
109
|
-
]}
|
|
110
|
-
counts={resources}
|
|
111
|
-
layout="row"
|
|
112
|
-
/>;
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
### Action buttons with costs
|
|
116
|
-
|
|
117
|
-
```tsx
|
|
118
|
-
<ActionButton
|
|
119
|
-
label="Build Farm"
|
|
120
|
-
cost={{ wood: 2, stone: 1 }}
|
|
121
|
-
currentResources={resources}
|
|
122
|
-
resourceDefs={resourceDefinitions}
|
|
123
|
-
icon={Home}
|
|
124
|
-
onClick={() => actions.buildActions.build({ buildingType: "farm" })}
|
|
125
|
-
/>
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
## UIArgs recommendations
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
// shared/ui-args.ts
|
|
132
|
-
export interface PlacementPhaseUIArgs {
|
|
133
|
-
slots: SlotDefinition[];
|
|
134
|
-
occupants: SlotOccupant[];
|
|
135
|
-
availableSlotIds: string[]; // Slots the current player can legally place on
|
|
136
|
-
workersRemaining: number;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export interface HarvestPhaseUIArgs {
|
|
140
|
-
feedingRequired: number; // Food needed
|
|
141
|
-
currentFood: number;
|
|
142
|
-
}
|
|
143
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
# UI Style Guide
|
|
2
|
-
|
|
3
|
-
This style guide details the design philosophy, visual tokens, and core components for the Dreamboard.games UI SDK. The framework uses a **Hand-Drawn** aesthetic that emphasizes human creativity over corporate polish.
|
|
4
|
-
|
|
5
|
-
## Design Philosophy
|
|
6
|
-
|
|
7
|
-
The Hand-Drawn design style celebrates authentic imperfection and human touch in a digital world. It rejects clinical precision in favor of organic, playful irregularity that evokes sketches on paper, sticky notes on a wall, and napkin diagrams from a brainstorming session.
|
|
8
|
-
|
|
9
|
-
### Core Principles
|
|
10
|
-
|
|
11
|
-
- **No Straight Lines**: Every border, shape, and container uses irregular border-radius values to create wobbly, hand-drawn edges that reject geometric perfection.
|
|
12
|
-
- **Authentic Texture**: The design layer paper grain, dot patterns, and subtle background textures to simulate physical media (notebook paper, post-its, sketch pads).
|
|
13
|
-
- **Playful Rotation**: Elements are deliberately tilted using small rotation transforms (`-rotate-1`, `rotate-2`) to break rigid grid alignment and create casual energy.
|
|
14
|
-
- **Hard Offset Shadows**: Reject soft blur shadows entirely. Use solid, offset box-shadows (like `4px 4px 0px`) to create a cut-paper, layered collage aesthetic.
|
|
15
|
-
- **Handwritten Typography**: Use exclusively handwritten or marker-style fonts (like Kalam for headings and Patrick Hand for body text) that feel human and approachable.
|
|
16
|
-
- **Limited Color Palette**: Stick to pencil blacks (`#2d2d2d`), paper whites (`#fdfbf7`), correction marker red (`#ff4d4d`), post-it yellow (`#fff9c4`), and ballpoint blue (`#2d5da1`).
|
|
17
|
-
- **Intentional Messiness**: Embrace overlap, asymmetry, and visual "mistakes" that make the design feel spontaneous.
|
|
18
|
-
|
|
19
|
-
## CSS Tokens & Utilities
|
|
20
|
-
|
|
21
|
-
The platform provides several global CSS utilities designed for this aesthetic:
|
|
22
|
-
|
|
23
|
-
- **Borders**: `.wobbly-border`, `.wobbly-border-md`, `.wobbly-border-lg` apply the irregular `border-radius` shapes. Used with `border-2`, `border-[3px]`, or `border-[4px]`.
|
|
24
|
-
- **Shadows**: `.hard-shadow`, `.hard-shadow-md`, `.hard-shadow-lg` apply the solid offset shadows. Use `.hard-shadow-sm` for active states (buttons pressing flat).
|
|
25
|
-
|
|
26
|
-
## Implementing in Components
|
|
27
|
-
|
|
28
|
-
When writing or modifying UI components in `ui/` or `ui-sdk/`:
|
|
29
|
-
|
|
30
|
-
### Containers & Cards
|
|
31
|
-
|
|
32
|
-
- Add `wobbly-border-md` or `wobbly-border-lg`.
|
|
33
|
-
- Use `border-[3px] border-border` to give it a thick pencil-like stroke.
|
|
34
|
-
- Apply `bg-[#fdfbf7]` (warm paper) or `bg-white`.
|
|
35
|
-
- Add a solid shadow with `hard-shadow` or `hard-shadow-lg`.
|
|
36
|
-
- Slightly rotate the element with `rotate-1` or `-rotate-1`.
|
|
37
|
-
|
|
38
|
-
### Buttons
|
|
39
|
-
|
|
40
|
-
- Use `wobbly-border`.
|
|
41
|
-
- Normal state: `border-[3px] border-border bg-[#fdfbf7] text-foreground hard-shadow`.
|
|
42
|
-
- Hover state: `hover:bg-primary hover:text-white hover:hard-shadow-sm hover:-translate-y-1`.
|
|
43
|
-
- Active state: `active:shadow-none active:translate-y-1 active:translate-x-1`.
|
|
44
|
-
- Secondary variants can use `bg-[#e5e0d8]` or `bg-[#fff9c4]`.
|
|
45
|
-
|
|
46
|
-
### Typography
|
|
47
|
-
|
|
48
|
-
- Add `font-sans` for standard handwritten text or `font-display` for bold marker headings.
|
|
49
|
-
- Make things bold! `font-bold` works well with handwritten fonts to make them legible.
|
|
50
|
-
|
|
51
|
-
### Decoration
|
|
52
|
-
|
|
53
|
-
- For emphasis, wrap text in a post-it styling: `bg-[#fff9c4] px-2 py-1 border-2 border-border wobbly-border rotate-2 inline-block`.
|
|
54
|
-
- Add "tape" to tops of containers: `<div className="absolute top-2 left-1/2 -translate-x-1/2 w-24 h-6 bg-[#e5e0d8] border border-border opacity-80 backdrop-blur-sm -rotate-2 z-10" />`.
|
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { access, readFile } from "node:fs/promises";
|
|
4
|
-
|
|
5
|
-
const DEFAULT_EVENTS_PATH = ".dreamboard/run/events.ndjson";
|
|
6
|
-
|
|
7
|
-
function printHelp() {
|
|
8
|
-
console.log(`Extract fields from dreamboard run artifacts.
|
|
9
|
-
|
|
10
|
-
Usage:
|
|
11
|
-
node .agents/skills/dreamboard/scripts/events-extract.mjs [options]
|
|
12
|
-
|
|
13
|
-
Options:
|
|
14
|
-
--file, -f <path> NDJSON file path (default: ${DEFAULT_EVENTS_PATH})
|
|
15
|
-
--type <eventType> Filter by event type (repeatable)
|
|
16
|
-
--field <path> Dot path to extract (e.g. message.reason)
|
|
17
|
-
--player <playerId> Filter by player ID across common message fields
|
|
18
|
-
--limit <number> Limit output records
|
|
19
|
-
--no-index Omit line index in output
|
|
20
|
-
--help, -h Show this help
|
|
21
|
-
|
|
22
|
-
Examples:
|
|
23
|
-
node .agents/skills/dreamboard/scripts/events-extract.mjs --type YOUR_TURN
|
|
24
|
-
node .agents/skills/dreamboard/scripts/events-extract.mjs --type ACTION_REJECTED --field message.reason
|
|
25
|
-
node .agents/skills/dreamboard/scripts/events-extract.mjs --player player-2 --field message.availableActions
|
|
26
|
-
`);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function parseCliArgs(argv) {
|
|
30
|
-
const options = {
|
|
31
|
-
filePath: DEFAULT_EVENTS_PATH,
|
|
32
|
-
types: new Set(),
|
|
33
|
-
includeIndex: true,
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
for (let index = 0; index < argv.length; index += 1) {
|
|
37
|
-
const token = argv[index];
|
|
38
|
-
const nextToken = argv[index + 1];
|
|
39
|
-
|
|
40
|
-
if (token === "--help" || token === "-h") {
|
|
41
|
-
printHelp();
|
|
42
|
-
process.exit(0);
|
|
43
|
-
}
|
|
44
|
-
if (token === "--no-index") {
|
|
45
|
-
options.includeIndex = false;
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
if (token === "--file" || token === "-f") {
|
|
49
|
-
if (!nextToken) {
|
|
50
|
-
throw new Error("--file requires a value");
|
|
51
|
-
}
|
|
52
|
-
options.filePath = nextToken;
|
|
53
|
-
index += 1;
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (token === "--type") {
|
|
57
|
-
if (!nextToken) {
|
|
58
|
-
throw new Error("--type requires a value");
|
|
59
|
-
}
|
|
60
|
-
options.types.add(nextToken);
|
|
61
|
-
index += 1;
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
if (token === "--field") {
|
|
65
|
-
if (!nextToken) {
|
|
66
|
-
throw new Error("--field requires a value");
|
|
67
|
-
}
|
|
68
|
-
options.fieldPath = nextToken;
|
|
69
|
-
index += 1;
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
if (token === "--player") {
|
|
73
|
-
if (!nextToken) {
|
|
74
|
-
throw new Error("--player requires a value");
|
|
75
|
-
}
|
|
76
|
-
options.playerId = nextToken;
|
|
77
|
-
index += 1;
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
if (token === "--limit") {
|
|
81
|
-
if (!nextToken) {
|
|
82
|
-
throw new Error("--limit requires a value");
|
|
83
|
-
}
|
|
84
|
-
const parsed = Number.parseInt(nextToken, 10);
|
|
85
|
-
if (!Number.isFinite(parsed) || parsed <= 0) {
|
|
86
|
-
throw new Error("--limit must be a positive integer");
|
|
87
|
-
}
|
|
88
|
-
options.limit = parsed;
|
|
89
|
-
index += 1;
|
|
90
|
-
continue;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
throw new Error(`Unknown argument: ${token}`);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
return options;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function getByPath(value, path) {
|
|
100
|
-
const segments = path.split(".").filter(Boolean);
|
|
101
|
-
let current = value;
|
|
102
|
-
|
|
103
|
-
for (const segment of segments) {
|
|
104
|
-
if (current === null || current === undefined) {
|
|
105
|
-
return undefined;
|
|
106
|
-
}
|
|
107
|
-
if (typeof current !== "object") {
|
|
108
|
-
return undefined;
|
|
109
|
-
}
|
|
110
|
-
current = current[segment];
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
return current;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function extractPlayerCandidates(record) {
|
|
117
|
-
const message = record.message ?? {};
|
|
118
|
-
const players = new Set();
|
|
119
|
-
|
|
120
|
-
const singleCandidates = [
|
|
121
|
-
message.playerId,
|
|
122
|
-
message.targetPlayer,
|
|
123
|
-
message.toUser,
|
|
124
|
-
];
|
|
125
|
-
for (const candidate of singleCandidates) {
|
|
126
|
-
if (typeof candidate === "string") {
|
|
127
|
-
players.add(candidate);
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const listCandidates = [
|
|
132
|
-
message.activePlayers,
|
|
133
|
-
message.previousPlayers,
|
|
134
|
-
message.currentPlayers,
|
|
135
|
-
message.controllablePlayerIds,
|
|
136
|
-
message.eligiblePlayerIds,
|
|
137
|
-
];
|
|
138
|
-
for (const candidate of listCandidates) {
|
|
139
|
-
if (!Array.isArray(candidate)) {
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
for (const item of candidate) {
|
|
143
|
-
if (typeof item === "string") {
|
|
144
|
-
players.add(item);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return [...players];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
function toOutputRecord(record, lineIndex, options) {
|
|
153
|
-
const output = {};
|
|
154
|
-
|
|
155
|
-
if (options.includeIndex) {
|
|
156
|
-
output.index = lineIndex;
|
|
157
|
-
}
|
|
158
|
-
output.observedAt = record.observedAt ?? null;
|
|
159
|
-
output.sessionId = record.sessionId ?? null;
|
|
160
|
-
output.eventId = record.eventId ?? null;
|
|
161
|
-
output.type = record.type ?? null;
|
|
162
|
-
|
|
163
|
-
if (options.fieldPath) {
|
|
164
|
-
output.field = options.fieldPath;
|
|
165
|
-
output.value = getByPath(record, options.fieldPath);
|
|
166
|
-
} else {
|
|
167
|
-
output.message = record.message ?? null;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return output;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
async function main() {
|
|
174
|
-
const options = parseCliArgs(process.argv.slice(2));
|
|
175
|
-
await access(options.filePath);
|
|
176
|
-
|
|
177
|
-
const text = await readFile(options.filePath, "utf8");
|
|
178
|
-
const lines = text
|
|
179
|
-
.split(/\r?\n/u)
|
|
180
|
-
.map((line) => line.trim())
|
|
181
|
-
.filter((line) => line.length > 0);
|
|
182
|
-
|
|
183
|
-
let emitted = 0;
|
|
184
|
-
for (let lineIndex = 0; lineIndex < lines.length; lineIndex += 1) {
|
|
185
|
-
const line = lines[lineIndex];
|
|
186
|
-
let record;
|
|
187
|
-
try {
|
|
188
|
-
record = JSON.parse(line);
|
|
189
|
-
} catch {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (options.types.size > 0 && !options.types.has(record.type ?? "")) {
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
if (options.playerId) {
|
|
198
|
-
const players = extractPlayerCandidates(record);
|
|
199
|
-
if (!players.includes(options.playerId)) {
|
|
200
|
-
continue;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const output = toOutputRecord(record, lineIndex + 1, options);
|
|
205
|
-
console.log(JSON.stringify(output));
|
|
206
|
-
emitted += 1;
|
|
207
|
-
|
|
208
|
-
if (options.limit !== undefined && emitted >= options.limit) {
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
main().catch((error) => {
|
|
215
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
216
|
-
console.error(`events-extract failed: ${message}`);
|
|
217
|
-
process.exit(1);
|
|
218
|
-
});
|
|
File without changes
|
|
File without changes
|
|
File without changes
|