qnce-engine 1.3.2 → 1.4.1
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/README.md +134 -2
- package/dist/adapters/contracts.d.ts +1 -1
- package/dist/adapters/contracts.d.ts.map +1 -1
- package/dist/adapters/storage/MockAdapters.d.ts +89 -0
- package/dist/adapters/storage/MockAdapters.d.ts.map +1 -0
- package/dist/adapters/storage/MockAdapters.js +109 -0
- package/dist/adapters/storage/MockAdapters.js.map +1 -0
- package/dist/adapters/story/CustomJSONAdapter.d.ts +1 -1
- package/dist/adapters/story/CustomJSONAdapter.d.ts.map +1 -1
- package/dist/adapters/story/CustomJSONAdapter.js +20 -14
- package/dist/adapters/story/CustomJSONAdapter.js.map +1 -1
- package/dist/adapters/story/InkAdapter.d.ts +1 -1
- package/dist/adapters/story/InkAdapter.d.ts.map +1 -1
- package/dist/adapters/story/InkAdapter.js +7 -10
- package/dist/adapters/story/InkAdapter.js.map +1 -1
- package/dist/adapters/story/TwisonAdapter.d.ts +1 -1
- package/dist/adapters/story/TwisonAdapter.d.ts.map +1 -1
- package/dist/adapters/story/TwisonAdapter.js +2 -2
- package/dist/adapters/story/TwisonAdapter.js.map +1 -1
- package/dist/cli/audit.js +1 -0
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/import.d.ts.map +1 -1
- package/dist/cli/import.js +31 -20
- package/dist/cli/import.js.map +1 -1
- package/dist/cli/init.js +1 -0
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/perf.d.ts.map +1 -1
- package/dist/cli/perf.js +30 -0
- package/dist/cli/perf.js.map +1 -1
- package/dist/cli/play.d.ts.map +1 -1
- package/dist/cli/play.js +90 -77
- package/dist/cli/play.js.map +1 -1
- package/dist/engine/condition.d.ts +25 -3
- package/dist/engine/condition.d.ts.map +1 -1
- package/dist/engine/condition.js +358 -64
- package/dist/engine/condition.js.map +1 -1
- package/dist/engine/core.d.ts +93 -1
- package/dist/engine/core.d.ts.map +1 -1
- package/dist/engine/core.js +405 -33
- package/dist/engine/core.js.map +1 -1
- package/dist/engine/demo-story.d.ts +1 -0
- package/dist/engine/demo-story.d.ts.map +1 -1
- package/dist/engine/demo-story.js +1 -0
- package/dist/engine/demo-story.js.map +1 -1
- package/dist/engine/error-factory.d.ts +86 -0
- package/dist/engine/error-factory.d.ts.map +1 -0
- package/dist/engine/error-factory.js +87 -0
- package/dist/engine/error-factory.js.map +1 -0
- package/dist/engine/errors.d.ts +3 -0
- package/dist/engine/errors.d.ts.map +1 -1
- package/dist/engine/errors.js +3 -0
- package/dist/engine/errors.js.map +1 -1
- package/dist/engine/validation.js +1 -1
- package/dist/engine/validation.js.map +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/react.d.ts +20 -3
- package/dist/integrations/react.d.ts.map +1 -1
- package/dist/integrations/react.js +15 -2
- package/dist/integrations/react.js.map +1 -1
- package/dist/narrative/branching/models.d.ts +1 -0
- package/dist/narrative/branching/models.d.ts.map +1 -1
- package/dist/narrative/branching/models.js.map +1 -1
- package/dist/performance/AdaptiveControllers.d.ts +51 -0
- package/dist/performance/AdaptiveControllers.d.ts.map +1 -0
- package/dist/performance/AdaptiveControllers.js +87 -0
- package/dist/performance/AdaptiveControllers.js.map +1 -0
- package/dist/performance/ContextPool.d.ts +1 -0
- package/dist/performance/ContextPool.d.ts.map +1 -0
- package/dist/performance/ContextPool.js +2 -0
- package/dist/performance/ContextPool.js.map +1 -0
- package/dist/performance/HotReloadDelta.d.ts +5 -0
- package/dist/performance/HotReloadDelta.d.ts.map +1 -1
- package/dist/performance/HotReloadDelta.js +18 -4
- package/dist/performance/HotReloadDelta.js.map +1 -1
- package/dist/performance/ObjectPool.d.ts.map +1 -1
- package/dist/performance/ObjectPool.js +4 -1
- package/dist/performance/ObjectPool.js.map +1 -1
- package/dist/performance/PerfReporter.d.ts +69 -0
- package/dist/performance/PerfReporter.d.ts.map +1 -1
- package/dist/performance/PerfReporter.js +314 -28
- package/dist/performance/PerfReporter.js.map +1 -1
- package/dist/performance/ThreadPool.d.ts +5 -0
- package/dist/performance/ThreadPool.d.ts.map +1 -1
- package/dist/performance/ThreadPool.js +33 -5
- package/dist/performance/ThreadPool.js.map +1 -1
- package/dist/persistence/StorageAdapters.d.ts.map +1 -1
- package/dist/persistence/StorageAdapters.js +13 -19
- package/dist/persistence/StorageAdapters.js.map +1 -1
- package/dist/qnce-engine.d.ts +2258 -0
- package/dist/quantum/entangler.d.ts +13 -0
- package/dist/quantum/entangler.d.ts.map +1 -0
- package/dist/quantum/entangler.js +24 -0
- package/dist/quantum/entangler.js.map +1 -0
- package/dist/quantum/flags.d.ts +24 -0
- package/dist/quantum/flags.d.ts.map +1 -0
- package/dist/quantum/flags.js +29 -0
- package/dist/quantum/flags.js.map +1 -0
- package/dist/quantum/integration.d.ts +26 -0
- package/dist/quantum/integration.d.ts.map +1 -0
- package/dist/quantum/integration.js +38 -0
- package/dist/quantum/integration.js.map +1 -0
- package/dist/quantum/measurement.d.ts +22 -0
- package/dist/quantum/measurement.d.ts.map +1 -0
- package/dist/quantum/measurement.js +44 -0
- package/dist/quantum/measurement.js.map +1 -0
- package/dist/quantum/phase.d.ts +20 -0
- package/dist/quantum/phase.d.ts.map +1 -0
- package/dist/quantum/phase.js +22 -0
- package/dist/quantum/phase.js.map +1 -0
- package/dist/quantum/types.d.ts +12 -0
- package/dist/quantum/types.d.ts.map +1 -0
- package/dist/quantum/types.js +5 -0
- package/dist/quantum/types.js.map +1 -0
- package/dist/schemas/validateStoryData.d.ts.map +1 -1
- package/dist/schemas/validateStoryData.js +8 -2
- package/dist/schemas/validateStoryData.js.map +1 -1
- package/dist/telemetry/core.d.ts +27 -1
- package/dist/telemetry/core.d.ts.map +1 -1
- package/dist/telemetry/core.js +63 -8
- package/dist/telemetry/core.js.map +1 -1
- package/dist/telemetry/types.d.ts +27 -0
- package/dist/telemetry/types.d.ts.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/dist/ui/__tests__/AutosaveIndicator.test.js +10 -13
- package/dist/ui/__tests__/AutosaveIndicator.test.js.map +1 -1
- package/dist/ui/__tests__/UndoRedoControls.test.js +7 -9
- package/dist/ui/__tests__/UndoRedoControls.test.js.map +1 -1
- package/dist/ui/components/AutosaveIndicator.d.ts +1 -0
- package/dist/ui/components/AutosaveIndicator.d.ts.map +1 -1
- package/dist/ui/components/AutosaveIndicator.js +2 -1
- package/dist/ui/components/AutosaveIndicator.js.map +1 -1
- package/dist/ui/components/UndoRedoControls.d.ts +1 -0
- package/dist/ui/components/UndoRedoControls.d.ts.map +1 -1
- package/dist/ui/components/UndoRedoControls.js +1 -0
- package/dist/ui/components/UndoRedoControls.js.map +1 -1
- package/dist/ui/hooks/useKeyboardShortcuts.d.ts +1 -0
- package/dist/ui/hooks/useKeyboardShortcuts.d.ts.map +1 -1
- package/dist/ui/hooks/useKeyboardShortcuts.js +17 -5
- package/dist/ui/hooks/useKeyboardShortcuts.js.map +1 -1
- package/dist/ui/types.d.ts +6 -0
- package/dist/ui/types.d.ts.map +1 -1
- package/dist/ui/types.js +1 -0
- package/dist/ui/types.js.map +1 -1
- package/dist/utils/debug-logger.d.ts +20 -0
- package/dist/utils/debug-logger.d.ts.map +1 -0
- package/dist/utils/debug-logger.js +24 -0
- package/dist/utils/debug-logger.js.map +1 -0
- package/dist/utils/hot-profiler.d.ts +21 -0
- package/dist/utils/hot-profiler.d.ts.map +1 -0
- package/dist/utils/hot-profiler.js +36 -0
- package/dist/utils/hot-profiler.js.map +1 -0
- package/dist/utils/intern.d.ts +11 -0
- package/dist/utils/intern.d.ts.map +1 -0
- package/dist/utils/intern.js +45 -0
- package/dist/utils/intern.js.map +1 -0
- package/dist/utils/logger.d.ts +34 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +115 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/PERFORMANCE.md +330 -0
- package/examples/fluent-builder-prototype.ts +71 -0
- package/examples/quantum-integration-demo.ts +51 -0
- package/package.json +25 -9
package/README.md
CHANGED
|
@@ -2,22 +2,65 @@
|
|
|
2
2
|
|
|
3
3
|
**Quantum Narrative Convergence Engine** - A framework-agnostic TypeScript library for creating interactive narrative experiences with quantum-inspired mechanics.
|
|
4
4
|
|
|
5
|
-
> **🚀 Latest v1.
|
|
5
|
+
> **🚀 Latest v1.4.0 (Adaptive Performance & Quantum Primitives):** Adaptive perf pipeline (dynamic batch sizing, backoff, guarded retry, smoothed p95), expanded telemetry metrics, structured logging, memory optimizations, and first experimental quantum primitives (Entangler, Phase, Measurement). Previous 1.3.x delivered import & persistence foundations.
|
|
6
6
|
|
|
7
7
|
[](https://badge.fury.io/js/qnce-engine)
|
|
8
|
+
[](https://www.npmjs.com/package/qnce-engine)
|
|
8
9
|
[](https://www.typescriptlang.org/)
|
|
9
10
|
[](https://opensource.org/licenses/MIT)
|
|
10
11
|
|
|
11
12
|
> New: Lightweight, privacy-safe telemetry (opt-in). CLI now supports `--telemetry` and `--telemetry-report`, with p50/p95 batch send latency. See the wiki: [Analytics & Telemetry](https://github.com/ByteSower/qnce-engine/blob/main/wiki/Analytics-and-Telemetry.md).
|
|
12
13
|
|
|
14
|
+
## TL;DR Quickstart
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# Install
|
|
18
|
+
npm install qnce-engine
|
|
19
|
+
|
|
20
|
+
# Play the demo story (from this repo)
|
|
21
|
+
node examples/quickstart-demo.js
|
|
22
|
+
|
|
23
|
+
# Live performance monitor (global CLI)
|
|
24
|
+
npm install -g qnce-engine
|
|
25
|
+
qnce-perf dashboard
|
|
26
|
+
qnce-perf stream 1000 | jq '.' # NDJSON streaming (optional)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
New to coding? Start here:
|
|
30
|
+
- Beginner Guide (no code): wiki/Beginner-Guide.md
|
|
31
|
+
- Getting Started: wiki/Getting-Started.md
|
|
32
|
+
|
|
33
|
+
## Documentation & Guides
|
|
34
|
+
|
|
35
|
+
- Getting Started (wiki)
|
|
36
|
+
- Analytics & Telemetry (wiki)
|
|
37
|
+
- Branching Guide (wiki)
|
|
38
|
+
- Performance Tuning (wiki)
|
|
39
|
+
- Error Handling & Debug (docs/ERROR-HANDLING-AND-DEBUG.md)
|
|
40
|
+
- Adapter Lifecycle (docs/ADAPTER-LIFECYCLE.md)
|
|
41
|
+
- Deprecation Policy (docs/DEPRECATION-POLICY.md)
|
|
42
|
+
|
|
43
|
+
## Public Roadmap
|
|
44
|
+
|
|
45
|
+
High-level, non-sensitive roadmap: [`docs/PUBLIC_ROADMAP.md`](./docs/PUBLIC_ROADMAP.md). Internal sprint artifacts are intentionally excluded from the repository for security/privacy.
|
|
46
|
+
|
|
47
|
+
|
|
13
48
|
## Core Concepts
|
|
14
49
|
|
|
15
50
|
- **Superposition:** Multiple narrative outcomes exist simultaneously until a choice is made
|
|
16
51
|
- **Collapse:** Player choices "collapse" the narrative to a specific path, updating state and flags
|
|
17
52
|
- **Entanglement:** Early decisions affect later outcomes, enabling complex, interconnected stories
|
|
18
53
|
|
|
54
|
+
New to coding? See the no-code [Beginner Guide](wiki/Beginner-Guide.md) to create and play a story from the terminal.
|
|
55
|
+
|
|
19
56
|
## ✨ Current Features (v1.3.0)
|
|
20
57
|
|
|
58
|
+
### 🧪 Experimental (Opt-in)
|
|
59
|
+
Early quantum helpers are available behind feature flags. They are off by default and safe to ignore. See the wiki for details and examples:
|
|
60
|
+
|
|
61
|
+
- Experimental APIs: https://github.com/ByteSower/qnce-engine/blob/main/wiki/API-Reference.md#-experimental-opt-in
|
|
62
|
+
- Release Notes (Unreleased): https://github.com/ByteSower/qnce-engine/blob/main/wiki/Release-Notes.md#unreleased
|
|
63
|
+
|
|
21
64
|
### 💾 State Persistence & Checkpoints
|
|
22
65
|
- **Complete save/load system** with data integrity validation
|
|
23
66
|
- **Lightweight checkpoints** for undo/redo functionality
|
|
@@ -53,6 +96,7 @@
|
|
|
53
96
|
- **Background processing** for non-blocking operations
|
|
54
97
|
- **Hot-reload capabilities** with <3.5ms story updates
|
|
55
98
|
- **Comprehensive monitoring** with built-in CLI tools
|
|
99
|
+
- **Adaptive perf pipeline (beta)** with dynamic batch sizing & backoff
|
|
56
100
|
|
|
57
101
|
#### Basic Flag-Based Conditions
|
|
58
102
|
|
|
@@ -215,6 +259,10 @@ engine.clearConditionEvaluator();
|
|
|
215
259
|
- **Expression Caching:** Conditions are compiled once and cached for subsequent evaluations
|
|
216
260
|
- **Safe Evaluation:** All expressions are sanitized to prevent code injection
|
|
217
261
|
- **Minimal Overhead:** Choice filtering adds <1ms to `getAvailableChoices()` calls
|
|
262
|
+
|
|
263
|
+
## Examples
|
|
264
|
+
|
|
265
|
+
- Opt‑in quantum helpers (FeatureFlags + attachQuantumFeatures): `examples/quantum-integration-demo.ts`
|
|
218
266
|
- **Error Isolation:** Invalid conditions don't affect other choices in the same node
|
|
219
267
|
|
|
220
268
|
### ⚡ Performance Infrastructure
|
|
@@ -223,6 +271,7 @@ engine.clearConditionEvaluator();
|
|
|
223
271
|
- **🔥 Hot-Reload:** <3.5ms live story updates with delta patching
|
|
224
272
|
- **📊 Real-time Profiling:** Comprehensive event instrumentation and analysis
|
|
225
273
|
- **🖥️ Live Monitoring:** `qnce-perf` CLI dashboard with performance alerts
|
|
274
|
+
- **🧠 Adaptive Flush (Beta):** Dynamic telemetry/perf batch sizing + rejection backoff for smoother throughput
|
|
226
275
|
|
|
227
276
|
### Performance Dashboard
|
|
228
277
|
```bash
|
|
@@ -234,10 +283,67 @@ qnce-perf live 1000
|
|
|
234
283
|
|
|
235
284
|
# Export performance data
|
|
236
285
|
qnce-perf export > performance-report.json
|
|
286
|
+
|
|
287
|
+
# Stream NDJSON (metrics+thread stats per line)
|
|
288
|
+
qnce-perf stream 1000 | jq '.'
|
|
237
289
|
```
|
|
238
290
|
|
|
239
291
|
**[📚 Complete Performance Guide →](docs/PERFORMANCE.md)**
|
|
240
292
|
|
|
293
|
+
### Adaptive Performance (Beta)
|
|
294
|
+
|
|
295
|
+
The PerfReporter now implements adaptive heuristics to optimize background flush behavior.
|
|
296
|
+
|
|
297
|
+
Key components:
|
|
298
|
+
|
|
299
|
+
1. Exponential Backoff (R2)
|
|
300
|
+
- Triggered after consecutive flush dispatch rejections (e.g. thread pool queue full)
|
|
301
|
+
- Delay doubles each rejection (base 20ms, cap 500ms)
|
|
302
|
+
- Prevents tight retry loops and reduces queue pressure
|
|
303
|
+
|
|
304
|
+
2. Dynamic Batch Sizing (R6)
|
|
305
|
+
- Starts from a configured base batch size
|
|
306
|
+
- Upscales when: backlog is large AND p95 send latency remains low (<25ms or <50ms tiers)
|
|
307
|
+
* Low latency + backlog > 2× base ⇒ scale toward up to ~3× base
|
|
308
|
+
* Low latency + backlog > 4× base ⇒ scale toward up to ~4× base (ceiling)
|
|
309
|
+
- Downscales aggressively when rejection streak ≥2 (divides batch by streak factor, never below 10)
|
|
310
|
+
- Exposed via `lastEffectiveBatchSize` in flush metrics snapshot
|
|
311
|
+
|
|
312
|
+
3. Rejection Rate Metric
|
|
313
|
+
- `rejectionRate` (0–1) = rejectedFlushes / (accepted + rejected)
|
|
314
|
+
- Fast signal for sustained downstream pressure; enables dashboard or future auto-tuning hooks
|
|
315
|
+
|
|
316
|
+
4. Debug Accessor
|
|
317
|
+
- `__getInternalPerfDebug()` includes: `consecutiveRejects`, `backoffDelayMs`, `nextAllowedFlushTime`, `lastEffectiveBatchSize`
|
|
318
|
+
|
|
319
|
+
5. Environment Flag
|
|
320
|
+
- Set `QNCE_SUPPRESS_PERF_WARN=1` to silence repetitive flush failure warnings (e.g. in CI)
|
|
321
|
+
- Set `QNCE_DISABLE_ADAPTIVE_BATCH=1` to force fixed `batchSize` (disables dynamic scaling but keeps backoff)
|
|
322
|
+
|
|
323
|
+
Status & Stability:
|
|
324
|
+
- Marked `@beta` and subject to heuristic tuning (thresholds & scaling formula may evolve)
|
|
325
|
+
- Safe to consume metrics (`rejectionRate`, `lastEffectiveBatchSize`, `adaptiveEnabled`) for observability, not yet for strict alert SLAs
|
|
326
|
+
|
|
327
|
+
Example (inspection inside tests / diagnostics):
|
|
328
|
+
```ts
|
|
329
|
+
import { getPerfReporter } from 'qnce-engine/performance';
|
|
330
|
+
|
|
331
|
+
const reporter = getPerfReporter();
|
|
332
|
+
const snapshot = reporter.getFlushMetrics();
|
|
333
|
+
console.log(snapshot.rejectionRate, snapshot.lastEffectiveBatchSize, snapshot.adaptiveEnabled);
|
|
334
|
+
|
|
335
|
+
// Internal (beta) debug details
|
|
336
|
+
// @ts-expect-error internal accessor
|
|
337
|
+
console.log(reporter.__getInternalPerfDebug());
|
|
338
|
+
|
|
339
|
+
// Force fixed batch sizing (example)
|
|
340
|
+
// (Re-create reporter before use to apply config/env values)
|
|
341
|
+
// const fixed = getPerfReporter({ batchSize: 100, disableAdaptiveBatch: true });
|
|
342
|
+
// Snapshot field `adaptiveEnabled` will be false when dynamic sizing disabled.
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
If you experiment with tuning, please open an issue with: base batch size, average backlog, p95 latency trajectory, and observed rejectionRate.
|
|
346
|
+
|
|
241
347
|
## Installation
|
|
242
348
|
|
|
243
349
|
```bash
|
|
@@ -580,7 +686,7 @@ const engine = createQNCEEngine(storyData, {}, true, {
|
|
|
580
686
|
// Monitor performance in real-time with CLI dashboard
|
|
581
687
|
```
|
|
582
688
|
|
|
583
|
-
**📖 Complete Performance Guide:** [docs/
|
|
689
|
+
**📖 Complete Performance Guide:** [docs/PERFORMANCE.md](docs/PERFORMANCE.md)
|
|
584
690
|
|
|
585
691
|
## Core API
|
|
586
692
|
|
|
@@ -1078,6 +1184,17 @@ npm run build:watch
|
|
|
1078
1184
|
npm run lint
|
|
1079
1185
|
```
|
|
1080
1186
|
|
|
1187
|
+
## 🔒 Security
|
|
1188
|
+
|
|
1189
|
+
QNCE Engine follows security best practices and provides guidance for secure usage:
|
|
1190
|
+
|
|
1191
|
+
- **Vulnerability Reporting**: Please report security vulnerabilities privately via [GitHub Security Advisories](https://github.com/ByteSower/qnce-engine/security/advisories/new)
|
|
1192
|
+
- **Supported Versions**: Security updates are provided for current stable versions (1.3.x) and previous major version (1.2.x)
|
|
1193
|
+
- **Input Validation**: Always validate story data and user inputs from untrusted sources
|
|
1194
|
+
- **State Security**: Use QNCE's built-in integrity validation when loading serialized states
|
|
1195
|
+
|
|
1196
|
+
For detailed security guidelines, see our [Security Policy](SECURITY.md).
|
|
1197
|
+
|
|
1081
1198
|
## License
|
|
1082
1199
|
|
|
1083
1200
|
MIT - See LICENSE file for details.
|
|
@@ -1220,3 +1337,18 @@ try {
|
|
|
1220
1337
|
}
|
|
1221
1338
|
}
|
|
1222
1339
|
```
|
|
1340
|
+
|
|
1341
|
+
## 🧪 Experimental (Opt-in)
|
|
1342
|
+
|
|
1343
|
+
These are off by default and safe to import. Enable with `FeatureFlags` when ready to experiment.
|
|
1344
|
+
|
|
1345
|
+
```ts
|
|
1346
|
+
import { attachQuantumFeatures, FeatureFlags, Phase } from 'qnce-engine';
|
|
1347
|
+
const engine = createQNCEEngine(story);
|
|
1348
|
+
const q = attachQuantumFeatures(engine, new FeatureFlags({ 'quantum.phases': true, 'quantum.entanglement': true }));
|
|
1349
|
+
const alpha = new Phase('alpha', ({ flags }) => !!flags.unlockAlpha);
|
|
1350
|
+
q.isPhaseActive(alpha);
|
|
1351
|
+
q.entangle(e => e.bind('a', 'b', v => Number(v) * 2));
|
|
1352
|
+
```
|
|
1353
|
+
|
|
1354
|
+
APIs: `FeatureFlags`, `Phase`, `Entangler`, `attachQuantumFeatures` (all `@experimental`).
|
|
@@ -11,7 +11,7 @@ export interface StoryAdapter {
|
|
|
11
11
|
detect?(source: unknown): boolean;
|
|
12
12
|
mapIds?(storyData: StoryData, strategy?: 'deterministic' | 'passthrough'): StoryData;
|
|
13
13
|
}
|
|
14
|
-
export interface SaveEnvelope<TPayload =
|
|
14
|
+
export interface SaveEnvelope<TPayload = unknown> {
|
|
15
15
|
version: number;
|
|
16
16
|
storyId: string;
|
|
17
17
|
storyVersion: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/adapters/contracts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5E,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAAC;IACjD,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,aAAa,GAAG,SAAS,CAAC;CACtF;AAGD,MAAM,WAAW,YAAY,CAAC,QAAQ,GAAG,
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/adapters/contracts.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAC5E,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,gBAAgB,CAAC;IACjD,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC;IAClC,MAAM,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,eAAe,GAAG,aAAa,GAAG,SAAS,CAAC;CACtF;AAGD,MAAM,WAAW,YAAY,CAAC,QAAQ,GAAG,OAAO;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,QAAQ,CAAC;CACnB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { StorageAdapter, SerializedState, PersistenceResult, SerializationOptions, LoadOptions } from '../../engine/types';
|
|
2
|
+
export interface FailingAdapterOptions {
|
|
3
|
+
failSaves?: boolean;
|
|
4
|
+
failLoads?: boolean;
|
|
5
|
+
failDeletes?: boolean;
|
|
6
|
+
delayMs?: number;
|
|
7
|
+
}
|
|
8
|
+
/** Adapter that can be configured to fail certain operations */
|
|
9
|
+
export declare class FailingStorageAdapter implements StorageAdapter {
|
|
10
|
+
private opts;
|
|
11
|
+
constructor(opts?: FailingAdapterOptions);
|
|
12
|
+
save(key: string, data: SerializedState, _options?: SerializationOptions): Promise<PersistenceResult>;
|
|
13
|
+
load(key: string, _options?: LoadOptions): Promise<SerializedState | null>;
|
|
14
|
+
delete(key: string): Promise<boolean>;
|
|
15
|
+
list(): Promise<string[]>;
|
|
16
|
+
exists(key: string): Promise<boolean>;
|
|
17
|
+
getStats(): Promise<{
|
|
18
|
+
totalSize: number;
|
|
19
|
+
keyCount: number;
|
|
20
|
+
[k: string]: unknown;
|
|
21
|
+
}>;
|
|
22
|
+
clear(): Promise<boolean>;
|
|
23
|
+
}
|
|
24
|
+
export interface RetryAdapterOptions {
|
|
25
|
+
failCount: number;
|
|
26
|
+
maxAttempts?: number;
|
|
27
|
+
delayMs?: number;
|
|
28
|
+
}
|
|
29
|
+
/** Adapter that fails first N saves then succeeds, to exercise retry logic (future). */
|
|
30
|
+
export declare class FlakySaveAdapter implements StorageAdapter {
|
|
31
|
+
private opts;
|
|
32
|
+
private attempts;
|
|
33
|
+
constructor(opts: RetryAdapterOptions);
|
|
34
|
+
save(key: string, data: SerializedState, _options?: SerializationOptions): Promise<PersistenceResult>;
|
|
35
|
+
load(key: string): Promise<SerializedState | null>;
|
|
36
|
+
delete(key: string): Promise<boolean>;
|
|
37
|
+
list(): Promise<string[]>;
|
|
38
|
+
exists(key: string): Promise<boolean>;
|
|
39
|
+
getStats(): Promise<{
|
|
40
|
+
totalSize: number;
|
|
41
|
+
keyCount: number;
|
|
42
|
+
[k: string]: unknown;
|
|
43
|
+
}>;
|
|
44
|
+
clear(): Promise<boolean>;
|
|
45
|
+
}
|
|
46
|
+
/** Adapter introducing artificial latency without failures. */
|
|
47
|
+
export declare class SlowStorageAdapter implements StorageAdapter {
|
|
48
|
+
private delayMs;
|
|
49
|
+
constructor(delayMs?: number);
|
|
50
|
+
private lag;
|
|
51
|
+
save(key: string, data: SerializedState): Promise<PersistenceResult>;
|
|
52
|
+
load(key: string): Promise<SerializedState | null>;
|
|
53
|
+
delete(key: string): Promise<boolean>;
|
|
54
|
+
list(): Promise<string[]>;
|
|
55
|
+
exists(key: string): Promise<boolean>;
|
|
56
|
+
getStats(): Promise<{
|
|
57
|
+
totalSize: number;
|
|
58
|
+
keyCount: number;
|
|
59
|
+
[k: string]: unknown;
|
|
60
|
+
}>;
|
|
61
|
+
clear(): Promise<boolean>;
|
|
62
|
+
}
|
|
63
|
+
export interface TimeoutAdapterOptions {
|
|
64
|
+
timeoutFailCount: number;
|
|
65
|
+
resolveDelayMs?: number;
|
|
66
|
+
timeoutDelayMs?: number;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Adapter that simulates network timeouts for the first N save attempts by rejecting.
|
|
70
|
+
* After those attempts it succeeds (optionally with a delay). Useful to exercise retry logic and telemetry attempts field.
|
|
71
|
+
*/
|
|
72
|
+
export declare class TimeoutSaveAdapter implements StorageAdapter {
|
|
73
|
+
private opts;
|
|
74
|
+
private attempt;
|
|
75
|
+
constructor(opts: TimeoutAdapterOptions);
|
|
76
|
+
private delay;
|
|
77
|
+
save(key: string, data: SerializedState): Promise<PersistenceResult>;
|
|
78
|
+
load(key: string): Promise<SerializedState | null>;
|
|
79
|
+
delete(key: string): Promise<boolean>;
|
|
80
|
+
list(): Promise<string[]>;
|
|
81
|
+
exists(key: string): Promise<boolean>;
|
|
82
|
+
getStats(): Promise<{
|
|
83
|
+
totalSize: number;
|
|
84
|
+
keyCount: number;
|
|
85
|
+
[k: string]: unknown;
|
|
86
|
+
}>;
|
|
87
|
+
clear(): Promise<boolean>;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=MockAdapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MockAdapters.d.ts","sourceRoot":"","sources":["../../../src/adapters/storage/MockAdapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TimeoutSaveAdapter = exports.SlowStorageAdapter = exports.FlakySaveAdapter = exports.FailingStorageAdapter = void 0;
|
|
4
|
+
/** Simple in-memory backing store shared across mock adapters */
|
|
5
|
+
const store = new Map();
|
|
6
|
+
/** Adapter that can be configured to fail certain operations */
|
|
7
|
+
class FailingStorageAdapter {
|
|
8
|
+
opts;
|
|
9
|
+
constructor(opts = {}) {
|
|
10
|
+
this.opts = opts;
|
|
11
|
+
}
|
|
12
|
+
async save(key, data, _options) {
|
|
13
|
+
if (this.opts.delayMs)
|
|
14
|
+
await new Promise(r => setTimeout(r, this.opts.delayMs));
|
|
15
|
+
if (this.opts.failSaves)
|
|
16
|
+
return { success: false, error: 'mock-save-failed' };
|
|
17
|
+
store.set(key, data);
|
|
18
|
+
return { success: true };
|
|
19
|
+
}
|
|
20
|
+
async load(key, _options) {
|
|
21
|
+
if (this.opts.delayMs)
|
|
22
|
+
await new Promise(r => setTimeout(r, this.opts.delayMs));
|
|
23
|
+
if (this.opts.failLoads)
|
|
24
|
+
throw new Error('mock-load-failed');
|
|
25
|
+
return store.get(key) ?? null;
|
|
26
|
+
}
|
|
27
|
+
async delete(key) {
|
|
28
|
+
if (this.opts.failDeletes)
|
|
29
|
+
return false;
|
|
30
|
+
return store.delete(key);
|
|
31
|
+
}
|
|
32
|
+
async list() { return [...store.keys()]; }
|
|
33
|
+
async exists(key) { return store.has(key); }
|
|
34
|
+
async getStats() { return { totalSize: store.size, keyCount: store.size }; }
|
|
35
|
+
async clear() { store.clear(); return true; }
|
|
36
|
+
}
|
|
37
|
+
exports.FailingStorageAdapter = FailingStorageAdapter;
|
|
38
|
+
/** Adapter that fails first N saves then succeeds, to exercise retry logic (future). */
|
|
39
|
+
class FlakySaveAdapter {
|
|
40
|
+
opts;
|
|
41
|
+
attempts = 0;
|
|
42
|
+
constructor(opts) {
|
|
43
|
+
this.opts = opts;
|
|
44
|
+
}
|
|
45
|
+
async save(key, data, _options) {
|
|
46
|
+
if (this.opts.delayMs)
|
|
47
|
+
await new Promise(r => setTimeout(r, this.opts.delayMs));
|
|
48
|
+
this.attempts++;
|
|
49
|
+
if (this.attempts <= this.opts.failCount)
|
|
50
|
+
return { success: false, error: 'transient-error' };
|
|
51
|
+
store.set(key, data);
|
|
52
|
+
return { success: true }; // attempts tracked internally; tests inspect adapter state if needed
|
|
53
|
+
}
|
|
54
|
+
async load(key) { return store.get(key) ?? null; }
|
|
55
|
+
async delete(key) { return store.delete(key); }
|
|
56
|
+
async list() { return [...store.keys()]; }
|
|
57
|
+
async exists(key) { return store.has(key); }
|
|
58
|
+
async getStats() { return { totalSize: store.size, keyCount: store.size }; }
|
|
59
|
+
async clear() { store.clear(); return true; }
|
|
60
|
+
}
|
|
61
|
+
exports.FlakySaveAdapter = FlakySaveAdapter;
|
|
62
|
+
/** Adapter introducing artificial latency without failures. */
|
|
63
|
+
class SlowStorageAdapter {
|
|
64
|
+
delayMs;
|
|
65
|
+
constructor(delayMs = 25) {
|
|
66
|
+
this.delayMs = delayMs;
|
|
67
|
+
}
|
|
68
|
+
async lag() { await new Promise(r => setTimeout(r, this.delayMs)); }
|
|
69
|
+
async save(key, data) { await this.lag(); store.set(key, data); return { success: true }; }
|
|
70
|
+
async load(key) { await this.lag(); return store.get(key) ?? null; }
|
|
71
|
+
async delete(key) { await this.lag(); return store.delete(key); }
|
|
72
|
+
async list() { await this.lag(); return [...store.keys()]; }
|
|
73
|
+
async exists(key) { await this.lag(); return store.has(key); }
|
|
74
|
+
async getStats() { return { totalSize: store.size, keyCount: store.size }; }
|
|
75
|
+
async clear() { await this.lag(); store.clear(); return true; }
|
|
76
|
+
}
|
|
77
|
+
exports.SlowStorageAdapter = SlowStorageAdapter;
|
|
78
|
+
/**
|
|
79
|
+
* Adapter that simulates network timeouts for the first N save attempts by rejecting.
|
|
80
|
+
* After those attempts it succeeds (optionally with a delay). Useful to exercise retry logic and telemetry attempts field.
|
|
81
|
+
*/
|
|
82
|
+
class TimeoutSaveAdapter {
|
|
83
|
+
opts;
|
|
84
|
+
attempt = 0;
|
|
85
|
+
constructor(opts) {
|
|
86
|
+
this.opts = opts;
|
|
87
|
+
}
|
|
88
|
+
async delay(ms) { if (ms)
|
|
89
|
+
await new Promise(r => setTimeout(r, ms)); }
|
|
90
|
+
async save(key, data) {
|
|
91
|
+
this.attempt++;
|
|
92
|
+
if (this.attempt <= this.opts.timeoutFailCount) {
|
|
93
|
+
await this.delay(this.opts.timeoutDelayMs);
|
|
94
|
+
// Simulate a network timeout by throwing (engine converts to failed PersistenceResult)
|
|
95
|
+
throw new Error('timeout');
|
|
96
|
+
}
|
|
97
|
+
await this.delay(this.opts.resolveDelayMs);
|
|
98
|
+
store.set(key, data);
|
|
99
|
+
return { success: true };
|
|
100
|
+
}
|
|
101
|
+
async load(key) { return store.get(key) ?? null; }
|
|
102
|
+
async delete(key) { return store.delete(key); }
|
|
103
|
+
async list() { return [...store.keys()]; }
|
|
104
|
+
async exists(key) { return store.has(key); }
|
|
105
|
+
async getStats() { return { totalSize: store.size, keyCount: store.size }; }
|
|
106
|
+
async clear() { store.clear(); return true; }
|
|
107
|
+
}
|
|
108
|
+
exports.TimeoutSaveAdapter = TimeoutSaveAdapter;
|
|
109
|
+
//# sourceMappingURL=MockAdapters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MockAdapters.js","sourceRoot":"","sources":["../../../src/adapters/storage/MockAdapters.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import type { StoryData } from '../../engine/core';
|
|
|
3
3
|
import type { ValidationResult } from '../../engine/validation';
|
|
4
4
|
export declare class CustomJSONAdapter implements StoryAdapter {
|
|
5
5
|
load(source: string | object, options?: AdapterOptions): Promise<StoryData>;
|
|
6
|
-
validate(
|
|
6
|
+
validate(): ValidationResult;
|
|
7
7
|
detect(source: unknown): boolean;
|
|
8
8
|
}
|
|
9
9
|
export default CustomJSONAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomJSONAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/CustomJSONAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,qBAAa,iBAAkB,YAAW,YAAY;IAC9C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"CustomJSONAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/CustomJSONAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,qBAAa,iBAAkB,YAAW,YAAY;IAC9C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;IA6FjF,QAAQ,IAAI,gBAAgB;IAI5B,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO;CAYjC;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -9,7 +9,7 @@ class CustomJSONAdapter {
|
|
|
9
9
|
if (!data || typeof data !== 'object')
|
|
10
10
|
throw new Error('Invalid story source');
|
|
11
11
|
const initialNodeId = data.initialNodeId || 'start';
|
|
12
|
-
const nodes = data.nodes
|
|
12
|
+
const nodes = data.nodes ?? [];
|
|
13
13
|
if (!Array.isArray(nodes))
|
|
14
14
|
throw new Error('Invalid nodes array');
|
|
15
15
|
const normalized = {
|
|
@@ -17,10 +17,14 @@ class CustomJSONAdapter {
|
|
|
17
17
|
nodes: nodes.map((n) => ({
|
|
18
18
|
id: String(n.id),
|
|
19
19
|
text: String(n.text ?? ''),
|
|
20
|
-
meta: n.meta && typeof n.meta === 'object'
|
|
21
|
-
? {
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
meta: n && typeof n === 'object' && n.meta && typeof n.meta === 'object'
|
|
21
|
+
? (() => {
|
|
22
|
+
const meta = n.meta;
|
|
23
|
+
const tags = meta.tags;
|
|
24
|
+
return {
|
|
25
|
+
tags: Array.isArray(tags) ? tags.map((t) => String(t)) : undefined,
|
|
26
|
+
};
|
|
27
|
+
})()
|
|
24
28
|
: undefined,
|
|
25
29
|
choices: Array.isArray(n.choices)
|
|
26
30
|
? n.choices.map((c) => ({
|
|
@@ -54,25 +58,27 @@ class CustomJSONAdapter {
|
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
else {
|
|
57
|
-
// Lenient mode:
|
|
61
|
+
// Lenient mode: ignore unknown keys silently
|
|
58
62
|
const allowedNodeKeys = new Set(['id', 'text', 'choices', 'meta']);
|
|
59
63
|
const allowedChoiceKeys = new Set([
|
|
60
64
|
'text', 'nextNodeId', 'flagEffects', 'flagRequirements', 'timeRequirements', 'inventoryRequirements', 'enabled', 'condition'
|
|
61
65
|
]);
|
|
62
66
|
for (const n of nodes) {
|
|
63
|
-
for (const k of Object.keys(n))
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
for (const k of Object.keys(n)) {
|
|
68
|
+
// ignore unknown keys
|
|
69
|
+
void (allowedNodeKeys.has(k));
|
|
70
|
+
}
|
|
71
|
+
for (const c of n.choices || []) {
|
|
72
|
+
for (const ck of Object.keys(c)) {
|
|
73
|
+
// ignore unknown keys
|
|
74
|
+
void (allowedChoiceKeys.has(ck));
|
|
75
|
+
}
|
|
70
76
|
}
|
|
71
77
|
}
|
|
72
78
|
}
|
|
73
79
|
return normalized;
|
|
74
80
|
}
|
|
75
|
-
validate(
|
|
81
|
+
validate() {
|
|
76
82
|
return { isValid: true };
|
|
77
83
|
}
|
|
78
84
|
detect(source) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomJSONAdapter.js","sourceRoot":"","sources":["../../../src/adapters/story/CustomJSONAdapter.ts"],"names":[],"mappings":";AAAA,4BAA4B;AAC5B,uFAAuF;;;AAMvF,MAAa,iBAAiB;IAC5B,KAAK,CAAC,IAAI,CAAC,MAAuB,EAAE,OAAwB;QAC1D,MAAM,IAAI,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAEtE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"CustomJSONAdapter.js","sourceRoot":"","sources":["../../../src/adapters/story/CustomJSONAdapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import type { StoryData } from '../../engine/core';
|
|
|
3
3
|
import type { ValidationResult } from '../../engine/validation';
|
|
4
4
|
export declare class InkAdapter implements StoryAdapter {
|
|
5
5
|
load(source: string | object, options?: AdapterOptions): Promise<StoryData>;
|
|
6
|
-
validate(
|
|
6
|
+
validate(): ValidationResult;
|
|
7
7
|
detect(source: unknown): boolean;
|
|
8
8
|
}
|
|
9
9
|
export default InkAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/InkAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,qBAAa,UAAW,YAAW,YAAY;IACvC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"InkAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/InkAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,qBAAa,UAAW,YAAW,YAAY;IACvC,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;IAuBjF,QAAQ,IAAI,gBAAgB;IAE5B,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO;CAKjC;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -9,23 +9,20 @@ class InkAdapter {
|
|
|
9
9
|
const obj = typeof source === 'string' ? JSON.parse(source) : source;
|
|
10
10
|
if (!obj || typeof obj !== 'object')
|
|
11
11
|
throw new Error('Invalid Ink JSON');
|
|
12
|
-
|
|
13
|
-
const knots = obj.knots || {};
|
|
12
|
+
const knots = (obj.knots) || {};
|
|
14
13
|
const idPrefix = options?.idPrefix ?? '';
|
|
15
|
-
|
|
16
|
-
console.warn('[QNCE] Ink JSON appears complex; using minimal adapter. Pass experimentalInk to attempt richer import.');
|
|
17
|
-
}
|
|
14
|
+
// Silently proceed in non-experimental mode; no console noise in library code
|
|
18
15
|
const nodes = Object.keys(knots).map((k) => ({
|
|
19
16
|
id: `${idPrefix}${k}`,
|
|
20
|
-
text: String(knots[k]
|
|
21
|
-
choices: Array.isArray(knots[k]
|
|
22
|
-
? knots[k].choices.map((c) => ({ text: String(c.text ?? ''), nextNodeId: `${idPrefix}${c.target}` }))
|
|
17
|
+
text: String(knots[k]?.text ?? ''),
|
|
18
|
+
choices: Array.isArray(knots[k]?.choices)
|
|
19
|
+
? knots[k].choices.map((c) => ({ text: String(c.text ?? ''), nextNodeId: `${idPrefix}${String(c.target ?? '')}` }))
|
|
23
20
|
: [],
|
|
24
21
|
}));
|
|
25
22
|
const initialNodeId = `${idPrefix}${(obj.start ?? Object.keys(knots)[0] ?? 'start')}`;
|
|
26
23
|
return { initialNodeId, nodes };
|
|
27
24
|
}
|
|
28
|
-
validate(
|
|
25
|
+
validate() { return { isValid: true }; }
|
|
29
26
|
detect(source) {
|
|
30
27
|
let obj = source;
|
|
31
28
|
if (typeof source === 'string') {
|
|
@@ -36,7 +33,7 @@ class InkAdapter {
|
|
|
36
33
|
return false;
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
|
-
return !!obj && typeof obj === 'object' && (
|
|
36
|
+
return !!obj && typeof obj === 'object' && ('knots' in obj || 'inkVersion' in obj);
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
exports.InkAdapter = InkAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InkAdapter.js","sourceRoot":"","sources":["../../../src/adapters/story/InkAdapter.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,sGAAsG;;;AAMtG,yEAAyE;AACzE,MAAa,UAAU;IACrB,KAAK,CAAC,IAAI,CAAC,MAAuB,EAAE,OAAwB;
|
|
1
|
+
{"version":3,"file":"InkAdapter.js","sourceRoot":"","sources":["../../../src/adapters/story/InkAdapter.ts"],"names":[],"mappings":";AAAA,oDAAoD;AACpD,sGAAsG;;;AAMtG,yEAAyE;AACzE,MAAa,UAAU;IACrB,KAAK,CAAC,IAAI,CAAC,MAAuB,EAAE,OAAwB;QAC5D,MAAM,GAAG,GAA4B,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAkC,CAAC;QACzH,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAI3E,MAAM,KAAK,GAAG,CAAE,GAAwC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;QACpE,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,EAAE,CAAC;QAEzC,8EAA8E;QAE9E,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3C,EAAE,EAAE,GAAG,QAAQ,GAAG,CAAC,EAAE;YACrB,IAAI,EAAE,MAAM,CAAE,KAAK,CAAC,CAAC,CAAsB,EAAE,IAAI,IAAI,EAAE,CAAC;YACxD,OAAO,EAAE,KAAK,CAAC,OAAO,CAAE,KAAK,CAAC,CAAC,CAAsB,EAAE,OAAO,CAAC;gBAC7D,CAAC,CAAG,KAAK,CAAC,CAAC,CAAU,CAAC,OAAuD,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,UAAU,EAAE,GAAG,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;gBAC9K,CAAC,CAAC,EAAE;SACP,CAAC,CAAC,CAAC;QAEJ,MAAM,aAAa,GAAG,GAAG,QAAQ,GAAG,CAAG,GAA2B,CAAC,KAAgB,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,EAAE,CAAC;QAC3H,OAAO,EAAE,aAAa,EAAE,KAAK,EAAe,CAAC;IAC/C,CAAC;IAED,QAAQ,KAAuB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;IAE1D,MAAM,CAAC,MAAe;QACtB,IAAI,GAAG,GAAY,MAAM,CAAC;QACxB,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAAC,IAAI,CAAC;gBAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC;gBAAC,OAAO,KAAK,CAAC;YAAC,CAAC;QAAC,CAAC;QAC/F,OAAO,CAAC,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,OAAO,IAAI,GAAG,IAAI,YAAY,IAAI,GAAG,CAAC,CAAC;IACnF,CAAC;CACF;AA/BD,gCA+BC;AAED,kBAAe,UAAU,CAAC"}
|
|
@@ -3,7 +3,7 @@ import type { StoryData } from '../../engine/core';
|
|
|
3
3
|
import type { ValidationResult } from '../../engine/validation';
|
|
4
4
|
export declare class TwisonAdapter implements StoryAdapter {
|
|
5
5
|
load(source: string | object, options?: AdapterOptions): Promise<StoryData>;
|
|
6
|
-
validate(
|
|
6
|
+
validate(): ValidationResult;
|
|
7
7
|
detect(source: unknown): boolean;
|
|
8
8
|
}
|
|
9
9
|
export default TwisonAdapter;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TwisonAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/TwisonAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAiBhE,qBAAa,aAAc,YAAW,YAAY;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;IA4CjF,QAAQ,
|
|
1
|
+
{"version":3,"file":"TwisonAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/story/TwisonAdapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAiBhE,qBAAa,aAAc,YAAW,YAAY;IAC1C,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;IA4CjF,QAAQ,IAAI,gBAAgB;IAI5B,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO;CAOjC;AAED,eAAe,aAAa,CAAC"}
|